diff --git a/.abi-check/6.29.1/postgres.symbols.ignore b/.abi-check/6.29.1/postgres.symbols.ignore new file mode 100644 index 000000000000..aa4c33e2be25 --- /dev/null +++ b/.abi-check/6.29.1/postgres.symbols.ignore @@ -0,0 +1 @@ +ConfigureNamesBool_gp diff --git a/.abi-check/6.29.2/postgres.symbols.ignore b/.abi-check/6.29.2/postgres.symbols.ignore new file mode 100644 index 000000000000..aa4c33e2be25 --- /dev/null +++ b/.abi-check/6.29.2/postgres.symbols.ignore @@ -0,0 +1 @@ +ConfigureNamesBool_gp diff --git a/.github/CODE_OF_CONDUCT.md b/.github/CODE_OF_CONDUCT.md index c90a6f5a1253..5eaf063d68d9 100644 --- a/.github/CODE_OF_CONDUCT.md +++ b/.github/CODE_OF_CONDUCT.md @@ -1,50 +1,45 @@ -# Code of Conduct +# Greengage DB Community Code of Conduct -## Intro +Greengage DB is an open community project. Every Greengage DB user or developer is responsible for making the community a place where people want to come back. We expect all community members to maintain professional ethics and communicate respectfully and politely. -Standing on the shoulders of the giants means not only leveraging the code base of the most successful open source relational database (PostgreSQL) but also taking a page out of one of the most successful open source governance bodies: Apache Software Foundation (ASF). Greengage Database developer community has adopted not only the Apache License but also the following code of conduct heavily borrowing from an ASF’s: +## Community Development Principles -This code of conduct applies to all spaces that are associated with the participation in the Greengage Database open source project, including chat, all public and private mailing lists, issue trackers, wikis, blogs, Twitter, and any other communication channel used by our community. A code of conduct which is specific to in-person events (ie., conferences, meetups, etc.) is expected to be a superset of this document covering additional principles put forward by the organizers of the event(s) and landlords of the space where the event is held. +In developing code, documentation, and any other products of intellectual work, we are guided by principles that are important for the development of the community. -We expect this code of conduct to be honored by everyone who participates in the Greengage Database community formally or informally, or claims any affiliation with the project, in any activities and especially when representing the Greengage Database project, in any role. +**Collaboration** -This code is not exhaustive or complete. It serves to distil our common understanding of a collaborative, shared environment and goals. We expect it to be followed in spirit as much as in the letter so that it can enrich all of us and the technical communities in which we participate. +Anyone can join the Greengage DB community and make a contribution. -## Specific guidelines +**Equality** -We strive to: -1. **Be open** We invite anyone to participate in our community. We preferably use public methods of communication for project-related messages, unless discussing something sensitive. This applies to messages for help or project-related support, too; not only is a public support request much more likely to result in an answer to a question, it also makes sure that any inadvertent mistakes made by people answering will be more easily detected and corrected. -2. **Be empathetic**, welcoming, friendly, and patient. We work together to resolve conflict, assume good intentions, and do our best to act in an empathetic fashion. We may all experience some frustration from time to time, but we do not allow frustration to turn into a personal attack. A community where people feel uncomfortable or threatened is not a productive one. We should be respectful when dealing with other community members as well as with people outside our community. -3. **Be collaborative**. Our work will be used by other people, and in turn will depend on the work of others. When we make something for the benefit of the project, we are willing to explain to others how it works, so that they can build on the work to make it even better. Any decision we make will affect users and colleagues, and we take those consequences seriously when making decisions. -4. **Be inquisitive**. Nobody knows everything! Asking questions early avoids many problems later, so questions are encouraged, though they may be directed to the appropriate forum. Those who are asked should be responsive and helpful, within the context of our shared goal of improving Greengage Database project code. -5. **Be careful in the words that we choose**. Whether we are participating as professionals or volunteers, we value professionalism in all interactions, and take responsibility for our own speech. Be kind to others. Do not insult or put down other participants. Harassment and other exclusionary behaviour are not acceptable. This includes, but is not limited to: - * Violent threats or language directed against another person. - * Sexist, racist, or otherwise discriminatory jokes and language. - * Posting sexually explicit or violent material. - * Posting (or threatening to post) other people's personally identifying information ("doxing"). - * Sharing private content, such as emails sent privately or non-publicly, or unlogged forums such as IRC channel history. - * Personal insults, especially those using racist or sexist terms. - * Unwelcome sexual attention. - * Excessive or unnecessary profanity. - * Repeated harassment of others. In general, if someone asks you to stop, then stop. - * Advocating for, or encouraging, any of the above behaviour. -6. **Be concise**. Keep in mind that what you write once will be read by hundreds of persons. Writing a short email means people can understand the conversation as efficiently as possible. Short emails should always strive to be empathetic, welcoming, friendly and patient. When a long explanation is necessary, consider adding a summary. - Try to bring new ideas to a conversation so that each mail adds something unique to the thread, keeping in mind that the rest of the thread still contains the other messages with arguments that have already been made. - Try to stay on topic, especially in discussions that are already fairly large. -7. **Step down considerately**. Members of every project come and go. When somebody leaves or disengages from the project they should tell people they are leaving and take the proper steps to ensure that others can pick up where they left off. In doing so, they should remain respectful of those who continue to participate in the project and should not misrepresent the project's goals or achievements. Likewise, community members should respect any individual's choice to leave the project. +The contribution of each community member will be assessed equally, based on its objective significance for the project. -## Diversity statement +**Opportunities** -Greengage Database project welcomes and encourages participation by everyone. We are committed to being a community that everyone feels good about joining. Although we may not be able to satisfy everyone, we will always work to treat everyone well. +Community members who contribute to Greengage DB can influence the direction of the product's development. -No matter how you identify yourself or how others perceive you: we welcome you. Though no list can hope to be comprehensive, we explicitly honour diversity in: age, culture, ethnicity, genotype, gender identity or expression, language, national origin, neurotype, phenotype, political beliefs, profession, race, religion, sexual orientation, socioeconomic status, subculture and technical ability. +**Availability** -Though we welcome people fluent in all languages, Greengage Database project development is conducted in English. +The project code will be distributed under an open license for community members anywhere in the world. -Standards for behaviour in this community are detailed in the Code of Conduct above. We expect participants in our community to meet these standards in all their interactions and to help others to do so as well. +## Code of Conduct in Action -## Reporting guidelines +This code of conduct applies to all available channels of interaction between community members, including comments on code or documentation, the project's social media, and online and offline events that are partially or fully dedicated to Greengage DB. -While this code of conduct should be adhered to by participants, we recognize that sometimes people may have a bad day, or be unaware of some of the guidelines in this code of conduct. When that happens, you may reply to them and point out this code of conduct. Such messages may be in public or in private, whatever is most appropriate. However, regardless of whether the message is public or not, it should still adhere to the relevant parts of this code of conduct; in particular, it should not be abusive or disrespectful. +Every member of the Greengage DB community is expected to adhere to the project’s code of conduct, especially when speaking on behalf of Greengage DB in the public space. +We encourage everyone to be interested in Greengage DB, regardless of their track record or formal qualifications. This does not negate the important procedures for code and documentation quality, but it does require respectful and polite treatment. -If you believe someone is violating this code of conduct, you may reply to them and point out this code of conduct. Assume good faith; it is more likely that participants are unaware of their bad behaviour than that they intentionally try to degrade the quality of the discussion. Should there be difficulties in dealing with the situation, you may report your compliance issues in confidence to coc@greengagedb.org. This will go to an individual who is entrusted with your report. +The Greengage DB project exists thanks to the voluntary contributions of its members. Some of them may leave the project over time, and this decision should be respected in the same way as their initial involvement. We expect this code of conduct to be followed in the event of parting with the project, and the departing community member is supposed to treat those who remain with respect. + +## Appropriate Conduct + +No personal characteristics can serve as grounds for refusing to work for the benefit of the Greengage DB project or belittling your contribution to it. This code of conduct considers any attacks on a person unacceptable. These are the basic principles of communication in the community. + +Unacceptable behavior is any threat to use violence, damage social or professional reputation, expressed to an individual or a group of people. Threats to damage the Greengage DB project or its reputation or the implementation of such threats are also a violation of this code of conduct. Harassment of any kind and violation of the basic principles of communication are not tolerated in the Greengage DB community. + +In the event of receiving a warning about inappropriate behavior, it is necessary to immediately stop it. Subsequent violations of the Code of Conduct will serve as grounds for taking restrictive measures against the violator, up to and including exclusion from the community. + +## Reporting + +In many cases, simply sending a link to this code of conduct will be enough to maintain a good community culture. If you see a discussion where the code may potentially be violated, proactively send a link to it. +In some cases, violations may require issuing warnings and other restrictive measures. In this case, please contact us at **code@greengagedb.org**. diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000000..aca16a9294a0 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,84 @@ +name: Bug Report +description: Create a report to help us improve GreengageDB +title: "[Bug] " +labels: ["bug"] +assignees: [] + +body: + - type: textarea + id: problem_description + attributes: + label: "Describe the problem" + description: "Please describe the issue you observed, and any steps we can take to reproduce it" + placeholder: "Describe the problem you encountered..." + validations: + required: true + + - type: textarea + id: reproduction_steps + attributes: + label: "How to reproduce" + description: "Steps to reproduce the behavior" + placeholder: | + 1. + 2. + 3. + ... + validations: + required: true + + - type: textarea + id: expected_behavior + attributes: + label: "Expected behavior" + description: "A clear and concise description of what you expected to happen" + placeholder: "Describe what you expected to happen..." + validations: + required: true + + - type: textarea + id: additional_data + attributes: + label: "Additional data" + description: | + If the problem is SQL-related, include a copy of the SQL query and the schema. + + If a segment in your cluster encountered a fatal error, supply the contents of the log directory (at minimum of the affected segment(s), but preferably all segments). + + Note that log files can contain confidential information. + placeholder: | + SQL Query: + Schema: + Log files: + ... + + - type: input + id: environment_greengagedb + attributes: + label: "GreengageDB version" + description: "What version of GreengageDB are you using?" + validations: + required: true + + - type: input + id: environment_os + attributes: + label: "Server OS" + description: "What operating system is the server running on?" + placeholder: "e.g. Linux/Distrib version" + validations: + required: true + + - type: input + id: environment_client + attributes: + label: "Client application" + description: "What client application are you using?" + placeholder: "e.g. psql, JDBC, pxf, ..." + + - type: textarea + id: additional_context + attributes: + label: "Additional context" + description: "What was the impact? Add any other context about the problem here" + placeholder: "Add any other relevant context about the problem..." \ No newline at end of file diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000000..f61d70e28ade --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,17 @@ +--- +name: Feature request +about: Suggest an idea for Greengage project +title: "[Feature]" +labels: '' +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. + +**Describe the solution** +A clear and concise description of what you want to happen. + +**Additional context** +Add any other context about the feature request, user stories or examples of usage. diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 86450215b42a..08d466d88685 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -37,6 +37,82 @@ operating systems: DockerHub. Runs for push to `main` (retags to `latest`) and tags (uses tag like `6.28.2`) after build. +## Release Workflow + +A separate workflow `Greengage release` handles the uploading of Debian package +to GitHub releases. It is triggered when a release is published and uses a +composite action to manage package deployment. + +### Key Features + +- **Triggers:** `release: [published]` - Runs when a release is published, +including re-publishing. +- **Concurrency:** Uses the same concurrency group as the CI workflow +(`Greengage CI-${{ github.ref }}`) to ensure proper sequencing and prevent race +conditions. +- **Cache-based Artifacts:** Restores built packages from cache using the +commit SHA as the key, rather than downloading artifacts from previous jobs. +- **Manual Recovery:** If the cache is missing, the workflow checks the status +of the last build for the tag and provides clear instructions for manual +intervention. It does not automatically trigger builds to avoid infinite loops. +- **Safe Uploads:** Uploads packages with fixed naming patterns and optional +overwrite (`clobber` flag). + +### Behavior + +1. **Normal Flow (Cache Available):** Restores packages from cache, renames +them to the pattern `${PACKAGE_NAME}${VERSION}.${EXT}`, and uploads to the +release. +2. **Cache Miss Scenarios:** + - **No previous build or previous build successful:** Provides instructions + to manually trigger the CI build, then restart the release workflow. + - **Previous build failed:** Reports the failure with a link to the failed + run and requires manual fixing before retrying. + +The release workflow is designed to be robust and provide clear feedback when +issues occur, ensuring that releases are always consistent and reliable. + +## SQL Dump Workflow + +A separate workflow `Greengage SQL Dump` is responsible for generating SQL dump +artifacts after the main CI process completes successfully. It is triggered +automatically upon the completion of the `Greengage CI` workflow. + +### Key Features + +- **Triggers:** `workflow_run: workflows: ["Greengage CI"], types: [completed]` +- **Branch Targeting:** Runs only for the `main` and `7.x` branches. +- **Version Detection:** Automatically determines the database version (6 or 7) +based on the triggering branch. +- **Artifact Creation:** Executes regression tests with the `dump_db: "true"` +parameter to generate a SQL dump archive, which is then uploaded as a workflow +artifact. +- **Controlled Execution:** Since the main CI workflow runs on `main` and `7.x` +branches only for push events (which occur after final merge of a PR), SQL dump +are generated exclusively for verified, approved patches after they are merged +into the main branches. +- **Artifact Retention:** The generated SQL dump artifact is retained 90 days +after the last download. Each new run of the `behave tests gpexpand` workflow +(which consumes this artifact as a consumer) resets this retention period to +90 days when it downloads the artifact. + +### Behavior + +1. **Triggering:** Automatically starts after the `Greengage CI` workflow +finishes on the `main` or `7.x` branch. +2. **Preparation:** Configures Docker storage on the runner to utilize +`/mnt/docker` for increased disk space. +3. **Version Mapping:** Maps the branch name (`main` -> version 6, `7.x` -> +version 7) to select the correct Docker image for testing. +4. **Dump Generation:** Runs the regression test suite using the reusable +action with the `dump_db` option enabled, which creates a +`*_postgres_sqldump.tar` file. +5. **Artifact Upload:** Uploads the generated SQL dump archive as a named +artifact (e.g., `sqldump_ggdb7_ubuntu`) to the workflow run. + +This workflow ensures that a current database schema dump is available as an +artifact following successful CI runs on the primary branches `main` and `7.x`. + ## Configuration The workflow is parameterized to support flexibility: diff --git a/.github/workflows/greengage-abi-tests.yml b/.github/workflows/greengage-abi-tests.yml index 3a72e300a72e..7a0ce0a50a3a 100644 --- a/.github/workflows/greengage-abi-tests.yml +++ b/.github/workflows/greengage-abi-tests.yml @@ -8,22 +8,7 @@ concurrency: on: workflow_dispatch: pull_request: - paths: - - 'concourse/scripts/**' - - 'src/**' - - '.github/workflows/**' - - '.github/scripts/**' - - '.abi-check/**' - - push: - branches: - - 6X_STABLE - paths: - - 'concourse/scripts/**' - - 'src/**' - - '.github/workflows/**' - - '.github/scripts/**' - - '.abi-check/**' + branches: ['**'] env: # workaround required for checkout@v3, https://github.com/actions/checkout/issues/1590 diff --git a/.github/workflows/greengage-ci.yml b/.github/workflows/greengage-ci.yml index 7e5fbbc7c41b..b3d307d6c4b4 100644 --- a/.github/workflows/greengage-ci.yml +++ b/.github/workflows/greengage-ci.yml @@ -6,7 +6,7 @@ on: branches: ['main'] # Trigger on push to main (after merged PR) tags: ['6.*'] # Trigger on tags for versioned releases pull_request: - branches: ['*'] # Trigger on pull requests for all branches + branches: ['**'] # Trigger on pull requests for all branches # Concurrency control to cancel previous runs on new push to same PR/branch concurrency: @@ -18,12 +18,12 @@ jobs: strategy: fail-fast: true # Stop on any failure in the matrix matrix: - target_os: [ubuntu] #, centos] + target_os: [ubuntu] permissions: contents: read # Explicit for default behavior packages: write # Required for GHCR access actions: write # Required for artifact upload - uses: greengagedb/greengage-ci/.github/workflows/greengage-reusable-build.yml@v1 + uses: greengagedb/greengage-ci/.github/workflows/greengage-reusable-build.yml@v19 with: version: 6 target_os: ${{ matrix.target_os }} @@ -36,12 +36,12 @@ jobs: strategy: fail-fast: true matrix: - target_os: [ubuntu] #, centos] + target_os: [ubuntu] permissions: contents: read # Explicit for default behavior packages: read # Explicit for GHCR access clarity actions: write # Required for artifact upload - uses: greengagedb/greengage-ci/.github/workflows/greengage-reusable-tests-behave.yml@v1 + uses: greengagedb/greengage-ci/.github/workflows/greengage-reusable-tests-behave.yml@v24 with: version: 6 target_os: ${{ matrix.target_os }} @@ -54,12 +54,12 @@ jobs: strategy: fail-fast: true matrix: - target_os: [ubuntu] #, centos] + target_os: [ubuntu] permissions: contents: read # Explicit for default behavior packages: read # Explicit for GHCR access clarity actions: write # Required for artifact upload - uses: greengagedb/greengage-ci/.github/workflows/greengage-reusable-tests-regression.yml@v1 + uses: greengagedb/greengage-ci/.github/workflows/greengage-reusable-tests-regression.yml@v19 with: version: 6 target_os: ${{ matrix.target_os }} @@ -72,12 +72,12 @@ jobs: strategy: fail-fast: true matrix: - target_os: [ubuntu] #, centos] + target_os: [ubuntu] permissions: contents: read # Explicit for default behavior packages: read # Explicit for GHCR access clarity actions: write # Required for artifact upload - uses: greengagedb/greengage-ci/.github/workflows/greengage-reusable-tests-orca.yml@v1 + uses: greengagedb/greengage-ci/.github/workflows/greengage-reusable-tests-orca.yml@v19 with: version: 6 target_os: ${{ matrix.target_os }} @@ -90,12 +90,12 @@ jobs: strategy: fail-fast: true matrix: - target_os: [ubuntu] #, centos] + target_os: [ubuntu] permissions: contents: read # Explicit for default behavior packages: read # Explicit for GHCR access clarity actions: write # Required for artifact upload - uses: greengagedb/greengage-ci/.github/workflows/greengage-reusable-tests-resgroup.yml@v1 + uses: greengagedb/greengage-ci/.github/workflows/greengage-reusable-tests-resgroup.yml@v23 with: version: 6 target_os: ${{ matrix.target_os }} @@ -108,12 +108,12 @@ jobs: strategy: fail-fast: true matrix: - target_os: [ubuntu] #, centos] + target_os: [ubuntu] permissions: contents: read # Explicit for default behavior packages: write # Required for GHCR access actions: write # Required for artifact upload - uses: greengagedb/greengage-ci/.github/workflows/greengage-reusable-upload.yml@v1 + uses: greengagedb/greengage-ci/.github/workflows/greengage-reusable-upload.yml@v21 with: version: 6 target_os: ${{ matrix.target_os }} @@ -121,3 +121,22 @@ jobs: ghcr_token: ${{ secrets.GITHUB_TOKEN }} DOCKERHUB_TOKEN: ${{ secrets.DOCKERHUB_TOKEN }} DOCKERHUB_USERNAME: ${{ secrets.DOCKERHUB_USERNAME }} + + # Rebuild prod-redy version without debug extensions and pack it to deb + package: + needs: build # For push (main or tags) + strategy: + fail-fast: false + matrix: + target_os: [ubuntu] + permissions: + contents: read # Explicit for default behavior + packages: write # Required for GHCR access + actions: write # Required for artifact upload + uses: greengagedb/greengage-ci/.github/workflows/greengage-reusable-package.yml@v10 + with: + version: 6 + target_os: ${{ matrix.target_os }} + test_docker: ubuntu:22.04 # Docker Image (e.g., ubuntu:22.04, ubuntu:noble) for deploy test. Skip if empty + secrets: + ghcr_token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/greengage-release.yml b/.github/workflows/greengage-release.yml new file mode 100644 index 000000000000..083834935c8e --- /dev/null +++ b/.github/workflows/greengage-release.yml @@ -0,0 +1,27 @@ +# Release creation workflow +name: Greengage release + +on: + release: + types: [released] + +jobs: + upload-to-release: + strategy: + fail-fast: false + matrix: + include: + - version: 6 + extensions: deb ddeb + artifact_name: deb-packages + runs-on: ubuntu-latest + permissions: + contents: write + actions: read + steps: + - name: Upload packages to release + uses: greengagedb/greengage-ci/.github/actions/upload-pkgs-to-release@v10 + with: + version: ${{ matrix.version }} + extensions: ${{ matrix.extensions }} + artifact_name: ${{ matrix.artifact_name }} diff --git a/.github/workflows/greengage-sql-dump.yml b/.github/workflows/greengage-sql-dump.yml new file mode 100644 index 000000000000..9c069189d0dd --- /dev/null +++ b/.github/workflows/greengage-sql-dump.yml @@ -0,0 +1,83 @@ +# .github/workflows/greengage-sql-dump.yml +name: Greengage SQL Dump + +on: + workflow_run: + workflows: ["Greengage CI"] + types: [completed] + branches: + - main + - 7.x + +jobs: + create-sql-dump-regression: + runs-on: ubuntu-latest + timeout-minutes: 180 + if: | + github.event.workflow_run.event == 'push' && + github.event.workflow_run.conclusion == 'success' && + !startsWith(github.event.workflow_run.head_branch, 'refs/tags/') + strategy: + fail-fast: true + matrix: + target_os: [ubuntu] + permissions: + contents: read # Explicit for default behavior + packages: read # Explicit for GHCR access clarity + actions: write # Required for cache and artifact upload + steps: + - name: Display trigger information + env: + RUN_NAME: ${{ github.event.workflow_run.name }} + RUN_ID: ${{ github.event.workflow_run.id }} + RUN_HEAD_BRANCH: ${{ github.event.workflow_run.head_branch }} + RUN_HEAD_SHA: ${{ github.event.workflow_run.head_sha }} + RUN_HEAD_COMMIT_MESSAGE: ${{ github.event.workflow_run.head_commit.message }} + RUN_HEAD_COMMIT_AUTHOR: ${{ github.event.workflow_run.head_commit.author.name }} + run: | + cat << EOF + ================== Workflow Trigger Information ================== + Triggered by: ${RUN_NAME} (#${RUN_ID}) + Target branch: ${RUN_HEAD_BRANCH} + Source commit: ${RUN_HEAD_SHA} + Commit message: ${RUN_HEAD_COMMIT_MESSAGE} + + Author: ${RUN_HEAD_COMMIT_AUTHOR} + ================================================================== + EOF + + - name: Maximize disk space + uses: greengagedb/greengage-ci/.github/actions/maximize-disk-space@v19 + + - name: Determine version from branch + id: version + env: + BRANCH: ${{ github.event.workflow_run.head_branch }} + run: | + case "$BRANCH" in + main) + echo "version=6" >> $GITHUB_OUTPUT + ;; + 7.x) + echo "version=7" >> $GITHUB_OUTPUT + ;; + *) + echo "Unsupported branch: $BRANCH" + exit 1 + ;; + esac + + - name: Create SQL Dump via regression tests + uses: greengagedb/greengage-ci/.github/actions/tests/regression@v16 + with: + image: ghcr.io/${{ github.repository }}/ggdb${{ steps.version.outputs.version }}_${{ matrix.target_os }}:${{ github.event.workflow_run.head_sha }} + optimizer: postgres + target_os: ${{ matrix.target_os }} + dump_db: "true" + + - name: Upload SQL Dump + uses: actions/upload-artifact@v4 + with: + name: sqldump_ggdb${{ steps.version.outputs.version }}_${{ matrix.target_os }} + path: /mnt/logs/${{ matrix.target_os }}_postgres_sqldump.tar + if-no-files-found: error diff --git a/.gitignore b/.gitignore index 8f979721c160..799206a138da 100644 --- a/.gitignore +++ b/.gitignore @@ -53,6 +53,10 @@ GTAGS lib*dll.def lib*.pc compile_commands.json +**/debian/* +!**/debian/co* +!**/debian/lint* +!**/debian/rules # Local excludes in root directory /GNUmakefile @@ -65,3 +69,4 @@ compile_commands.json /Debug/ /Release/ /CMakeLists.txt +/Package/ diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d3b512ee0dc8..a557b7874723 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,69 +1,77 @@ # Contributing -Greengage is maintained by a core team of developers with commit rights to the [main Greengage repository](https://github.com/GreengageDB/greengage) on GitHub. At the same time, we are very eager to receive contributions from anybody in the wider Greengage community. This section covers all you need to know if you want to see your code or documentation changes be added to Greengage and appear in the future releases. +Greengage was launched and is maintained by a team of independent contributors to Greenplum. Currently, we own the [Greengage DB repository on GitHub](https://github.com/GreengageDB/greengage), appoint the members of the architectural committee and perform other work related to the organizational process in addition to software development. However, great open source projects cannot exist and last long without a strong community, **so community contributions to Greengage DB are very welcome**. In this section, you’ll find initial guidance on how to contribute to Greengage and links to additional resources that will help you get your code released as part of Greengage. ## Getting started -Greengage is developed on GitHub, and anybody wishing to contribute to it will have to [have a GitHub account](https://github.com/signup) and be familiar with [Git tools and workflow](https://wiki.postgresql.org/wiki/Working_with_Git). +To contribute to Greengage, you will need a [GitHub account](https://github.com/signup). If you haven’t used Git before, find a time to familiarize yourself with [Git tooling and workflow](https://wiki.postgresql.org/wiki/Working_with_Git) before you start. -Once you have your GitHub account, [fork](https://github.com/GreengageDB/greengage/fork) this repository so that you can have your private copy to start hacking on and to use as source of pull requests. +A private copy of the Greengage repository is required to introduce changes. To create one, [fork](https://github.com/GreengageDB/greengage/fork) our repository and work on it. Having changed something, you will be able to pull request, and someone from the architectural committee will review your contribution. To get more information on the review process, see the “Patch review” section of this document. -## Licensing of Greengage contributions +## Contributions licensing -If the contribution you're submitting is original work, you can assume that we will release it as part of an overall Greengage release available to the downstream consumers under the Apache License, Version 2.0. However, in addition to that, we may also decide to release it under a different license (such as PostgreSQL License to the upstream consumers that require it. A typical example here would be we upstreaming your contribution back to PostgreSQL community (which can be done either verbatim or your contribution being upstreamed as part of the larger changeset). +As the original author of the code, you can expect that your contribution will be released and licensed under Apache License, v. 2.0. Additionally, certain contributions valuable to the broader PostgreSQL community might be released under the PostgreSQL license. If your patch is beneficial for upstream PostgreSQL, we can offer it for review individually or include it with a set of changes. -If the contribution you're submitting is NOT original work you have to indicate the name of the license and also make sure that it is similar in terms to the Apache License 2.0. Apache Software Foundation maintains a list of these licenses under [Category A](https://www.apache.org/legal/resolved.html#category-a). In addition to that, you may be required to make proper attribution in the [NOTICE file](https://github.com/GreengageDB/greengage/blob/adb-6.x/NOTICE) file similar to [these examples](https://github.com/GreengageDB/greengage/blob/adb-6.x/NOTICE#L278). +If you are NOT the author of the code you are contributing to Greengage, please make sure you take proper licensing into account. Check the third-party license terms for similarity to the Apache License 2.0. Similar licenses are listed on the Apache Software Foundation website under [Category A](https://www.apache.org/legal/resolved.html#category-a). Note that some of these licenses require making proper attribution in the [NOTICE file](https://github.com/GreengageDB/greengage/blob/main/NOTICE) (see examples [here](https://github.com/GreengageDB/greengage/blob/main/NOTICE#L335)). -Finally, keep in mind that it is NEVER a good idea to remove licensing headers from the work that is not your original one. Even if you are using parts of the file that originally had a licensing header at the top you should err on the side of preserving it. As always, if you are not quite sure about the licensing implications of your contributions, feel free to reach out to us. +Do NOT remove licensing headers from any piece of work done by a third party. Even partial usage of someone else’s work may assume licensing implications. Please give the original author credit for their work by keeping the licensing headers ## Coding guidelines -Your chances of getting feedback and seeing your code merged into the project greatly depend on how granular your changes are. If you happen to have a bigger change in mind, we highly recommend creating an issue first and sharing your proposal with us before you spend a lot of time writing code. Even when your proposal gets validated by the community, we still recommend doing the actual work as a series of small, self-contained commits. This makes the reviewer's job much easier and increases the timeliness of feedback. +Before introducing a major change, it is always good to validate your idea with the architectural committee. [Create an issue on GitHub](https://github.com/GreengageDB/greengage/issues) and explain what’s on your mind before you spend hours writing code. We expect that while explaining your proposal to the committee, you’ll be specific about the approaches you are going to use and reasons behind using them. -When it comes to C and C++ parts of Greengage, we try to follow [PostgreSQL Coding Conventions](https://www.postgresql.org/docs/devel/source.html). In addition to that: +Submitting changes in small portions is the best strategy, even if you are working on a massive feature. Smaller patches can be reviewed within a week while large changesets require more time for being checked by the committee members. To get timely feedback and see your code merged into the project faster, stick to small, granular pull requests. This is also a way to show the reviewers that their job is valued and respected. - * For C and perl code, please run pgindent if necessary as specified in [README.gpdb](/src/tools/pgindent/README.gpdb). - * All Python code must pass [Pylint](https://www.pylint.org/). - * All Go code must be formatted according to [gofmt](https://golang.org/cmd/gofmt/). +To help you with the process of coding and describing your pull requests for reviewers, we have created a separate [Pull Request Submission Guidelines](https://greengagedb.org/en/blog/contributing.html) document. Please refer to it when in doubt and contact us if the document provides no answer. -We recommend using `git diff --color` when reviewing your changes so that you don't have any spurious whitespace issues in the code that you submit. +Here we mention just a few best practices we expect you to apply while contributing to Greengage DB. For detailed recommendations, please refer to Greengage DB’s [Pull Request Submission Guidelines](https://greengagedb.org/en/blog/contributing.html). -All new functionality that is contributed to Greengage should be covered by regression tests that are contributed alongside it. If you are uncertain on how to test or document your work, please raise the question in a PR and the developer community will do its best to help you. + - Follow [PostgreSQL Coding Conventions](https://www.postgresql.org/docs/devel/source.html) when writing C/C++ code for Greengage. + - Run **pgindent** for C and Perl code as per [README.gpdb](https://github.com/GreengageDB/greengage/blob/main/src/tools/pgindent/README.gpdb). + - Use [Pylint](https://www.pylint.org/) for all Python code. + - Format all Golang code in accordance with [gofmt](https://golang.org/cmd/gofmt/). -At the very minimum you should always be running `make installcheck-world` to make sure that you're not breaking anything. +Use git `diff --color` as you review your changes to avoid spurious whitespace issues in the submitted code. -## Changes applicable to upstream PostgreSQL +Regression tests are mandatory for every new feature that you contribute to Greengage. All tests covering new functionality should also be contributed to the project. Check [Pull Request Submission Guidelines](https://greengagedb.org/en/blog/contributing.html) to make sure that all tests are placed in the right folders within the project repository. If you need guidance related to testing or documenting your contributions, please explicitly include your questions in the pull request, and the architectural committee members will address them during patch review. -If the change you're working on touches functionality that is common between PostgreSQL and Greengage, you may be asked to forward-port it to PostgreSQL. This is not only so that we keep reducing the delta between the two projects, but also so that any change that is relevant to PostgreSQL can benefit from a much broader review of the upstream PostgreSQL community. In general, it is a good idea to keep both code bases handy so you can be sure whether your changes may need to be forward-ported. +At the very minimum you should always make sure that all local test runs are successful before submitting a pull request (PR) to the main repository. + +## PostgreSQL-related changes + +We prefer to get the changes related to the shared functionality of PostgreSQL and Greengage DB reviewed by the members of both communities. The larger Postgres community has more resources to help improve your patches, that’s why we may request submitting your PostgreSQL-related changes to Postgres upstream to leverage that power and reduce the delta between Greengage DB and PostgreSQL. If your contribution is likely to be forward-ported to PostgreSQL, please refer to PostgreSQL code base where appropriate. ## Patch submission -Once you are ready to share your work with the Greengage core team and the rest of the Greengage community, you should push all the commits to a branch in your own repository forked from our one and [send us a pull request](https://help.github.com/articles/about-pull-requests/). +We expect that in the repository you forked from the Greengage DB one you’ll create a branch **other than main** that will contain the changes you prepared to share with us and the rest of the community. Then [send us a pull request](https://help.github.com/articles/about-pull-requests/). -We require all pull requests to be submitted against the main branch (clearly stating if the change needs to be back-ported to STABLE branches). If the change is ONLY applicable to given STABLE branch, you may decide to submit your pull requests against an active STABLE release branch. +Do keep in mind that your patch review will slow down + - if you do not follow [Pull Request Submission Guidelines](https://greengagedb.org/en/blog/contributing.html) + - if tests are missing or copied to incorrect folders -Things which slow down patch approval - - missing to accompany tests (or reproducible steps at minimum) - - submitting the patch against STABLE branch where the fix also applies to main branch +## Patch review -## Validation checks and CI +All submitted patches are subject to review by the architectural committee members. The time required for review depends of the volume and complexity of the submitted patch: + - Up to 1 week for small/easy patches; + - Up to 4 weeks for patches of medium complexity + - Up to 8 weeks for patches of extra size or complexity. -Once you submit your pull request, you will immediately see a number of validation checks performed by our automated CI pipelines. If any of these checks fails, you will need to update your pull request to take care of the issue. Pull requests with failed validation checks are very unlikely to receive any further peer review from the community members. +Architectural committee reserves the right to decline patches without review if they introduce no valuable changes and/or contain garbage code. -If you cannot figure out why a certain validation check failed, feel free to ask us in the pull request. +Each contributed patch should get approvals from two architectural committee members before being merged into the project. Both pull request description and code will be thoroughly examined to ensure high quality and security. -## Patch review +The first reviewer might initiate a discussion proposing further improvements / changes to your pull request. You might also be asked to explain certain solutions and approaches applied as part of the proposed changeset. Discussions around pull requests along with any other communication in the Greengage DB project are covered by the Code of Conduct. Once the patch is accepted by the first reviewer, the second reviewer steps up to double-check your contribution and possibly provide a final commentary. -A submitted pull request with passing validation checks is assumed to be available for peer review. Peer review is the process that ensures that contributions to Greengage are of high quality and align well with the road map and community expectations. Every member of the Greengage community is encouraged to review pull requests and provide feedback. Since you don't have to be a core team member to be able to do that, we recommend following a stream of pull reviews to anybody who's interested in becoming a long-term contributor to Greengage. As [Linus would say](https://en.wikipedia.org/wiki/Linus's_Law) "given enough eyeballs, all bugs are shallow". +Note that the members of committee volunteer to review patches. Therefore, their availability may be limited, and reasonable delays are possible. In many cases, being proactive and asking for feedback may speed up the review process. -One outcome of the peer review could be a consensus that you need to modify your pull request in certain ways. GitHub allows you to push additional commits into a branch from which a pull request was sent. Those additional commits will be then visible to all of the reviewers. +After basic review (including feature relevancy, absence of malicious changes, etc.) and approve to run CI pipelines, the processes of patch review begins. -A peer review converges when it receives at least one +1 and no -1s votes from the participants. At that point you should expect one of the core team members to pull your changes into the project. +## Validation checks and CI -Greengage prides itself on being a collaborative, consensus-driven environment. We do not believe in vetoes and any -1 vote casted as part of the peer review has to have a detailed technical explanation of what's wrong with the change. +Your patch will undergo a series of validation checks from our automated CI pipeline. If any of them fails, you will need to change the patch you contributed so as to pass this check next time. -At any time during the patch review, you may experience delays based on the availability of reviewers and core team members. Please be patient. That being said, don't get discouraged either. If you're not getting expected feedback for a few days add a comment asking for updates on the pull request itself. +While the process is generally intuitive and enables you understand what exactly was wrong, do not hesitate to ask your reviewers for help if you don’t know why your approved patch was not merged. Use the pull request discussion to contact them. ## Direct commits to the repository -On occasion you will see core team members committing directly to the repository without going through the pull request workflow. This is reserved for small changes only and the rule of thumb we use is this: if the change touches any functionality that may result in a test failure, then it has to go through a pull request workflow. If, on the other hand, the change is in the non-functional part of the code base (such as fixing a typo inside of a comment block) core team members can decide to just commit to the repository directly. +Members of the architectural committee may sometimes commit to the repository directly, without submitting pull requests. Usually they do so to introduce minor changes (i.e. typo corrections), all major code contributions need to be submitted as pull requests and go through checks. diff --git a/README.CentOS.bash b/README.CentOS.bash index cd0aacabc261..bee249e73f57 100755 --- a/README.CentOS.bash +++ b/README.CentOS.bash @@ -14,17 +14,23 @@ sudo yum install -y \ libcurl-devel \ libevent-devel \ libkadm5 \ - libyaml-devel \ + libtool \ + libuuid-devel \ + libuv-devel \ libxml2-devel \ + libxslt-devel \ + libyaml-devel \ libzstd-devel \ + libzstd-static \ + net-tools \ + openldap-devel \ + openssl \ openssl-devel \ + pam-devel \ + perl-Env \ perl-ExtUtils-Embed \ python-devel \ python-pip \ readline-devel \ xerces-c-devel \ zlib-devel - -sudo pip install conan -sudo pip install -r python-dependencies.txt -sudo pip install -r python-developer-dependencies.txt diff --git a/README.Rhel-Rocky.bash b/README.Rhel-Rocky.bash new file mode 100755 index 000000000000..866c646e08fb --- /dev/null +++ b/README.Rhel-Rocky.bash @@ -0,0 +1,45 @@ +#!/bin/bash + +sudo dnf -y update +sudo dnf -y install epel-release +sudo dnf -y install 'dnf-command(config-manager)' +sudo dnf config-manager --set-enabled devel +sudo dnf makecache + +sudo dnf -y install\ + apr-devel \ + bison \ + bzip2-devel \ + cmake3 \ + flex \ + gcc \ + gcc-c++ \ + iproute \ + krb5-devel \ + libcurl-devel \ + libevent-devel \ + libicu \ + libkadm5 \ + libtool \ + libuuid-devel \ + libuv-devel \ + libxml2-devel \ + libxslt-devel \ + libyaml-devel \ + net-tools \ + openldap-devel \ + openssl \ + openssl-devel \ + pam-devel \ + perl-Env \ + perl-ExtUtils-Embed \ + perl-IPC-Run \ + perl-JSON \ + perl-Test-Base \ + procps-ng \ + python2-devel \ + python2-pip \ + readline-devel \ + snappy-devel \ + xerces-c-devel \ + zlib-devel diff --git a/README.linux.md b/README.linux.md index fb5e754faa1c..806589bb4ff7 100644 --- a/README.linux.md +++ b/README.linux.md @@ -1,63 +1,35 @@ -## For CentOS: - -- Install Dependencies +## For CentOS 7: +- Install dependencies using README.CentOS.bash script: ```bash ./README.CentOS.bash ``` + Note: CentOS 7 is EOL — configure `yum` to use a valid repo (e.g., `vault.centos.org`) before installing dependencies. -- If you want to link cmake3 to cmake, run: +## For RHEL/Rocky 8: +- Install dependencies using README.Rhel-Rocky.bash script: ```bash - sudo ln -sf /usr/bin/cmake3 /usr/local/bin/cmake + ./README.Rhel-Rocky.bash ``` -- Make sure that you add `/usr/local/lib` and `/usr/local/lib64` to -`/etc/ld.so.conf`, then run command `ldconfig`. - -- If you want to install and use gcc-6 by default, run: - +- Build and install zstd with static library, e.g.: ```bash - sudo yum install -y centos-release-scl - sudo yum install -y devtoolset-6-toolchain - echo 'source scl_source enable devtoolset-6' >> ~/.bashrc + cd /tmp + curl -LO https://github.com/facebook/zstd/releases/download/v1.4.4/zstd-1.4.4.tar.gz + tar -xf zstd-1.4.4.tar.gz + cd zstd-1.4.4 + make -j$(nproc) + sudo make install PREFIX=/usr/local ``` -## For RHEL: - -- Install Development Tools. - - For RHEL 8: Install `Development Tools`: - - ```bash - sudo yum group install -y "Development Tools" - ``` - - - For RHEL versions (< 8.0): Install `devtoolset-7`: - - ```bash - sudo yum-config-manager --enable rhui-REGION-rhel-server-rhscl - sudo yum install -y devtoolset-7-toolchain - ``` - -- Install dependencies using README.CentOS.bash script. - - For RHEL 8: Execute additional steps before running README.CentOS.bash script. - - Note: Make sure installation of `Development Tools` includes `git` and `make` else install these tools manually. - - ```bash - sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-8.noarch.rpm - sed -i -e 's/python-devel /python2-devel /' -e 's/python-pip/python2-pip/' -e 's/sudo pip/sudo pip2/' README.CentOS.bash - sed -i '/xerces-c-devel/d' README.CentOS.bash - sudo ln -s /usr/bin/python2.7 /usr/bin/python - ``` - - - Install dependencies using README.CentOS.bash script. +- Create symbolic link to Python 2 in `/usr/bin`: - ```bash - ./README.CentOS.bash - ``` + ```bash + sudo ln -s python2 /usr/bin/python + ``` -## For Ubuntu (versions 20.04 or 22.04): +## For Ubuntu (22.04): - Install dependencies using README.ubuntu.bash script: ```bash @@ -85,19 +57,7 @@ ## Common Platform Tasks: -1. Create gpadmin and setup ssh keys - - Either use: - - ```bash - # Requires gpdb clone to be named gpdb_src - gpdb_src/concourse/scripts/setup_gpadmin_user.bash - ``` - to create the gpadmin user and set up keys, - - OR - - manually create ssh keys so you can do ssh localhost without a password, e.g., +1. Setup SSH keys so you can run ssh localhost without a password, e.g., ```bash ssh-keygen @@ -108,7 +68,7 @@ 2. Verify that you can ssh to your machine name without a password ```bash - ssh # e.g., ssh briarwood + ssh `hostname` # e.g., ssh briarwood ``` 3. Set up your system configuration: @@ -150,7 +110,3 @@ su - $USER # Apply settings ``` -5. Make sure that you download yaml and psutil as submodules. To do this, use `git clone --recurse-submodules` when downloading the source code. If you want to update the submodules, run: - ```bash - git submodule update --init --recursive --force - ``` diff --git a/README.md b/README.md index 16eb0e7e2b0d..5ba48b9693a8 100644 --- a/README.md +++ b/README.md @@ -37,56 +37,84 @@ Follow [these macOS steps](README.macOS.md) for getting your system ready for GP ### Installing dependencies (for Linux developers) Follow [appropriate linux steps](README.linux.md) for getting your system ready for GPDB +### Downloading submodules +Make sure that you download submodules. To do this, use `git clone --recurse-submodules` +when downloading the source code. If you want to update the submodules, run: +```bash +git submodule update --init --recursive --force +``` + ### Build the database +The recommended way to build the database is to use build system located in the gpAux +directory, which is also used for CI testing and building packages. + +To create optimized release build, use the following: + +``` +make GPROOT=~/build PARALLEL_MAKE_OPTS=-j8 dist -C gpAux +``` +where `GPROOT` defines the base installation directory. + +By default, the target installation directory is `greengage-db-devel`. +You can override this directory name by setting the `GPDIR` option. +For example, to install into `/usr/local/gpdb`: `make GPROOT=/usr/local GPDIR=gpdb dist -C gpAux`. + +To run regression tests, a debug build with debug extensions is required. It can be built using the following command: + +``` +make GPROOT=~/build PARALLEL_MAKE_OPTS=-j8 devel -C gpAux ``` -# Configure build environment to install at /usr/local/gpdb -./configure --with-perl --with-python --with-libxml --with-gssapi --prefix=/usr/local/gpdb -# Compile and install -make -j8 -make -j8 install +Load the greengage environment into your current shell: -# Bring in greengage environment into your running shell -source /usr/local/gpdb/greengage_path.sh +``` +source ~/build/greengage-db-devel/greengage_path.sh +``` -# Start demo cluster +Start demo cluster: + +``` make create-demo-cluster -# (gpdemo-env.sh contains __PGPORT__ and __MASTER_DATA_DIRECTORY__ values) +``` + +To use the demo cluster, source the environment variables from gpdemo-env.sh, which contains +__PGPORT__ and __MASTER_DATA_DIRECTORY__ values: + +``` source gpAux/gpdemo/gpdemo-env.sh ``` The directory, the TCP ports, the number of segments, and the existence of standbys for segments and coordinator for the demo cluster can be changed -on the fly. +when starting the demo cluster. Instead of `make create-demo-cluster`, consider: ``` DATADIRS=/tmp/gpdb-cluster PORT_BASE=5555 NUM_PRIMARY_MIRROR_PAIRS=1 WITH_MIRRORS=false make create-demo-cluster ``` -The TCP port for the regression test can be changed on the fly: - +If you want to clean all generated files: ``` -PGPORT=5555 make installcheck-world +make distclean ``` -To turn GPORCA off and use Postgres planner for query optimization: +## Running tests + +* By default, tests use the GPORCA optimizer: ``` -set optimizer=off; +make installcheck-world ``` -If you want to clean all generated files +* To turn GPORCA off and use the Postgres planner for query optimization: ``` -make distclean +PGOPTIONS='-c optimizer=off' make installcheck-world ``` -## Running tests - -* The default regression tests +* The TCP port for the regression test can be changed: ``` -make installcheck-world +PGPORT=5555 make installcheck-world ``` * The top-level target __installcheck-world__ will run all regression @@ -112,17 +140,15 @@ make installcheck-world ## Alternative Configurations +Internally, the configure script is used to adapt the build system to the characteristics of the host machine. For finer control over the components that are built, configuration options must be specified explicitly. The configuration options in effect are recorded in the file config.log and may be inspected with the following command: +``` +head config.log +``` + ### Building GPDB without GPORCA Currently, GPDB is built with GPORCA by default. If you want to build GPDB without GPORCA, configure requires `--disable-orca` flag to be set. -``` -# Clean environment -make distclean - -# Configure build environment to install at /usr/local/gpdb -./configure --disable-orca --with-perl --with-python --with-libxml --prefix=/usr/local/gpdb -``` ### Building GPDB with gpperfmon enabled diff --git a/README.ubuntu.bash b/README.ubuntu.bash index b740a108eb8d..0285e641ff8d 100755 --- a/README.ubuntu.bash +++ b/README.ubuntu.bash @@ -1,16 +1,24 @@ #!/bin/bash - +# Some packages, for example KRB5, not installing properly without this option +export DEBIAN_FRONTEND=noninteractive apt-get update apt-get install -y \ bison \ + build-essential \ cmake \ curl \ + debhelper \ + devscripts \ + dh-python \ + fakeroot \ flex \ g++ \ gcc \ git \ iproute2 \ iputils-ping \ + krb5-admin-server \ + krb5-kdc \ libapr1-dev \ libaprutil1-dev \ libbz2-dev \ @@ -34,7 +42,11 @@ apt-get install -y \ openssh-client \ openssh-server \ pkg-config \ + protobuf-compiler \ + python-pip \ python2 \ python2-dev \ + python3-dev \ rsync \ + sudo \ zlib1g-dev diff --git a/ci/Dockerfile.ubuntu b/ci/Dockerfile.ubuntu index eb7b658ac788..4cda6fd7d52b 100644 --- a/ci/Dockerfile.ubuntu +++ b/ci/Dockerfile.ubuntu @@ -1,4 +1,6 @@ -FROM ubuntu:22.04 as base +FROM ubuntu:22.04 AS base +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +WORKDIR /home/gpadmin ARG UBUNTU_MAIN_MIRROR=http://archive.ubuntu.com/ubuntu ARG UBUNTU_UPDATES_MIRROR=http://archive.ubuntu.com/ubuntu @@ -12,6 +14,7 @@ ARG adb_python3=https://downloads.adsw.io/ADB/6.27.1_arenadata56/ubuntu/22.04/co ARG adb_python3_bin=/opt/adb6-python3.9/bin/python3 COPY README.ubuntu.bash ./ +COPY gpMgmt/bin/gpload_test/pytest_requirement.txt ./ RUN set -eux; \ sed -i \ -e "s|http://archive.ubuntu.com/ubuntu/ jammy |${UBUNTU_MAIN_MIRROR}/ jammy |g" \ @@ -26,7 +29,7 @@ RUN set -eux; \ rm ./*.deb; \ ln -s python2 /usr/bin/python; \ # Install pg_bsd_indent used by pgindent utility - wget https://ftp.postgresql.org/pub/dev/pg_bsd_indent-1.3.tar.gz -O - | tar -xzf -; \ + wget --progress=dot:giga --no-hsts https://ftp.postgresql.org/pub/dev/pg_bsd_indent-1.3.tar.gz -O - | tar -xzf -; \ make install -C pg_bsd_indent; \ rm -r pg_bsd_indent; \ # The en_US.UTF-8 locale is needed to run GPDB @@ -35,46 +38,47 @@ RUN set -eux; \ mkdir /run/sshd; \ # Alter precedence in favor of IPv4 during resolving echo 'precedence ::ffff:0:0/96 100' >> /etc/gai.conf; \ -# Packages for tests - DEBIAN_FRONTEND=noninteractive \ - apt install -y krb5-kdc krb5-admin-server fakeroot sudo python-pip \ - openjdk-11-jdk protobuf-compiler; \ # Install allure-behave for behave tests - pip2 install allure-behave==2.4.0; \ - pip2 cache purge; \ + pip2 install --no-cache-dir allure-behave==2.4.0; \ +# Install pytest for gpload test + python -m pip install --no-cache-dir -r pytest_requirement.txt; \ + rm pytest_requirement.txt; \ + # pip2 cache purge; \ # ADCC extension dependencies $adb_python3_bin -m pip install protobuf==3.20.0; \ - $adb_python3_bin -m pip cache purge + $adb_python3_bin -m pip cache purge; \ +# Cleanup to reduce image size + apt-get clean; \ + rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* /var/cache/man/ -WORKDIR /home/gpadmin +ENV LANG=en_US.UTF-8 ENV CONFIGURE_FLAGS="--enable-debug-extensions --with-gssapi --enable-cassert --enable-debug --enable-depend" -FROM base as build +FROM base AS build COPY . gpdb_src -RUN mkdir /home/gpadmin/bin_gpdb +RUN mkdir bin_gpdb -ENV TARGET_OS=ubuntu -ENV OUTPUT_ARTIFACT_DIR=bin_gpdb +ENV TARGET_OS=ubuntu \ + OUTPUT_ARTIFACT_DIR=bin_gpdb \ # Use python3.9 to compile into GPDB's plpython3u -ENV PYTHON3=$adb_python3_bin + PYTHON3=$adb_python3_bin # Compile with running mocking tests -RUN bash /home/gpadmin/gpdb_src/concourse/scripts/compile_gpdb.bash +RUN gpdb_src/concourse/scripts/compile_gpdb.bash -FROM base as code +FROM base AS code # Use --exclude, when it will be available in stable syntax. COPY . gpdb_src RUN rm -rf gpdb_src/.git/ -FROM base as test -COPY --from=code /home/gpadmin/gpdb_src gpdb_src -COPY --from=build /home/gpadmin/bin_gpdb /home/gpadmin/bin_gpdb +FROM base AS test + +COPY --from=code /home/gpadmin/gpdb_src gpdb_src +COPY --from=build /home/gpadmin/bin_gpdb bin_gpdb +COPY --from=build /home/gpadmin/gpdb_src/VERSION gpdb_src # Install entab used by pgindent utility. # This should be done using gpdb sources. RUN make -C gpdb_src/src/tools/entab install clean - -# Volume for tests output -VOLUME /home/gpadmin/gpdb_src/src/test diff --git a/ci/docker-compose.yaml b/ci/docker-compose.yaml index 550e24b28d24..f2386f3f4232 100644 --- a/ci/docker-compose.yaml +++ b/ci/docker-compose.yaml @@ -1,64 +1,57 @@ ---- +x-common-service: &common-service + image: "${IMAGE}" + privileged: true + sysctls: + kernel.sem: 500 1024000 200 4096 + init: true + ulimits: + nofile: 65535 + entrypoint: > + sleep infinity -version: "3" services: cdw: - image: "${IMAGE}" + <<: *common-service working_dir: /home/gpadmin hostname: cdw volumes: - - "$PWD/ssh_keys/id_rsa:/home/gpadmin/.ssh/id_rsa" - - "$PWD/ssh_keys/id_rsa.pub:/home/gpadmin/.ssh/id_rsa.pub" - - "$PWD/allure-results:/tmp/allure-results" - - "$PWD/logs_cdw:/logs" - privileged: true - sysctls: - kernel.sem: 500 1024000 200 4096 - init: true - ulimits: - nofile: 65535 - entrypoint: > - sleep infinity + - ${PWD}/allure-results:/tmp/allure-results + - ${PWD}/sqldump/dump.sql:/home/gpadmin/sqldump/dump.sql + - ${PWD}/ssh_keys:/home/gpadmin/.ssh.src + - ${PWD}/logs_cdw:/logs sdw1: - image: "${IMAGE}" - privileged: true + <<: *common-service hostname: sdw1 volumes: - - "$PWD/ssh_keys/id_rsa:/home/gpadmin/.ssh/id_rsa" - - "$PWD/ssh_keys/id_rsa.pub:/home/gpadmin/.ssh/id_rsa.pub" - - "$PWD/logs_sdw1:/logs" - sysctls: - kernel.sem: 500 1024000 200 4096 - init: true - ulimits: - nofile: 65535 - entrypoint: > - sleep infinity + - ${PWD}/ssh_keys:/home/gpadmin/.ssh.src + - ${PWD}/logs_sdw1:/logs sdw2: - image: "${IMAGE}" - privileged: true + <<: *common-service hostname: sdw2 volumes: - - "$PWD/ssh_keys/id_rsa:/home/gpadmin/.ssh/id_rsa" - - "$PWD/ssh_keys/id_rsa.pub:/home/gpadmin/.ssh/id_rsa.pub" - sysctls: - kernel.sem: 500 1024000 200 4096 - init: true - ulimits: - nofile: 65535 - entrypoint: > - sleep infinity + - ${PWD}/ssh_keys:/home/gpadmin/.ssh.src + - ${PWD}/logs_sdw2:/logs sdw3: - image: "${IMAGE}" - privileged: true + <<: *common-service hostname: sdw3 volumes: - - "$PWD/ssh_keys/id_rsa:/home/gpadmin/.ssh/id_rsa" - - "$PWD/ssh_keys/id_rsa.pub:/home/gpadmin/.ssh/id_rsa.pub" - sysctls: - kernel.sem: 500 1024000 200 4096 - init: true - ulimits: - nofile: 65535 - entrypoint: > - sleep infinity + - ${PWD}/ssh_keys:/home/gpadmin/.ssh.src + - ${PWD}/logs_sdw3:/logs + sdw4: + <<: *common-service + hostname: sdw4 + volumes: + - ${PWD}/ssh_keys:/home/gpadmin/.ssh.src + - ${PWD}/logs_sdw4:/logs + sdw5: + <<: *common-service + hostname: sdw5 + volumes: + - ${PWD}/ssh_keys:/home/gpadmin/.ssh.src + - ${PWD}/logs_sdw5:/logs + sdw6: + <<: *common-service + hostname: sdw6 + volumes: + - ${PWD}/ssh_keys:/home/gpadmin/.ssh.src + - ${PWD}/logs_sdw6:/logs diff --git a/ci/readme.md b/ci/readme.md index 070186b5a61b..0a622bad6d05 100644 --- a/ci/readme.md +++ b/ci/readme.md @@ -103,7 +103,9 @@ It required to add `gpMgmt/tests` directory to `PYTHONPATH`. Greengage cluster in Docker containers has its own peculiarities in preparing a cluster for tests. All tests are run in one way or another on the demo cluster, wherever possible. -For example, cross_subnet tests or tests with tag `concourse_cluster` currently not worked because of too complex cluster preconditions. +For example, cross_subnet tests currently not worked because of too complex cluster preconditions. +Behave tests run either on the concourse cluster (cluster on several hosts) or on the demo (cluster on single host), +while tests with both tags (concourse and demo) run only on the concourse cluster to avoid running the same test twice. Tests in a `docker compose` cluster use the same ssh keys for `gpadmin` user and pre-add the cluster hosts to `.ssh/know_hosts` and `/etc/hosts`. diff --git a/ci/scripts/behave_collect_logs.bash b/ci/scripts/behave_collect_logs.bash new file mode 100755 index 000000000000..16064acb744d --- /dev/null +++ b/ci/scripts/behave_collect_logs.bash @@ -0,0 +1,13 @@ +feature=$1 + +params=( + "./ d gpAdminLogs" + "gpdb_src/gpAux/gpdemo/datadirs/ d log" + "gpdb_src/gpAux/gpdemo/datadirs/ d pg_log" +) +for param in "${params[@]}"; do + read -r path type name <<< "$param" + [ -d "$path" ] && find "$path" -name "$name" -type "$type" \ + -exec tar -rf "/logs/behave_${feature}_${name}.tar" "{}" \; +done +chmod -R a+rwX /logs diff --git a/ci/scripts/behave_gpdb.bash b/ci/scripts/behave_gpdb.bash index 2d99d5444085..a8cbcd84c74f 100755 --- a/ci/scripts/behave_gpdb.bash +++ b/ci/scripts/behave_gpdb.bash @@ -11,8 +11,6 @@ function gen_env(){ source /usr/local/greengage-db-devel/greengage_path.sh - source gpdb_src/gpAux/gpdemo/gpdemo-env.sh - if [[ ${FEATURE} == "gpexpand" ]]; then mkdir -p /home/gpadmin/sqldump wget -nv https://downloads.adsw.io/misc/dump.sql.xz -O /home/gpadmin/sqldump/dump.sql.xz @@ -40,10 +38,6 @@ function _main() { exit 1 fi - # Run inside a subshell so it does not pollute the environment after - # sourcing greengage_path - time (make_cluster) - time gen_env time run_test diff --git a/ci/scripts/init_containers.sh b/ci/scripts/init_containers.sh index 3b30e3fd3fd5..a5c65faf7153 100644 --- a/ci/scripts/init_containers.sh +++ b/ci/scripts/init_containers.sh @@ -1,5 +1,5 @@ #!/bin/bash -set -eo pipefail +set -eox pipefail project="$1" @@ -18,6 +18,8 @@ for service in $services do docker compose -p $project -f ci/docker-compose.yaml exec -T \ $service bash -c "mkdir -p /data/gpdata && chmod -R 777 /data && + # each host should have its own copy of the (initially identical) files in .ssh + cp -rf .ssh.src .ssh && source gpdb_src/concourse/scripts/common.bash && install_gpdb && ./gpdb_src/concourse/scripts/setup_gpadmin_user.bash" & done @@ -30,3 +32,11 @@ do $service bash -c "ssh-keyscan ${services/$service/} >> /home/gpadmin/.ssh/known_hosts" & done wait + +# Add ip and host names of all cluster nodes to /etc/hosts +for service in $services +do + docker compose -p $project -f ci/docker-compose.yaml exec -T \ + $service bash -c "for HOST in $services; do echo \"\$(host \"\$HOST\" | grep 'has address' | head -n 1 | cut -d ' ' -f 4) \$HOST\" >>/etc/hosts; done" & +done +wait diff --git a/ci/scripts/run_behave_tests.bash b/ci/scripts/run_behave_tests.bash index cdcbdc474bff..cb73d097e8f9 100755 --- a/ci/scripts/run_behave_tests.bash +++ b/ci/scripts/run_behave_tests.bash @@ -3,15 +3,14 @@ set -x -o pipefail behave_tests_dir="gpMgmt/test/behave/mgmt_utils" -# TODO concourse_cluster tests are not stable -# clusters="concourse_cluster ~concourse_cluster,demo_cluster" +clusters="concourse_cluster ~concourse_cluster" -clusters="~concourse_cluster" +docker_compose_path="ci/docker-compose.yaml" if [ $# -eq 0 ] then # TODO cross_subnet and gpssh tests are excluded - features=`ls $behave_tests_dir -1 | grep feature | grep -v -E "cross_subnet|gpssh" | sed 's/\.feature$//'` + features=`ls $behave_tests_dir -1 | grep feature | sed 's/\.feature$//'` else for feature in $@ do @@ -45,18 +44,27 @@ run_feature() { echo "Started $feature behave tests on cluster $cluster and project $project" bash ci/scripts/init_containers.sh $project - docker compose -p $project -f ci/docker-compose.yaml exec -T \ + docker compose -p $project -f "$docker_compose_path" exec -T \ -e FEATURE="$feature" -e BEHAVE_FLAGS="--tags $feature --tags=$cluster \ -f behave_utils.ci.formatter:CustomFormatter \ -o non-existed-output \ -f allure_behave.formatter:AllureFormatter \ - -o /tmp/allure-results" \ + -o /tmp/allure-results \ + -f pretty" \ cdw gpdb_src/ci/scripts/behave_gpdb.bash status=$? - docker compose -p $project -f ci/docker-compose.yaml --env-file ci/.env down -v + if [ -n "$CI" ]; then + local services=$(docker compose -p $project -f "$docker_compose_path" config --services | tr '\n' ' ') + for service in $services; do + docker compose -p $project -f "$docker_compose_path" exec -T \ + $service /bin/bash -s "$feature" < ./ci/scripts/behave_collect_logs.bash + done + fi + + docker compose -p $project -f "$docker_compose_path" --env-file ci/.env down -v - if [[ $status > 0 ]]; then echo "Feature $feature failed with exit code $status"; fi + if [[ $status -gt 0 ]]; then echo "Feature $feature failed with exit code $status"; fi exit $status } diff --git a/ci/scripts/run_resgroup_test.bash b/ci/scripts/run_resgroup_test.bash index d7c96e8361ae..1cc66d9dddff 100755 --- a/ci/scripts/run_resgroup_test.bash +++ b/ci/scripts/run_resgroup_test.bash @@ -3,11 +3,16 @@ set -eox pipefail project="resgroup" +# Exit status file for cloud-init environments where exit codes aren't propagated. +# Parent processes can read this file to determine script success/failure. +logdir="$PWD/logs" +logfile=".exitcode" + function cleanup { docker compose -p $project -f ci/docker-compose.yaml --env-file ci/.env down } -mkdir ssh_keys -p +mkdir ssh_keys "$logdir" -p if [ ! -e "ssh_keys/id_rsa" ] then ssh-keygen -P "" -f ssh_keys/id_rsa @@ -50,7 +55,7 @@ docker compose -p $project -f ci/docker-compose.yaml exec -Tu gpadmin cdw bash - ${CONFIGURE_FLAGS} make -C /home/gpadmin/gpdb_src/src/test/regress - ssh sdw1 mkdir -p /home/gpadmin/gpdb_src/src/test/{regress,isolation2} "$logdir/$logfile" + docker compose -p $project -f ci/docker-compose.yaml exec -T cdw bash -ex < make GPROOT=`pwd` BLD_TARGETS="clients loaders connectivity gppkg" dist ## ---------------------------------------------------------------------- +## To build a Debian package: +## ---------------------------------------------------------------------- + + > make pkg-deb + +This will generate a changelog, build the Debian package using `debuild`, +and place the resulting `.deb` packages in the parent directory. + +See [README.package.md](README.package.md) + +## ---------------------------------------------------------------------- diff --git a/gpAux/Makefile b/gpAux/Makefile index f58c6bce3564..934a3fdc0077 100644 --- a/gpAux/Makefile +++ b/gpAux/Makefile @@ -170,34 +170,34 @@ RECONFIG : rm -f $(GPPGDIR)/GNUmakefile $(GPPGDIR)/GNUmakefile : $(GPPGDIR)/configure env.sh - rm -rf $(DESTDIR)$(INSTLOC) + rm -rf $(INSTLOC) mkdir -p $(GPPGDIR) echo "Running ./configure with CONFIGFLAGS=$(CONFIGFLAGS)\n" cd $(GPPGDIR) && CC="$(strip $(BLD_CC) $(BLD_CFLAGS))" \ CFLAGS=$(INSTCFLAGS) \ ./configure $(CONFIGFLAGS) \ - --prefix=$(INSTLOC) \ - --mandir=$(INSTLOC)/man + --prefix=$(DISTPATH) \ + --mandir=$(DISTPATH)/man Debug/GNUmakefile : $(GPPGDIR)/configure env.sh - rm -rf $(DESTDIR)$(INSTLOC) + rm -rf $(INSTLOC) mkdir -p Debug echo "Running ./configure with CONFIGFLAGS=$(CONFIGFLAGS)\n" cd Debug && CC="$(strip $(BLD_CC) $(BLD_CFLAGS))" \ CFLAGS=$(INSTCFLAGS) \ ./configure $(CONFIGFLAGS) \ - --prefix=$(INSTLOC) \ - --mandir=$(INSTLOC)/man + --prefix=$(DISTPATH) \ + --mandir=$(DISTPATH)/man Release/GNUmakefile : $(GPPGDIR)/configure env.sh - rm -rf $(DESTDIR)$(INSTLOC) + rm -rf $(INSTLOC) mkdir -p Release echo "Running ./configure with CONFIGFLAGS=$(CONFIGFLAGS)\n" cd Release && CC="$(strip $(BLD_CC) $(BLD_CFLAGS))" \ CFLAGS=$(INSTCFLAGS) \ ./configure $(CONFIGFLAGS) \ - --prefix=$(INSTLOC) \ - --mandir=$(INSTLOC)/man + --prefix=$(DISTPATH) \ + --mandir=$(DISTPATH)/man #--------------------------------------------------------------------- # autoconf @@ -224,7 +224,7 @@ perl_archlibexp:=$(shell perl -MConfig -e 'print $$Config{archlibexp}') # set default build steps define BUILD_STEPS - @rm -rf $(DESTDIR)$(INSTLOC) + @rm -rf $(INSTLOC) cd $(BUILDDIR) && PYGRESQL_LDFLAGS='-Wl,-rpath,\$$$$ORIGIN/../../../lib -Wl,--enable-new-dtags' $(MAKE) $(PARALLEL_MAKE_OPTS) install cd $(BUILDDIR)/src/pl/plpython && $(MAKE) clean && $(MAKE) $(PARALLEL_MAKE_OPTS) install && cd $(BUILDDIR) cd $(BUILDDIR)/src/pl/plperl && $(MAKE) clean && echo "LDFLAGS += -Wl,-rpath,$(perl_archlibexp)/CORE -Wl,--enable-new-dtags" >> GNUmakefile && echo "LDFLAGS_SL += -Wl,-rpath,$(perl_archlibexp)/CORE -Wl,--enable-new-dtags" >> GNUmakefile && $(MAKE) $(PARALLEL_MAKE_OPTS) install && cd $(BUILDDIR) @@ -241,7 +241,7 @@ endef ifeq "$(BLD_GPDB_BUILDSET)" "partial" define BUILD_STEPS - rm -rf $(DESTDIR)$(INSTLOC) + rm -rf $(INSTLOC) cd $(BUILDDIR)/gpMgmt/ && $(MAKE) generate_greengage_path_file cd $(BUILDDIR)/src/backend/ && $(MAKE) ../../src/include/parser/gram.h cd $(BUILDDIR)/src/backend/ && $(MAKE) ../../src/include/utils/errcodes.h @@ -290,9 +290,9 @@ endif #--------------------------------------------------------------------- devel : INSTCFLAGS=$(DEBUGFLAGS) -devel : INSTLOC=$(DEVPATH) -devel : CLIENTSINSTLOC=$(CLIENTSDEVPATH) -devel : CONFIGFLAGS+= --enable-cassert --enable-debug --enable-depend +devel : INSTLOC=$(DESTDIR)$(DEVPATH) +devel : CLIENTSINSTLOC=$(DESTDIR)$(CLIENTSDEVPATH) +devel : CONFIGFLAGS+= --enable-cassert --enable-debug --enable-debug-extensions --enable-depend ifdef ENABLE_VPATH_BUILD devel : BUILDDIR=Debug devel : ISCONFIG=$(BUILDDIR)/GNUmakefile @@ -307,8 +307,8 @@ endif #--------------------------------------------------------------------- dist : INSTCFLAGS=$(OPTFLAGS) -dist : INSTLOC=$(DISTPATH) -dist : CLIENTSINSTLOC=$(CLIENTSDISTPATH) +dist : INSTLOC=$(DESTDIR)$(DISTPATH) +dist : CLIENTSINSTLOC=$(DESTDIR)$(CLIENTSDISTPATH) ifdef ENABLE_VPATH_BUILD dist : BUILDDIR=Release dist : ISCONFIG=$(BUILDDIR)/GNUmakefile @@ -319,8 +319,8 @@ endif $(BUILD_STEPS) dist_prof : INSTCFLAGS=$(PROFFLAGS) -dist_prof : INSTLOC=$(DISTPATH) -dist_prof : CLIENTSINSTLOC=$(CLIENTSDISTPATH) +dist_prof : INSTLOC=$(DESTDIR)$(DISTPATH) +dist_prof : CLIENTSINSTLOC=$(DESTDIR)$(CLIENTSDISTPATH) ifdef ENABLE_VPATH_BUILD dist_prof : BUILDDIR=Release dist_prof : ISCONFIG=$(BUILDDIR)/GNUmakefile @@ -331,7 +331,7 @@ dist_prof : gccVersionCheck GPROOTDEP RECONFIG $(ISCONFIG) endif $(BUILD_STEPS) -dist_faultinj : CLIENTSINSTLOC=$(CLIENTSDISTPATH) +dist_faultinj : CLIENTSINSTLOC=$(DESTDIR)$(CLIENTSDISTPATH) ifdef ENABLE_VPATH_BUILD dist_faultinj : BUILDDIR=Release dist_faultinj : ISCONFIG=$(BUILDDIR)/GNUmakefile @@ -342,6 +342,67 @@ dist_faultinj : gccVersionCheck GPROOTDEP RECONFIG $(ISCONFIG) endif $(BUILD_STEPS) +#--------------------------------------------------------------------- +# Packaging targets with changelog options +#--------------------------------------------------------------------- + +# Metadata vars +PACKAGE_NAME := $(shell grep '^Package:' debian/control | head -1 | awk '{print $$2}') +MAINTAINER := $(shell grep '^Maintainer:' debian/control | sed 's/Maintainer: //') +DATE_RFC := $(shell date -R) +ARTIFACTS_DIR := $(CURDIR)/../Package + +../VERSION : + @echo "Update $@" + ../getversion > $@ + @cat $@ + +version-vars : ../VERSION + $(eval FULL_VERSION := $(shell [ -f ../VERSION ] && perl -pe 's, ,-,g' ../VERSION)) + $(eval PACKAGE_VERSION := $(shell [ -f ../VERSION ] && perl -pe 's, .*,,g' ../VERSION)) + $(eval IS_RELEASE := $(if $(findstring +dev,$(PACKAGE_VERSION)),no,yes)) + $(eval STABILITY := $(if $(filter yes,$(IS_RELEASE)),stable,unstable)) + $(eval BUILD_TYPE := $(if $(filter yes,$(IS_RELEASE)),Release build,Development build)) + +version-info : version-vars + @echo "PACKAGE_VERSION: $(PACKAGE_VERSION)" + @echo "FULL_VERSION: $(FULL_VERSION)" + @echo "IS_RELEASE: $(IS_RELEASE)" + @echo "STABILITY: $(STABILITY)" + @echo "BUILD_TYPE: $(BUILD_TYPE)" + +# Generate package control files +changelog : debian/changelog +debian/changelog : version-vars + @echo "$(PACKAGE_NAME) ($(PACKAGE_VERSION)) $(STABILITY); urgency=low" > $@ + @echo "" >> $@ + @echo " * $(BUILD_TYPE)" >> $@ + @echo "" >> $@ + @echo " -- $(MAINTAINER) $(DATE_RFC)" >> $@ + +debian/install: + @echo "$(PACKAGE_NAME)/* /" > $@ + + +# Default packaging target +pkg : pkg-deb + +# Build Debian package +pkg-deb : GPROOT = /opt/greengagedb +pkg-deb : GPDIR = $(PACKAGE_NAME) +pkg-deb : debian/changelog debian/install + @echo "Building with GPROOT=$(GPROOT), GPDIR=$(GPDIR), PACKAGE_NAME=$(PACKAGE_NAME)" + @GPROOT="$(GPROOT)" GPDIR="$(GPDIR)" PACKAGE_NAME="$(PACKAGE_NAME)" debuild --preserve-env -us -uc -b + @mkdir -p $(ARTIFACTS_DIR) + @find $(CURDIR)/../ -maxdepth 1 -type f \( -name "*.deb" \ + -o -name "*.ddeb" \ + -o -name "*.build" \ + -o -name "*.buildinfo" \ + -o -name "*.changes" \) \ + -exec mv -f {} $(ARTIFACTS_DIR)/ \; + +.PHONY: pkg pkg-deb changelog version-vars version-info + #--------------------------------------------------------------------- # clientTools #--------------------------------------------------------------------- @@ -412,7 +473,7 @@ endif endif ifeq "$(INSTLOC)" "" -INSTLOC=$(GPDIR) +INSTLOC=$(DESTDIR)$(GPDIR) endif VERSION:=$(shell [ -f ../VERSION ] && perl -pe 's, ,-,g' ../VERSION) @@ -473,7 +534,7 @@ PVK_FILESET = \ $(NULL) pvk : INSTCFLAGS=$(OPTFLAGS) -pvk : INSTLOC=$(DISTPATH) +pvk : INSTLOC=$(DESTDIR)$(DISTPATH) pvk : gccVersionCheck version GPROOTDEP cd $(GPMGMT)/bin && $(MAKE) stream mkdir -p $(INSTLOC)/bin/lib @@ -539,7 +600,7 @@ ifeq "$(shell uname -s)" "Darwin" echo "pgbouncer can't build on Mac" else @if [ ! -f extensions/pgbouncer/source/configure ]; then cd extensions/pgbouncer/source && ./autogen.sh ;fi - @cd extensions/pgbouncer/source && ./configure --with-libevent=$(BLD_TOP)/ext/$(BLD_ARCH) --prefix=$(INSTLOC) --enable-evdns --with-pam --with-ldap + @cd extensions/pgbouncer/source && ./configure --with-libevent=$(BLD_TOP)/ext/$(BLD_ARCH) --prefix=$(DISTPATH) --enable-evdns --with-pam --with-ldap $(MAKE) -C extensions/pgbouncer/source install endif @@ -618,8 +679,8 @@ copylibs : mkdir -p $(INSTLOC)/include greengage_path: - mkdir -p $(DESTDIR)$(INSTLOC) - $(BUILDDIR)/gpMgmt/bin/generate-greengage-path.sh no > $(DESTDIR)$(INSTLOC)/greengage_path.sh + mkdir -p $(INSTLOC) + $(BUILDDIR)/gpMgmt/bin/generate-greengage-path.sh no > $(INSTLOC)/greengage_path.sh copylicense: for proddir in $(INSTLOC) $(CLIENTSINSTLOC); do \ @@ -669,7 +730,7 @@ distclean : @if [ -d Release -a -f Release/GNUmakefile ]; then cd Release; $(MAKE) distclean; fi @if [ -d $(GPPGDIR) -a -f $(GPPGDIR)/GNUmakefile ]; then cd $(GPPGDIR); $(MAKE) distclean; fi @if [ -d $(GPMGMT)/bin ]; then cd $(GPMGMT)/bin; $(MAKE) distclean; fi - @rm -f VERSION + @if [ -d .git ] ; then rm -f VERSION; fi @rm -f env.sh distprep : $(ISCONFIG) diff --git a/gpAux/README.package.md b/gpAux/README.package.md new file mode 100644 index 000000000000..14e82f666ec8 --- /dev/null +++ b/gpAux/README.package.md @@ -0,0 +1,131 @@ +# Greengage Database Packaging System + +## Overview + +This documentation describes the Debian packaging system for Greengage Database located in the `gpAux/` subdirectory. The system builds Debian packages using a custom Makefile and `debian/rules` file. + +## Location and Structure + +The packaging system is located in: + +```text +./gpAux/ +``` + +The main components are: + +- `Makefile` - Defines packaging targets, version management, and artifact collection +- `debian/rules` - Debian build rules with custom overrides +- `debian/control` - Package metadata and dependencies +- Other standard Debian packaging files + +## Key Components + +### Makefile Targets + +1. **Version Management**: + - `../VERSION`: Generates version file using `../getversion` + - `version-vars`: Sets build variables (`FULL_VERSION`, `PACKAGE_VERSION`, `IS_RELEASE`, `STABILITY`, `BUILD_TYPE`) from `../VERSION` + - `version-info`: Displays version information for debugging + +2. **Packaging Targets**: + - `pkg`: Default target (aliases to `pkg-deb`) + - `pkg-deb`: Builds Debian package, preserves environment variables, and collects specific artifacts (`.deb`, `.ddeb`, `.build`, `.buildinfo`, `.changes`) + - `changelog`: Generates `debian/changelog` using version variables + - `debian/install`: Creates installation manifest + +### Debian Rules File + +The `debian/rules` file uses debhelper (dh) with custom overrides: + +1. **Distribution-specific Dependencies**: + - Detects Ubuntu 22.04 and adds `python2.7` dependency + +2. **Build Process Overrides**: + - Skips standard configure and build steps + - Uses the project's `make dist` target for installation + - Unsets standard compiler flags to avoid conflicts + - Enables parallel builds using all available CPU cores + +3. **Control File Generation**: + - Adds Python dependencies for Ubuntu 22.04 + +## Usage + +### Building the Package + +From the project root directory, run: + +```bash +make -C ./gpAux pkg-deb +``` + +### Custom Installation Paths + +To customize installation paths, set environment variables: + +```bash +make -C ./gpAux pkg-deb GGROOT=/custom/path GPDIR=custom_dir +``` + +### Environment Variables + +- `GGROOT`: Installation root directory (default: `/opt/greengagedb`) +- `GPDIR`: Subdirectory under `GGROOT` (default: `` from `debian/control`) +- `ARTIFACTS_DIR`: Directory for build artifacts (default: `$(CURDIR)/../Package`) + +## Build Process Details + +1. **Version Generation**: + - Runs `../getversion` to create `../VERSION` + - Processes version string into `FULL_VERSION` and `PACKAGE_VERSION` + - Sets `IS_RELEASE` and `STABILITY` for changelog generation + +2. **Package Building**: + - Executes `debuild` with preserved environment variables (`GGROOT`, `GPDIR`, `PACKAGE_NAME`) + - Skips signing with `-us -uc` flags + - Collects specific build artifacts (`.deb`, `.ddeb`, `.build`, `.buildinfo`, `.changes`) into `ARTIFACTS_DIR` + +3. **Installation**: + - Uses `make dist` for installation into `debian/tmp` + - Generates file manifest in `debian/install` + +## Dependencies + +The packaging system automatically handles: + +- `Ubuntu 22.04` detection and `python2.7` dependency +- Other distributions may require manual dependency configuration + +## Maintenance + +### Updating Package Metadata + +Edit `debian/control` to update: + +- Package description +- Maintainer information +- General dependencies + +### Adding Distribution Support + +Modify distribution detection in `debian/rules`: + +```makefile +ifeq ($(LSB_SI),Ubuntu) + ifeq ($(LSB_SR),22.04) + DEPS=python2.7 + endif + ifeq ($(LSB_SR),20.04) + DEPS=python2.7 + endif +endif +``` + +## Notes + +- Skips tests (`DEB_BUILD_OPTIONS=nocheck`) for faster builds +- Unsets compiler flags to avoid conflicts with the project's build system +- Enables parallel builds using all available CPU cores +- Builds without signing for development convenience +- Collects only specific build artifacts (`.deb`, `.ddeb`, `.build`, `.buildinfo`, `.changes`) into `$(CURDIR)/../Package` diff --git a/gpAux/debian/compat b/gpAux/debian/compat new file mode 100644 index 000000000000..b1bd38b62a08 --- /dev/null +++ b/gpAux/debian/compat @@ -0,0 +1 @@ +13 diff --git a/gpAux/debian/control b/gpAux/debian/control new file mode 100644 index 000000000000..760b24b0f548 --- /dev/null +++ b/gpAux/debian/control @@ -0,0 +1,30 @@ +Source: greengage +Maintainer: Greengage +Section: database +Build-Depends: debhelper (>= 13), + dh-python, + lsb-release + +Package: greengage +Architecture: any +Depends: ${shlibs:Depends}, + iproute2, + iputils-ping, + less, + openssh-client, + openssh-server, + openssl, + python2, + rsync, + zip, + net-tools, + ${pythonRequires} +Conflicts: greengage-loaders, + python-is-python3 +Description: Greengage MPP database engine + Greengage Database (GPDB) is an advanced, fully featured, open + source data warehouse, based on PostgreSQL. It provides powerful and + rapid analytics on petabyte scale data volumes. Uniquely geared toward + big data analytics, Greengage Database is powered by the world’s most + advanced cost-based query optimizer delivering high analytical query + performance on large data volumes. diff --git a/gpAux/debian/copyright b/gpAux/debian/copyright new file mode 100644 index 000000000000..cdc1800d9a0a --- /dev/null +++ b/gpAux/debian/copyright @@ -0,0 +1,24 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: greengage +Upstream-Contact: GreengageDB Team +Source: https://github.com/GreengageDB/greengage + +Files: * +Copyright: See COPYRIGHT file +License: Apache-2.0 + +License: Apache-2.0 + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + . + http://www.apache.org/licenses/LICENSE-2.0 + . + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + . + On Debian systems, the complete text of the Apache License 2.0 can be + found in "/usr/share/common-licenses/Apache-2.0". diff --git a/gpAux/debian/lintian-overrides b/gpAux/debian/lintian-overrides new file mode 100644 index 000000000000..491c4105a411 --- /dev/null +++ b/gpAux/debian/lintian-overrides @@ -0,0 +1,9 @@ +# 3rd-party Package +dir-or-file-in-opt + +# TODO +unusual-interpreter python +script-uses-unversioned-python-in-shebang + +# Not applicable for plugins +shared-library-lacks-prerequisites diff --git a/gpAux/debian/rules b/gpAux/debian/rules new file mode 100755 index 000000000000..878508a6da3b --- /dev/null +++ b/gpAux/debian/rules @@ -0,0 +1,40 @@ +#!/usr/bin/make -f +# Run command: `make -C ./gpdb_src/gpAux pkg-deb` + +DH_VERBOSE = 1 +export DH_OPTIONS = -v +export DEB_BUILD_OPTIONS = nocheck + +LSB_SI := $(shell lsb_release -si) +LSB_SR := $(shell lsb_release -sr) + +ifeq ($(LSB_SI),Ubuntu) + ifeq ($(LSB_SR),22.04) + DEPS = python2.7 + endif +endif + +%: + dh $@ + +override_dh_auto_clean: + @echo "Skipping clean" + +override_dh_auto_configure: + @echo "Skipping configure" + +override_dh_auto_build: + @echo "Skipping autobuild" + +override_dh_auto_install: + @echo "=== Building and installing with GPROOT=$(GPROOT), GPDIR=$(GPDIR), PACKAGE_NAME=$(PACKAGE_NAME) ===" + env -u CFLAGS -u CPPFLAGS -u CXXFLAGS -u LDFLAGS \ + $(MAKE) dist \ + DESTDIR=$(CURDIR)/debian/tmp/$(PACKAGE_NAME) \ + GPROOT=$(GPROOT) \ + GPDIR=$(GPDIR) \ + PARALLEL_MAKE_OPTS=-j$(shell nproc) + +override_dh_gencontrol: + @echo "=== GENCONTROL GPROOT=$(GPROOT), GPDIR=$(GPDIR), PACKAGE_NAME=$(PACKAGE_NAME) ===" + dh_gencontrol -p$(PACKAGE_NAME) -- -VpythonRequires="$(DEPS)" diff --git a/gpAux/gpdemo/demo_cluster.sh b/gpAux/gpdemo/demo_cluster.sh index 26715322123f..68740c1408fb 100755 --- a/gpAux/gpdemo/demo_cluster.sh +++ b/gpAux/gpdemo/demo_cluster.sh @@ -392,11 +392,13 @@ if [ -n "${STATEMENT_MEM}" ]; then EOF fi -if [ -n "${OPTIMIZER_ENABLE_TABLE_ALIAS}" ]; then - cat >> $CLUSTER_CONFIG_POSTGRES_ADDONS<<-EOF - optimizer_enable_table_alias = ${OPTIMIZER_ENABLE_TABLE_ALIAS} - EOF -fi +# Demo cluster always works with disabled optimizer_enable_table_alias, so it's +# easy to run tests suite with no additional setup. +# TODO: remove this and GUC optimizer_enable_table_alias when tests are +# corrected for aliases. +cat >> $CLUSTER_CONFIG_POSTGRES_ADDONS<<-EOF +optimizer_enable_table_alias = false +EOF if [ "${ONLY_PREPARE_CLUSTER_ENV}" == "true" ]; then echo "ONLY_PREPARE_CLUSTER_ENV set, generated clusterConf file: $CLUSTER_CONFIG, exiting" diff --git a/gpAux/releng/set_bld_arch.sh b/gpAux/releng/set_bld_arch.sh index efe799020d8d..3fecae9a27bc 100755 --- a/gpAux/releng/set_bld_arch.sh +++ b/gpAux/releng/set_bld_arch.sh @@ -7,7 +7,7 @@ case "`uname -s`" in if [ -f /etc/redhat-release -a ! -f /etc/altlinux-release -a ! -f /etc/redos-release ]; then case "`cat /etc/redhat-release`" in *) - BLD_ARCH_HOST="rhel`cat /etc/redhat-release | sed -e 's/CentOS Linux/RedHat/' -e 's/Red Hat Enterprise Linux/RedHat/' -e 's/WS//' -e 's/Server//' -e 's/Client//' | awk '{print $3}' | awk -F. '{print $1}'`_`uname -m | sed -e s/i686/x86_32/`" + BLD_ARCH_HOST="rhel`cat /etc/redhat-release | sed -e 's/CentOS Linux/RedHat/' -e 's/Red Hat Enterprise Linux/RedHat/' -e 's/Rocky Linux/RedHat/' -e 's/WS//' -e 's/Server//' -e 's/Client//' | awk '{print $3}' | awk -F. '{print $1}'`_`uname -m | sed -e s/i686/x86_32/`" ;; esac fi diff --git a/gpMgmt/bin/Makefile b/gpMgmt/bin/Makefile index 565941916ddc..23acd9210709 100644 --- a/gpMgmt/bin/Makefile +++ b/gpMgmt/bin/Makefile @@ -155,8 +155,6 @@ PYTHONSRC_INSTALL=$(PYLIB_SRC_EXT)/install PYTHON_VERSION=$(shell python -c "import sys; print ('%s.%s' % (sys.version_info[0:2]))") PYTHONSRC_INSTALL_SITE=$(PYLIB_SRC_EXT)/install/lib/python$(PYTHON_VERSION)/site-packages PYTHONSRC_INSTALL_PYTHON_PATH=$(PYTHONPATH):$(PYTHONSRC_INSTALL_SITE) -# TODO: mock-1.0.1-py2.6.egg package should be updated. -MOCK_BIN=$(PYTHONSRC_INSTALL)/lib/python$(PYTHON_VERSION)/site-packages/mock-1.0.1-py2.6.egg UBUNTU_PLATFORM=$(shell if lsb_release -a 2>/dev/null | grep -q 'Ubuntu' ; then echo "Ubuntu"; fi) pylint: @@ -172,18 +170,9 @@ pylint: @touch $(PYLIB_SRC_EXT)/$(PYLINT_DIR)/build/lib/__init__.py @touch $(PYLIB_SRC_EXT)/$(PYLINT_DIR)/build/lib/logilab/__init__.py -$(MOCK_BIN): +mockinstall: @echo "--- mock for platform $(UBUNTU_PLATFORM)" - @if [ $(UBUNTU_PLATFORM) = "Ubuntu" ]; then\ - wget https://bootstrap.pypa.io/pip/2.7/get-pip.py && \ - python2 get-pip.py && \ - pip install mock==1.0.1;\ - else\ - mkdir -p $(PYTHONSRC_INSTALL_SITE) && \ - cd $(PYLIB_SRC_EXT)/ && tar xzf $(MOCK_DIR).tar.gz && \ - cd $(PYLIB_SRC_EXT)/$(MOCK_DIR)/ && \ - PYTHONPATH=$(PYTHONSRC_INSTALL_PYTHON_PATH) python setup.py install --prefix $(PYTHONSRC_INSTALL) ; \ - fi; + python -m pip install $(PYLIB_SRC_EXT)/$(MOCK_DIR).tar.gz; \ PYTHON_FILES=`grep -l --exclude=Makefile --exclude=gplogfilter "/bin/env python" *`\ `grep -l "/bin/env python" $(SRC)/../sbin/*`\ @@ -201,12 +190,12 @@ check-regress: @PYTHONPATH=$(SRC):$(SRC)/ext:$(PYTHONPATH) \ gppylib/gpunit discover --verbose -s gppylib -p "test_regress*.py" 2> $(SRC)/../gpMgmt_testregress_results.log 1> $(SRC)/../gpMgmt_testregress_output.log -check: $(MOCK_BIN) +check: mockinstall @echo "Running pure unit and also "unit" tests that require cluster to be up..." @TMPDIR=/tmp PYTHONPATH=$(SERVER_SRC):$(SERVER_SBIN):$(PYTHONPATH):$(PYTHONSRC_INSTALL_PYTHON_PATH):$(SRC)/ext:$(SBIN_DIR):$(LIB_DIR):$(PYLIB_DIR)/mock-1.0.1 \ - gppylib/gpunit discover --verbose -s $(SRC)/gppylib -p "test_unit*.py" 2> $(SRC)/../gpMgmt_testunit_results.log 1> $(SRC)/../gpMgmt_testunit_output.log + gppylib/gpunit discover --verbose -s $(SRC)/gppylib -p "test_unit*.py" 2> $(SRC)/../gpMgmt_testunit_results.log 1> $(SRC)/../gpMgmt_testunit_output.log || (cat $(SRC)/../gpMgmt_testunit_results.log && cat $(SRC)/../gpMgmt_testunit_output.log && exit 1) @TMPDIR=/tmp PYTHONPATH=$(SERVER_SRC):$(SERVER_SBIN):$(PYTHONPATH):$(PYTHONSRC_INSTALL_PYTHON_PATH):$(SRC)/ext:$(SBIN_DIR):$(LIB_DIR):$(PYLIB_DIR)/mock-1.0.1 \ - gppylib/gpunit discover --verbose -s $(SRC)/gppylib -p "test_cluster*.py" 2>> $(SRC)/../gpMgmt_testunit_results.log 1>> $(SRC)/../gpMgmt_testunit_output.log + gppylib/gpunit discover --verbose -s $(SRC)/gppylib -p "test_cluster*.py" 2>> $(SRC)/../gpMgmt_testunit_results.log 1>> $(SRC)/../gpMgmt_testunit_output.log || (cat $(SRC)/../gpMgmt_testunit_results.log && cat $(SRC)/../gpMgmt_testunit_output.log && exit 1) unitdevel: @echo "Running pure unit tests..." @@ -220,7 +209,7 @@ installcheck-bash: ./test/suite.bash .PHONY: installcheck -installcheck: installcheck-bash +installcheck: check installcheck-bash $(MAKE) -C gpload_test $@ clean distclean: diff --git a/gpMgmt/bin/README b/gpMgmt/bin/README index ea0ff98334b1..7815e283c76c 100644 --- a/gpMgmt/bin/README +++ b/gpMgmt/bin/README @@ -155,10 +155,9 @@ Testing Management Scripts This directory contains the unit tests for the management scripts. These tests require the following Python modules to be installed: mock and pygresql. -These modules can be installed by running "git submodule update --init --recursive" -if they are not already installed on your machine. +These modules can be installed by running "make install" in gpMgmt/bin. -If you installed the dependencies using the above git command, you can run the tests with +If you installed the dependencies using the command above, you can run the tests with make, using the following commands in the current directory: "make check" will run all of the unit tests, some of which require a GPDB cluster to diff --git a/gpMgmt/bin/gpcheckcat b/gpMgmt/bin/gpcheckcat index 5188b13a5509..f031fbb3a874 100755 --- a/gpMgmt/bin/gpcheckcat +++ b/gpMgmt/bin/gpcheckcat @@ -325,6 +325,7 @@ def connect(user=None, password=None, host=None, port=None, '''Connect to DB using parameters in GV''' # make search path safe options = '-c search_path=' + options += ' -c gp_dispatch_drop_always=on' if utilityMode: options += ' -c gp_session_role=utility' for val in GV.opt['-x']: diff --git a/gpMgmt/bin/gpconfig b/gpMgmt/bin/gpconfig index a34fe0414d7e..bc4709aa3ca3 100755 --- a/gpMgmt/bin/gpconfig +++ b/gpMgmt/bin/gpconfig @@ -39,7 +39,7 @@ except ImportError as err: EXECNAME = os.path.split(__file__)[-1] PROHIBITED_GUCS = set(["port", "listen_addresses"]) -SAMEVALUE_GUCS = set(["gp_default_storage_options"]) +SAMEVALUE_GUCS = set(["gp_default_storage_options", "gp_resource_group_retrieve"]) read_only_gucs = set() # populated at runtime LOGGER = get_default_logger() setup_tool_logging(EXECNAME, getLocalHostname(), getUserName()) diff --git a/gpMgmt/bin/gpload_test/Makefile b/gpMgmt/bin/gpload_test/Makefile index e10b2991e84e..3d2df02e64da 100644 --- a/gpMgmt/bin/gpload_test/Makefile +++ b/gpMgmt/bin/gpload_test/Makefile @@ -19,10 +19,7 @@ GPTest.pm: .PHONY: installcheck -ifeq "$(findstring ubuntu, $(TEST_OS))" "ubuntu" -installcheck: gpdiff.pl gpstringsubs.pl - @echo "skip gpload test for ubuntu" -else ifeq "$(findstring CentOS release 6., $(OS))" "CentOS release 6." +ifeq "$(findstring CentOS release 6., $(OS))" "CentOS release 6." installcheck: gpdiff.pl gpstringsubs.pl @echo "skip gpload test for centos6" else ifeq "$(findstring CentOS Linux release 7., $(OS))" "CentOS Linux release 7." @@ -33,15 +30,8 @@ installcheck: gpdiff.pl gpstringsubs.pl @echo "skip gpload test for Red Hat" else installcheck: gpdiff.pl gpstringsubs.pl - # install pytest for python2 and gpload test - python2 -m ensurepip --upgrade - python2 -m pip install -r pytest_requirement.txt - python2 -m pip install pytest-order==0.11.0 - python2 -m pip install lxml - @cd gpload && ./TEST.py - @export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.7/site-packages/:/usr/lib64/python2.7/site-packages/:/usr/local/greengage-db-devel/lib/python\ - && cd gpload2 && python2 -m pytest TEST_local_* + @cd gpload2 && python -m pytest TEST_local_* endif clean distclean: diff --git a/gpMgmt/bin/gpload_test/pytest_requirement.txt b/gpMgmt/bin/gpload_test/pytest_requirement.txt index bdec52f5a477..7d686e8a198b 100644 --- a/gpMgmt/bin/gpload_test/pytest_requirement.txt +++ b/gpMgmt/bin/gpload_test/pytest_requirement.txt @@ -7,4 +7,6 @@ more_itertools==5.0.0 packaging==20.9 pluggy==0.13.1 importlib-metadata==2.1.0 -pytest==4.6. \ No newline at end of file +pytest==4.6. +pytest-order==0.11.0 +lxml==5.0.2 \ No newline at end of file diff --git a/gpMgmt/bin/gppylib/commands/gp.py b/gpMgmt/bin/gppylib/commands/gp.py index 05914ad9c736..29cf57887d46 100644 --- a/gpMgmt/bin/gppylib/commands/gp.py +++ b/gpMgmt/bin/gppylib/commands/gp.py @@ -60,24 +60,26 @@ PGDATABASE_FOR_COMMON_USE= 'postgres' def get_postmaster_pid_locally(datadir): - cmdStr = "ps -ef | grep postgres | grep -v grep | awk '{print $2}' | grep `cat %s/postmaster.pid | head -1` || echo -1" % (datadir) + cmdStr = "ps -p \"$(head -1 %s/postmaster.pid)\" -o comm= -o pid=" % (datadir) name = "get postmaster" cmd = Command(name, cmdStr) try: cmd.run(validateAfter=True) sout = cmd.get_results().stdout.lstrip(' ') - return int(sout.split()[0]) + comm, pid = sout.split() + return int(pid if comm == "postgres" else -1) except: return -1 def getPostmasterPID(hostname, datadir): - cmdStr="echo 'START_CMD_OUTPUT';ps -ef | grep postgres | grep -v grep | awk '{print $2}' | grep \\`cat %s/postmaster.pid | head -1\\` || echo -1" % (datadir) + cmdStr="echo 'START_CMD_OUTPUT';ps -p \"\\$(head -1 %s/postmaster.pid)\" -o comm= -o pid=" % (datadir) name="get postmaster pid" cmd=Command(name,cmdStr,ctxt=REMOTE,remoteHost=hostname) try: cmd.run(validateAfter=True) - sout=cmd.get_results().stdout.lstrip(' ') - return int(sout.split('START_CMD_OUTPUT\n')[1].split()[1]) + sout=cmd.get_results().stdout.lstrip(' ').split('START_CMD_OUTPUT\n')[1] + comm, pid = sout.split() + return int(pid if comm == "postgres" else -1) except: return -1 diff --git a/gpMgmt/bin/gppylib/commands/test/unit/test_cluster_gp.py b/gpMgmt/bin/gppylib/commands/test/unit/test_cluster_gp.py new file mode 100644 index 000000000000..e2e7112bf76d --- /dev/null +++ b/gpMgmt/bin/gppylib/commands/test/unit/test_cluster_gp.py @@ -0,0 +1,78 @@ +#!/usr/bin/env python + +import os +import psutil +import shutil +import tempfile +import unittest + +from gppylib.db import dbconn +from gppylib.commands.gp import getPostmasterPID, get_postmaster_pid_locally + + +class GpCommandTestCase(unittest.TestCase): + def setUp(self): + # Connect to the database pointed to by PGHOST et al. + self.url = dbconn.DbURL() + + with dbconn.connect(self.url) as conn: + result = dbconn.execSQL( + conn, + "SELECT port, datadir FROM gp_segment_configuration" + ).fetchall() + + for port, datadir in result: + if not psutil.pid_exists(port): + # Process with PID as port number doesn't exist + # use it for test + self.port = port + self.datadir = datadir + break + else: + # Unexpectedly all postmaster's ports have corresponding PIDs + self.port = -1 + self.pid = -1 + self.datadir = "" + + + def test_get_postmaster_pid_locally_valid_pid(self): + result = get_postmaster_pid_locally(self.datadir) + self.assertIsInstance(result, int) + self.assertNotEqual(result, -1) + + def test_getPostmasterPID_valid_pid(self): + result = getPostmasterPID("localhost", self.datadir) + self.assertIsInstance(result, int) + self.assertNotEqual(result, -1) + + def test_get_postmaster_pid_locally_nonexistent_pid(self): + if self.port == -1: + self.skipTest("Unexpectedly all postmaster's ports have corresponding PIDs") + + temp_dir = tempfile.mkdtemp() + temp_file_path = os.path.join(temp_dir, "postmaster.pid") + with open(temp_file_path, "w") as f: + f.write(str(self.port)) + + result = get_postmaster_pid_locally(temp_dir) + shutil.rmtree(temp_dir) + self.assertIsInstance(result, int) + self.assertEqual(result, -1, "PID file pid: {}, found pid: {}".format(self.port, result)) + + def test_get_getPostmasterPID_nonexistent_pid(self): + if self.port == -1: + self.skipTest("Unexpectedly all postmaster's ports have corresponding PIDs") + + temp_dir = tempfile.mkdtemp() + temp_file_path = os.path.join(temp_dir, "postmaster.pid") + with open(temp_file_path, "w") as f: + f.write(str(self.port)) + + result = getPostmasterPID("localhost", temp_dir) + shutil.rmtree(temp_dir) + self.assertIsInstance(result, int) + self.assertEqual(result, -1, "PID file pid: {}, found pid: {}".format(self.port, result)) + +#------------------------------- Mainline -------------------------------- +if __name__ == '__main__': + unittest.main() diff --git a/gpMgmt/bin/gppylib/commands/test/unit/test_unit_gp.py b/gpMgmt/bin/gppylib/commands/test/unit/test_unit_gp.py index 3b280307537b..d45db420bb51 100644 --- a/gpMgmt/bin/gppylib/commands/test/unit/test_unit_gp.py +++ b/gpMgmt/bin/gppylib/commands/test/unit/test_unit_gp.py @@ -146,7 +146,7 @@ def test_is_pid_postmaster_pgrep_failed_remote(self, mock1, mock2): self.assertTrue(is_pid_postmaster(datadir, pid, remoteHost=remoteHost)) @patch('gppylib.commands.gp.Command.run') - @patch('gppylib.commands.gp.Command.get_results', return_value=CommandResult(0, "1234", "", True, False)) + @patch('gppylib.commands.gp.Command.get_results', return_value=CommandResult(0, "postgres 1234", "", True, False)) def test_get_postmaster_pid_locally(self, mock1, mock2): self.assertEqual(get_postmaster_pid_locally('/tmp'), 1234) diff --git a/gpMgmt/bin/gppylib/commands/unix.py b/gpMgmt/bin/gppylib/commands/unix.py index f5ddddcbcc83..2352bb60874b 100644 --- a/gpMgmt/bin/gppylib/commands/unix.py +++ b/gpMgmt/bin/gppylib/commands/unix.py @@ -580,7 +580,7 @@ def __init__(self, name, srcFile, dstFile, srcHost=None, dstHost=None, recursive # of each line and redirects it to progress_file if progress_file: cmd_tokens.append( - '2>&1 | tr "\\r" "\\n" |sed -E "/[0-9]+%/ s/$/ :{0}/" > {1}'.format(name, pipes.quote(progress_file))) + '2>&1 | tr "\\r" "\\n" |sed -u -E "/[0-9]+%/ s/$/ :{0}/" > {1}'.format(name, pipes.quote(progress_file))) cmdStr = ' '.join(cmd_tokens) cmdStr = "set -o pipefail; {}".format(cmdStr) diff --git a/gpMgmt/bin/gppylib/operations/test/unit/test_unit_buildMirrorSegments.py b/gpMgmt/bin/gppylib/operations/test/unit/test_unit_buildMirrorSegments.py index 899d3d898002..8d5e87c1fca4 100644 --- a/gpMgmt/bin/gppylib/operations/test/unit/test_unit_buildMirrorSegments.py +++ b/gpMgmt/bin/gppylib/operations/test/unit/test_unit_buildMirrorSegments.py @@ -475,8 +475,9 @@ def test_clean_up_failed_segments(self): build_mirrors_obj._clean_up_failed_segments() + # Only inplace_full1 and inplace_full2 should be cleaned self.mock_get_segments_by_hostname.assert_called_once_with([failed1, failed3]) - self.mock_logger.info.called_once_with('"Cleaning files from 3 segment(s)') + self.mock_logger.info.assert_called_once_with('Cleaning files from 2 segment(s)') def test_clean_up_failed_segments_no_segs_to_cleanup(self): failed2 = self._create_primary(dbid='3', status='d') diff --git a/gpMgmt/bin/gppylib/test/unit/test_unit_gpcheckcat.py b/gpMgmt/bin/gppylib/test/unit/test_unit_gpcheckcat.py index 3850bd5fa6ec..eaae6336aa25 100755 --- a/gpMgmt/bin/gppylib/test/unit/test_unit_gpcheckcat.py +++ b/gpMgmt/bin/gppylib/test/unit/test_unit_gpcheckcat.py @@ -145,7 +145,7 @@ def test_truncate_batch_size(self, mock_log, mock_gpcheckcat, mock_sys_exit): for i in range(1, 50): primaries.append(dict(hostname='host0', port=123, id=1, address='123', datadir='dir', content=1, dbid=i, isprimary='t')) - self.db_connection.query.return_value.getresult.return_value = [['4.3']] + self.db_connection.query.return_value.getresult.return_value = [['6.2']] self.db_connection.query.return_value.dictresult.return_value = primaries testargs = ['some_string','-port 1', '-R foo'] diff --git a/gpMgmt/bin/gppylib/test/unit/test_unit_gpexpand.py b/gpMgmt/bin/gppylib/test/unit/test_unit_gpexpand.py index 0196ebf8862b..b36d56ed9b66 100644 --- a/gpMgmt/bin/gppylib/test/unit/test_unit_gpexpand.py +++ b/gpMgmt/bin/gppylib/test/unit/test_unit_gpexpand.py @@ -32,9 +32,13 @@ def setUp(self): self.subject.is_gpexpand_running = Mock(return_value=False) self.gparray = self.createGpArrayWith2Primary2Mirrors() + + open_mock = mock_open() + open_mock.return_value.encoding = 'utf-8' + self.apply_patches([ patch('gpexpand.GpArray.initFromCatalog', return_value=self.gparray), - patch('__builtin__.open', mock_open(), create=True), + patch('__builtin__.open', open_mock, create=True), patch('__builtin__.raw_input'), patch('gpexpand.copy.deepcopy', return_value=Mock()), patch('gpexpand.dbconn.execSQL', return_value=FakeCursor()), diff --git a/gpMgmt/bin/gppylib/test/unit/test_unit_gpsegrecovery.py b/gpMgmt/bin/gppylib/test/unit/test_unit_gpsegrecovery.py index 56ba305cfa94..e3c1a8a62ae1 100644 --- a/gpMgmt/bin/gppylib/test/unit/test_unit_gpsegrecovery.py +++ b/gpMgmt/bin/gppylib/test/unit/test_unit_gpsegrecovery.py @@ -310,7 +310,7 @@ def test_complete_workflow(self, mock_pgbasebackup_run, mock_pgbasebackup_init, self.assertEqual(1, mock_pgrewind_init.call_count) self.assertEqual(1, mock_pgbasebackup_run.call_count) self.assertEqual(1, mock_pgbasebackup_init.call_count) - self.assertRegexpMatches(gplog.get_logfile(), '/gpsegrecovery.py_\d+\.log') + self.assertRegexpMatches(gplog.get_logfile(), '/gpsegrecovery.pyc?_\d+\.log') @patch('gppylib.commands.pg.PgRewind.__init__', return_value=None) @patch('gppylib.commands.pg.PgRewind.run') @@ -338,7 +338,7 @@ def test_complete_workflow_exception(self, mock_pgbasebackup_run, mock_pgbasebac self.assertEqual(1, mock_pgrewind_init.call_count) self.assertEqual(1, mock_pgbasebackup_run.call_count) self.assertEqual(1, mock_pgbasebackup_init.call_count) - self.assertRegexpMatches(gplog.get_logfile(), '/gpsegrecovery.py_\d+\.log') + self.assertRegexpMatches(gplog.get_logfile(), '/gpsegrecovery.pyc?_\d+\.log') @patch('recovery_base.gplog.setup_tool_logging') @patch('recovery_base.RecoveryBase.main') diff --git a/gpMgmt/bin/gppylib/test/unit/test_unit_gpsegsetuprecovery.py b/gpMgmt/bin/gppylib/test/unit/test_unit_gpsegsetuprecovery.py index 72639d4b69d9..c0021cee1702 100644 --- a/gpMgmt/bin/gppylib/test/unit/test_unit_gpsegsetuprecovery.py +++ b/gpMgmt/bin/gppylib/test/unit/test_unit_gpsegsetuprecovery.py @@ -334,7 +334,7 @@ def test_complete_workflow(self, mock_execsql, mock_dburl, mock_connect, mock_va mock_connect.assert_called_once() mock_execsql.assert_called_once() #TODO use regex pattern - self.assertRegexpMatches(gplog.get_logfile(), '/gpsegsetuprecovery.py_\d+\.log') + self.assertRegexpMatches(gplog.get_logfile(), '/gpsegsetuprecovery.pyc?_\d+\.log') @patch('gpsegsetuprecovery.ValidationForFullRecovery.validate_failover_data_directory') @patch('gpsegsetuprecovery.dbconn.connect') @@ -357,7 +357,7 @@ def test_complete_workflow_exception(self, mock_execsql, mock_dburl, mock_connec mock_validate_datadir.assert_called_once() mock_dburl.assert_called_once() mock_connect.assert_called_once() - self.assertRegexpMatches(gplog.get_logfile(), '/gpsegsetuprecovery.py_\d+\.log') + self.assertRegexpMatches(gplog.get_logfile(), '/gpsegsetuprecovery.pyc?_\d+\.log') @patch('recovery_base.gplog.setup_tool_logging') diff --git a/gpMgmt/bin/gpsd b/gpMgmt/bin/gpsd index 7bd1c735b416..8982b9ec577c 100755 --- a/gpMgmt/bin/gpsd +++ b/gpMgmt/bin/gpsd @@ -6,6 +6,7 @@ import datetime import subprocess import os import platform +import pwd import sys import re from contextlib import closing @@ -208,7 +209,7 @@ def main(): # OK - now let's setup all the arguments & options db = args[0] host = options.host or platform.node() - user = options.user or os.getlogin() + user = options.user or pwd.getpwuid(os.geteuid())[0] port = options.port or '5432' inclSchema = options.dumpSchema inclHLL = options.dumpHLL diff --git a/gpMgmt/bin/minirepro b/gpMgmt/bin/minirepro index 153a55ae5bb7..839bbc674b55 100755 --- a/gpMgmt/bin/minirepro +++ b/gpMgmt/bin/minirepro @@ -59,6 +59,7 @@ EXAMPLE minirepro gptest -h locahost -U gpadmin -p 4444 -q ~/in.sql -f ~/out.sql ''' +import pwd import os, sys, re, json, platform, subprocess from optparse import OptionParser from pygresql import pgdb @@ -331,7 +332,7 @@ def main(): envOpts = os.environ db = args[0] host = options.host or platform.node() - user = options.user or ('PGUSER' in envOpts and envOpts['PGUSER']) or os.getlogin() + user = options.user or ('PGUSER' in envOpts and envOpts['PGUSER']) or pwd.getpwuid(os.geteuid())[0] port = options.port or ('PGPORT' in envOpts and envOpts['PGPORT']) or '5432' query_file = options.query_file output_file = options.output_file diff --git a/gpMgmt/test/README b/gpMgmt/test/README index bf7111ef3a4d..3672c9e3106b 100644 --- a/gpMgmt/test/README +++ b/gpMgmt/test/README @@ -22,6 +22,14 @@ integration tests. # this will run all tests tagged with smoke make -f Makefile.behave behave tags=smoke +# this will run all tests not tagged with concourse_cluster +# (on demo cluster, i.e. cluster on single host) +make -f Makefile.behave behave flags="--tags ~concourse_cluster" + +# this will run all tests tagged with concourse_cluster +# (on concourse cluster, i.e. cluster on several hosts) +make -f Makefile.behave behave flags="--tags concourse_cluster" + # this will run all tests tagged with smoke AND mirrors make -f Makefile.behave behave flags="--tags smoke --tags mirrors" diff --git a/gpMgmt/test/behave/mgmt_utils/cross_subnet.feature b/gpMgmt/test/behave/mgmt_utils/cross_subnet.feature index 17bac22a4f81..5defa151273e 100644 --- a/gpMgmt/test/behave/mgmt_utils/cross_subnet.feature +++ b/gpMgmt/test/behave/mgmt_utils/cross_subnet.feature @@ -1,4 +1,4 @@ -@cross_subnet +@cross_subnet @skip Feature: Tests for a cross_subnet cluster Scenario: gpinitsystem works across subnets diff --git a/gpMgmt/test/behave/mgmt_utils/environment.py b/gpMgmt/test/behave/mgmt_utils/environment.py index b659d67b32ca..8cc64a8a4223 100644 --- a/gpMgmt/test/behave/mgmt_utils/environment.py +++ b/gpMgmt/test/behave/mgmt_utils/environment.py @@ -5,7 +5,7 @@ from behave import use_fixture from test.behave_utils.utils import drop_database_if_exists, start_database_if_not_started,\ - create_database, \ + create_database, is_concourse_cluster, \ run_command, check_user_permissions, run_gpcommand, execute_sql from steps.mirrors_mgmt_utils import MirrorMgmtContext from steps.gpconfig_mgmt_utils import GpConfigContext @@ -20,12 +20,18 @@ def before_all(context): def before_feature(context, feature): # we should be able to run gpexpand without having a cluster initialized - tags_to_skip = ['gpexpand', 'gpaddmirrors', 'gpstate', 'gpmovemirrors', - 'gpconfig', 'gpssh-exkeys', 'gpstop', 'gpinitsystem', 'cross_subnet', - 'gplogfilter'] + tags_to_skip = ['gpexpand', 'gpaddmirrors', + 'gpssh-exkeys', 'gpinitsystem', 'cross_subnet'] + if not is_concourse_cluster(context): + tags_to_skip.append('gpstate') if set(context.feature.tags).intersection(tags_to_skip): return + if not hasattr(context, "cluster_created"): + context.cluster_created = True + from test.behave_utils.ci.fixtures import init_cluster + use_fixture(init_cluster, context) + drop_database_if_exists(context, 'testdb') drop_database_if_exists(context, 'bkdb') drop_database_if_exists(context, 'fullbkdb') @@ -102,10 +108,10 @@ def before_scenario(context, scenario): scenario.skip("skipping scenario tagged with @skip") return - if "concourse_cluster" in scenario.effective_tags and not hasattr(context, "concourse_cluster_created"): - from test.behave_utils.ci.fixtures import init_cluster - context.concourse_cluster_created = True - return use_fixture(init_cluster, context) + if "concourse_cluster" in scenario.effective_tags and \ + "demo_cluster" not in scenario.effective_tags and \ + not is_concourse_cluster(context): + raise Exception("This test can only be run under concourse cluster.") if 'gpmovemirrors' in context.feature.tags: context.mirror_context = MirrorMgmtContext() @@ -134,7 +140,7 @@ def before_scenario(context, scenario): if 'analyzedb' not in context.feature.tags: start_database_if_not_started(context) drop_database_if_exists(context, 'testdb') - if 'gp_bash_functions.sh' in context.feature.tags or 'backup_restore_bashrc' in scenario.effective_tags: + if 'gp_bash_functions' in context.feature.tags or 'backup_restore_bashrc' in scenario.effective_tags: backup_bashrc() def after_scenario(context, scenario): @@ -154,7 +160,7 @@ def after_scenario(context, scenario): And gpstart should return a return code of 0 ''') - if 'gp_bash_functions.sh' in context.feature.tags or 'backup_restore_bashrc' in scenario.effective_tags: + if 'gp_bash_functions' in context.feature.tags or 'backup_restore_bashrc' in scenario.effective_tags: restore_bashrc() # NOTE: gpconfig after_scenario cleanup is in the step `the gpconfig context is setup` diff --git a/gpMgmt/test/behave/mgmt_utils/gp_bash_functions.feature b/gpMgmt/test/behave/mgmt_utils/gp_bash_functions.feature index 35e6629020ef..01bdd3ddaa03 100644 --- a/gpMgmt/test/behave/mgmt_utils/gp_bash_functions.feature +++ b/gpMgmt/test/behave/mgmt_utils/gp_bash_functions.feature @@ -1,4 +1,4 @@ -@gp_bash_functions.sh +@gp_bash_functions Feature: gp_bash_funtions.sh unit test cases Scenario: REMOTE_EXECUTE_AND_GET_OUTPUT returns proper output when no banner is set Given a standard local demo cluster is running diff --git a/gpMgmt/test/behave/mgmt_utils/gpexpand.feature b/gpMgmt/test/behave/mgmt_utils/gpexpand.feature index e19a4514c158..1bf817c00be4 100644 --- a/gpMgmt/test/behave/mgmt_utils/gpexpand.feature +++ b/gpMgmt/test/behave/mgmt_utils/gpexpand.feature @@ -17,10 +17,9 @@ Feature: expand the cluster by adding more segments When the user runs gpexpand interview to add 2 new segment and 0 new host "ignored.host" Then the number of segments have been saved And user has created expansiontest tables - And 4000000 rows are inserted into table "expansiontest0" in schema "public" with column type list "int" And 4000000 rows are inserted into table "expansiontest1" in schema "public" with column type list "int" - And 4000000 rows are inserted into table "expansiontest2" in schema "public" with column type list "int" When the user runs gpexpand with the latest gpexpand_inputfile with additional parameters "--silent" + And add 5 seconds sleep after first table expand And the user runs gpexpand to redistribute with duration "00:00:02" Then gpexpand should print "End time reached. Stopping expansion." to stdout And verify that the cluster has 2 new segments @@ -44,10 +43,9 @@ Feature: expand the cluster by adding more segments And the cluster is setup for an expansion on hosts "cdw,sdw1" When the user runs gpexpand interview to add 2 new segment and 0 new host "ignored.host" Then user has created expansiontest tables - And 4000000 rows are inserted into table "expansiontest0" in schema "public" with column type list "int" And 4000000 rows are inserted into table "expansiontest1" in schema "public" with column type list "int" - And 4000000 rows are inserted into table "expansiontest2" in schema "public" with column type list "int" When the user runs gpexpand with the latest gpexpand_inputfile with additional parameters "--silent" + And add 5 seconds sleep after first table expand When the user runs gpexpand to redistribute with duration "00:00:02" Then gpexpand should print "End time reached. Stopping expansion." to stdout @@ -66,10 +64,9 @@ Feature: expand the cluster by adding more segments When the user runs gpexpand interview to add 2 new segment and 0 new host "ignored.host" Then the number of segments have been saved And user has created expansiontest tables - And 4000000 rows are inserted into table "expansiontest0" in schema "public" with column type list "int" And 4000000 rows are inserted into table "expansiontest1" in schema "public" with column type list "int" - And 4000000 rows are inserted into table "expansiontest2" in schema "public" with column type list "int" When the user runs gpexpand with the latest gpexpand_inputfile with additional parameters "--silent" + And add 5 seconds sleep after first table expand And the user runs gpexpand to redistribute with the --end flag Then gpexpand should print "End time reached. Stopping expansion." to stdout And verify that the cluster has 2 new segments diff --git a/gpMgmt/test/behave/mgmt_utils/gpperfmon.feature b/gpMgmt/test/behave/mgmt_utils/gpperfmon.feature index d96e01063ae5..97900095468f 100644 --- a/gpMgmt/test/behave/mgmt_utils/gpperfmon.feature +++ b/gpMgmt/test/behave/mgmt_utils/gpperfmon.feature @@ -121,6 +121,25 @@ Feature: gpperfmon | debug4 | true | | warning | false | + @gpperfmon_query_history + Scenario Outline: gpperfmon logs db with special characters in name + Given gpperfmon is configured and running in qamode + # escape bugs can reproduce themselves, unless we clear queries_tail + Given _queries_tail.dat is not clogged + Given database with special characters "" is created if not exists + When the user truncates "queries_history" tables in "gpperfmon" + When below sql is executed in "" db + """ + SELECT pg_sleep(20); + """ + Then wait until the history of database with special characters "" appears + And database with special characters "" is dropped if exists + + Examples: + | dbname | + | "ab""c | + | a1!@#$%^ &*()_-+={}\;:"",<.>/? | + @gpperfmon_system_history Scenario: gpperfmon adds to system_history table Given gpperfmon is configured and running in qamode diff --git a/gpMgmt/test/behave/mgmt_utils/gprecoverseg.feature b/gpMgmt/test/behave/mgmt_utils/gprecoverseg.feature index 466e5209ccae..1a49b6f8bcb0 100644 --- a/gpMgmt/test/behave/mgmt_utils/gprecoverseg.feature +++ b/gpMgmt/test/behave/mgmt_utils/gprecoverseg.feature @@ -1,4 +1,5 @@ @gprecoverseg +@concourse_cluster_2 Feature: gprecoverseg tests @demo_cluster @@ -736,6 +737,8 @@ Feature: gprecoverseg tests And user can start transactions And the user runs "gprecoverseg -a" Then gprecoverseg should return a return code of 0 + And the segments are synchronized + And the cluster is rebalanced And the "primary" segment pg_log directory content preserved diff --git a/gpMgmt/test/behave/mgmt_utils/gprecoverseg_newhost.feature b/gpMgmt/test/behave/mgmt_utils/gprecoverseg_newhost.feature index 9d7e9bff306a..383fdc48e67c 100644 --- a/gpMgmt/test/behave/mgmt_utils/gprecoverseg_newhost.feature +++ b/gpMgmt/test/behave/mgmt_utils/gprecoverseg_newhost.feature @@ -1,4 +1,5 @@ @gprecoverseg_newhost +@concourse_cluster_4 Feature: gprecoverseg tests involving migrating to a new host ########################### @concourse_cluster tests ########################### diff --git a/gpMgmt/test/behave/mgmt_utils/gpssh_exkeys.feature b/gpMgmt/test/behave/mgmt_utils/gpssh-exkeys.feature similarity index 100% rename from gpMgmt/test/behave/mgmt_utils/gpssh_exkeys.feature rename to gpMgmt/test/behave/mgmt_utils/gpssh-exkeys.feature diff --git a/gpMgmt/test/behave/mgmt_utils/minirepro.feature b/gpMgmt/test/behave/mgmt_utils/minirepro.feature index e5f8c2e80322..c461a7bdca3a 100644 --- a/gpMgmt/test/behave/mgmt_utils/minirepro.feature +++ b/gpMgmt/test/behave/mgmt_utils/minirepro.feature @@ -1,4 +1,4 @@ -@minirepro @skip +@minirepro Feature: Dump minimum database objects that is related to the query @minirepro_UI @@ -28,7 +28,9 @@ Feature: Dump minimum database objects that is related to the query @minirepro_UI Scenario: Database does not exist Given database "nonedb000" does not exist - When the user runs "minirepro nonedb000 -q ~/test/in.sql -f ~/out.sql" + # Make sure that minirepro doesn't complains about the missing of in.sql. + Given the file "/tmp/in.sql" exists and contains "select 1;" + When the user runs "minirepro nonedb000 -q /tmp/in.sql -f ~/out.sql" Then minirepro error should contain database "nonedb000" does not exist @minirepro_core @@ -43,8 +45,8 @@ Feature: Dump minimum database objects that is related to the query Given the file "/tmp/in.sql" exists and contains "select * from t1; delete from t2;" When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should contain "CREATE TABLE t1" - And the output file "/tmp/out.sql" should contain "CREATE TABLE t2" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t1" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t2" And the output file "/tmp/out.sql" should contain "WHERE relname = 't1'" And the output file "/tmp/out.sql" should contain "WHERE relname = 't2'" And the output file "/tmp/out.sql" should be loaded to database "minidb_tmp" without error @@ -62,9 +64,9 @@ Feature: Dump minimum database objects that is related to the query And the file "/tmp/out.sql" does not exist When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should contain "CREATE TABLE t1" before "CREATE TABLE t3" - And the output file "/tmp/out.sql" should contain "CREATE TABLE t3" before "CREATE VIEW v1" - And the output file "/tmp/out.sql" should not contain "CREATE TABLE t2" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t1" before "CREATE TABLE public.t3" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t3" before "CREATE VIEW public.v1" + And the output file "/tmp/out.sql" should not contain "CREATE TABLE public.t2" And the output file "/tmp/out.sql" should contain "WHERE relname = 't1'" And the output file "/tmp/out.sql" should contain "WHERE relname = 't3'" And the output file "/tmp/out.sql" should contain "Table: t1, Attribute: a" @@ -80,12 +82,12 @@ Feature: Dump minimum database objects that is related to the query And the file "/tmp/out.sql" does not exist When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should contain "CREATE TABLE t1" before "CREATE TABLE t3" - And the output file "/tmp/out.sql" should contain "CREATE TABLE t3" before "CREATE VIEW v1" - And the output file "/tmp/out.sql" should contain "CREATE TABLE t2" before "CREATE TABLE t3" - And the output file "/tmp/out.sql" should contain "CREATE TABLE t3" before "CREATE VIEW v2" - And the output file "/tmp/out.sql" should contain "CREATE VIEW v1" before "CREATE VIEW v3" - And the output file "/tmp/out.sql" should contain "CREATE VIEW v2" before "CREATE VIEW v3" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t1" before "CREATE TABLE public.t3" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t3" before "CREATE VIEW public.v1" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t2" before "CREATE TABLE public.t3" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t3" before "CREATE VIEW public.v2" + And the output file "/tmp/out.sql" should contain "CREATE VIEW public.v1" before "CREATE VIEW public.v3" + And the output file "/tmp/out.sql" should contain "CREATE VIEW public.v2" before "CREATE VIEW public.v3" And the output file "/tmp/out.sql" should contain "WHERE relname = 't1'" And the output file "/tmp/out.sql" should contain "WHERE relname = 't2'" And the output file "/tmp/out.sql" should contain "WHERE relname = 't3'" @@ -104,7 +106,7 @@ Feature: Dump minimum database objects that is related to the query And the file "/tmp/out.sql" does not exist When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should contain "CREATE TABLE t1" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t1" And the output file "/tmp/out.sql" should contain "WHERE relname = 't1'" And the output file "/tmp/out.sql" should contain "Table: t1, Attribute: a" And the output file "/tmp/out.sql" should contain "Table: t1, Attribute: b" @@ -117,7 +119,7 @@ Feature: Dump minimum database objects that is related to the query And the file "/tmp/out.sql" does not exist When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should contain "CREATE TABLE t2" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t2" And the output file "/tmp/out.sql" should contain "WHERE relname = 't2'" And the output file "/tmp/out.sql" should contain "Table: t2, Attribute: c" And the output file "/tmp/out.sql" should contain "Table: t2, Attribute: d" @@ -130,7 +132,7 @@ Feature: Dump minimum database objects that is related to the query And the file "/tmp/out.sql" does not exist When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should contain "CREATE TABLE t3" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t3" And the output file "/tmp/out.sql" should contain "WHERE relname = 't3'" And the output file "/tmp/out.sql" should contain "Table: t3, Attribute: e" And the output file "/tmp/out.sql" should contain "Table: t3, Attribute: f" @@ -143,7 +145,7 @@ Feature: Dump minimum database objects that is related to the query And the file "/tmp/out.sql" does not exist When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should not contain "CREATE TABLE t0" + And the output file "/tmp/out.sql" should not contain "CREATE TABLE public.t0" And the output file "/tmp/out.sql" should be loaded to database "minidb_tmp" without error And the file "/tmp/in.sql" should be executed in database "minidb_tmp" without error @@ -153,8 +155,8 @@ Feature: Dump minimum database objects that is related to the query And the file "/tmp/out.sql" does not exist When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should not contain "CREATE TABLE t0" - And the output file "/tmp/out.sql" should contain "CREATE TABLE t3" + And the output file "/tmp/out.sql" should not contain "CREATE TABLE public.t0" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t3" And the output file "/tmp/out.sql" should contain "WHERE relname = 't3'" And the output file "/tmp/out.sql" should contain "Table: t3, Attribute: e" And the output file "/tmp/out.sql" should contain "Table: t3, Attribute: f" @@ -167,7 +169,7 @@ Feature: Dump minimum database objects that is related to the query And the file "/tmp/out.sql" does not exist When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should contain "CREATE TABLE t2" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t2" And the output file "/tmp/out.sql" should contain "WHERE relname = 't2'" And the output file "/tmp/out.sql" should contain "Table: t2, Attribute: c" And the output file "/tmp/out.sql" should contain "Table: t2, Attribute: d" @@ -180,7 +182,7 @@ Feature: Dump minimum database objects that is related to the query And the file "/tmp/out.sql" does not exist When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should contain "CREATE TABLE t1" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t1" And the output file "/tmp/out.sql" should contain "WHERE relname = 't1'" And the output file "/tmp/out.sql" should contain "Table: t1, Attribute: a" And the output file "/tmp/out.sql" should contain "Table: t1, Attribute: b" @@ -193,7 +195,7 @@ Feature: Dump minimum database objects that is related to the query And the file "/tmp/out.sql" does not exist When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should contain "CREATE TABLE t3" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t3" And the output file "/tmp/out.sql" should contain "WHERE relname = 't3'" And the output file "/tmp/out.sql" should contain "Table: t3, Attribute: e" And the output file "/tmp/out.sql" should contain "Table: t3, Attribute: f" @@ -206,9 +208,9 @@ Feature: Dump minimum database objects that is related to the query And the file "/tmp/out.sql" does not exist When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should contain "CREATE TABLE t2" before "CREATE TABLE t3" - And the output file "/tmp/out.sql" should contain "CREATE TABLE t3" before "CREATE VIEW v2" - And the output file "/tmp/out.sql" should not contain "CREATE TABLE t1" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t2" before "CREATE TABLE public.t3" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t3" before "CREATE VIEW public.v2" + And the output file "/tmp/out.sql" should not contain "CREATE TABLE public.t1" And the output file "/tmp/out.sql" should contain "WHERE relname = 't2'" And the output file "/tmp/out.sql" should contain "WHERE relname = 't3'" And the output file "/tmp/out.sql" should contain "Table: t2, Attribute: c" @@ -244,7 +246,7 @@ Feature: Dump minimum database objects that is related to the query And the file "/tmp/out.sql" does not exist When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should contain "CREATE TABLE t3" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t3" And the output file "/tmp/out.sql" should contain "WHERE relname = 't3'" And the output file "/tmp/out.sql" should contain "Table: t3, Attribute: e" And the output file "/tmp/out.sql" should contain "Table: t3, Attribute: f" @@ -257,7 +259,7 @@ Feature: Dump minimum database objects that is related to the query And the file "/tmp/out.sql" does not exist When the user runs "minirepro minireprodb -q /tmp/in.sql -f /tmp/out.sql" Then the output file "/tmp/out.sql" should exist - And the output file "/tmp/out.sql" should contain "CREATE TABLE t3" + And the output file "/tmp/out.sql" should contain "CREATE TABLE public.t3" And the output file "/tmp/out.sql" should contain "WHERE relname = 't3'" And the output file "/tmp/out.sql" should contain "Table: t3, Attribute: e" And the output file "/tmp/out.sql" should contain "Table: t3, Attribute: f" diff --git a/gpMgmt/test/behave/mgmt_utils/steps/analyzedb_mgmt_utils.py b/gpMgmt/test/behave/mgmt_utils/steps/analyzedb_mgmt_utils.py index 2ce4aacce7d6..dc08ebd4ad25 100644 --- a/gpMgmt/test/behave/mgmt_utils/steps/analyzedb_mgmt_utils.py +++ b/gpMgmt/test/behave/mgmt_utils/steps/analyzedb_mgmt_utils.py @@ -4,6 +4,7 @@ import time from datetime import datetime, timedelta from gppylib.db import dbconn +from contextlib import closing from test.behave_utils.utils import check_schema_exists, check_table_exists, drop_table_if_exists from behave import given, when, then @@ -196,7 +197,8 @@ def impl(context, qualified_table): @then('{num_rows} rows are inserted into table "{tablename}" in schema "{schemaname}" with column type list "{column_type_list}"') @when('{num_rows} rows are inserted into table "{tablename}" in schema "{schemaname}" with column type list "{column_type_list}"') def impl(context, num_rows, tablename, schemaname, column_type_list): - insert_data_into_table(context.conn, schemaname, tablename, column_type_list, num_rows) + with closing(dbconn.connect(dbconn.DbURL(dbname=context.dbname))) as conn: + insert_data_into_table(conn, schemaname, tablename, column_type_list, num_rows) @given('some data is inserted into table "{tablename}" in schema "{schemaname}" with column type list "{column_type_list}"') @when('some data is inserted into table "{tablename}" in schema "{schemaname}" with column type list "{column_type_list}"') diff --git a/gpMgmt/test/behave/mgmt_utils/steps/gpssh_exkeys_mgmt_utils.py b/gpMgmt/test/behave/mgmt_utils/steps/gpssh_exkeys_mgmt_utils.py index 8690aa61ed4b..d92a530c82ef 100644 --- a/gpMgmt/test/behave/mgmt_utils/steps/gpssh_exkeys_mgmt_utils.py +++ b/gpMgmt/test/behave/mgmt_utils/steps/gpssh_exkeys_mgmt_utils.py @@ -57,6 +57,8 @@ def run_exkeys(hosts, capture=False): subprocess.check_call(args) return + if os.path.exists('/.dockerenv'): + return run_cmd(' '.join(args)) # Capture stdout/err for later use, while routing it through tee(1) so that # developers can still see the live stream output. # diff --git a/gpMgmt/test/behave/mgmt_utils/steps/mgmt_utils.py b/gpMgmt/test/behave/mgmt_utils/steps/mgmt_utils.py index 59bf568f5da3..2f995b7745ba 100644 --- a/gpMgmt/test/behave/mgmt_utils/steps/mgmt_utils.py +++ b/gpMgmt/test/behave/mgmt_utils/steps/mgmt_utils.py @@ -46,9 +46,7 @@ from gppylib.parseutils import canonicalize_address default_locale = None -master_data_dir = os.environ.get('MASTER_DATA_DIRECTORY') -if master_data_dir is None: - raise Exception('Please set MASTER_DATA_DIRECTORY in environment') +master_data_dir = None def show_all_installed(gphome): x = platform.linux_distribution() @@ -80,15 +78,24 @@ def create_local_demo_cluster(context, extra_config='', with_mirrors='true', wit num_primaries = os.getenv('NUM_PRIMARY_MIRROR_PAIRS', 3) os.environ['PGPORT'] = '15432' + demoDir = os.path.abspath("%s/../gpAux/gpdemo" % os.getcwd()) + global master_data_dir + master_data_dir = "%s/datadirs/qddir/demoDataDir-1" % demoDir + os.environ['MASTER_DATA_DIRECTORY'] = master_data_dir + cmd = """ cd ../gpAux/gpdemo && export DEMO_PORT_BASE={port_base} && export NUM_PRIMARY_MIRROR_PAIRS={num_primary_mirror_pairs} && + export PGPORT={pgport} && + export MASTER_DATA_DIRECTORY={master_data_dir} && export WITH_STANDBY={with_standby} && export WITH_MIRRORS={with_mirrors} && ./demo_cluster.sh -d && ./demo_cluster.sh -c && {extra_config} ./demo_cluster.sh """.format(port_base=os.getenv('PORT_BASE', 15432), + pgport=os.getenv('PGPORT', 15432), + master_data_dir=os.getenv('MASTER_DATA_DIRECTORY', master_data_dir), num_primary_mirror_pairs=num_primaries, with_mirrors=with_mirrors, with_standby=with_standby, @@ -150,10 +157,6 @@ def impl(context, checksum_toggle): @given('the cluster is generated with "{num_primaries}" primaries only') def impl(context, num_primaries): - os.environ['PGPORT'] = '15432' - demoDir = os.path.abspath("%s/../gpAux/gpdemo" % os.getcwd()) - os.environ['MASTER_DATA_DIRECTORY'] = "%s/datadirs/qddir/demoDataDir-1" % demoDir - create_local_demo_cluster(context, with_mirrors='false', with_standby='false', num_primaries=num_primaries) context.gpexpand_mirrors_enabled = False @@ -283,19 +286,27 @@ def impl(context, checksum_toggle): is_ok = False if not is_ok: - stop_database(context) + stop_database_if_started(context) os.environ['PGPORT'] = '15432' port_base = os.getenv('PORT_BASE', 15432) + demoDir = os.path.abspath("%s/../gpAux/gpdemo" % os.getcwd()) + global master_data_dir + master_data_dir = "%s/datadirs/qddir/demoDataDir-1" % demoDir + os.environ['MASTER_DATA_DIRECTORY'] = master_data_dir cmd = """ cd ../gpAux/gpdemo; \ export DEMO_PORT_BASE={port_base} && \ export NUM_PRIMARY_MIRROR_PAIRS={num_primary_mirror_pairs} && \ + export PGPORT={pgport} && + export MASTER_DATA_DIRECTORY={master_data_dir} && export WITH_MIRRORS={with_mirrors} && \ ./demo_cluster.sh -d && ./demo_cluster.sh -c && \ env EXTRA_CONFIG="HEAP_CHECKSUM={checksum_toggle}" ./demo_cluster.sh """.format(port_base=port_base, + pgport=os.getenv('PGPORT', 15432), + master_data_dir=os.getenv('MASTER_DATA_DIRECTORY', master_data_dir), num_primary_mirror_pairs=os.getenv('NUM_PRIMARY_MIRROR_PAIRS', 3), with_mirrors='true', checksum_toggle=checksum_toggle) @@ -2196,6 +2207,29 @@ def impl(context, dbname): drop_database_if_exists(context, dbname) create_database(context, dbname) +@given('database with special characters "{dbname}" is created if not exists') +@when('database with special characters "{dbname}" is created if not exists') +@then('database with special characters "{dbname}" is created if not exists') +def impl(context, dbname): + context.exception = None + if not check_db_exists(dbname.replace("'", "''")): + createdb_cmd = 'psql -d postgres -c \'CREATE DATABASE "%s";\'' % dbname.replace('"', '""') + run_command(context, createdb_cmd) + if context.exception: + raise context.exception + +@given('database with special characters "{dbname}" is dropped if exists') +@when('database with special characters "{dbname}" is dropped if exists') +@then('database with special characters "{dbname}" is dropped if exists') +def impl(context, dbname): + context.exception = None + if check_db_exists(dbname.replace("'", "''")): + dropdb_cmd = 'psql -d postgres -c \'DROP DATABASE "%s";\'' % dbname.replace('"', '""') + run_command(context, dropdb_cmd) + if context.exception: + raise context.exception + + @then('validate gpcheckcat logs contain skipping ACL and Owner tests') def imp(context): dirname = 'gpAdminLogs' @@ -2513,6 +2547,30 @@ def impl(context, sql, boolean): if _str2bool(result) != _str2bool(boolean): raise Exception("sql output '%s' is not same as '%s'" % (result, boolean)) +@then('wait until the history of database with special characters "{dbname}" appears') +def impl(context, dbname): + escape_dbname = dbname.replace('"', '\\"') + cmd = Command(name='psql', cmdStr='psql --tuples-only -d gpperfmon -c "select count(*) > 0 from queries_history where db=\'%s\';"' % escape_dbname) + start_time = current_time = datetime.now() + result = None + while (current_time - start_time).seconds < 120: + cmd.run() + if cmd.get_return_code() != 0: + break + result = cmd.get_stdout() + if _str2bool(result): + break + time.sleep(2) + current_time = datetime.now() + + if cmd.get_return_code() != 0: + context.ret_code = cmd.get_return_code() + context.error_message = 'psql internal error: %s' % cmd.get_stderr() + check_return_code(context, 0) + else: + if not _str2bool(result): + raise Exception("history of '%s' did not appear" % (dbname)) + @then('check that the result from boolean sql "{sql}" is "{boolean}"') def impl(context, sql, boolean): cmd = Command(name='psql', cmdStr='psql --tuples-only -d gpperfmon -c "%s"' % sql) @@ -2634,6 +2692,14 @@ def impl(context): raise Exception("File: %s is empty" % gpdb_alert_file_path_src) +@given("_queries_tail.dat is not clogged") +def impl(context): + filename = '%s/gpperfmon/data/_queries_tail.dat' % os.getenv("MASTER_DATA_DIRECTORY") + with open(filename, 'w') as f: + f.truncate() + filename = '%s/gpperfmon/data/queries_tail.dat' % os.getenv("MASTER_DATA_DIRECTORY") + with open(filename, 'w') as f: + f.truncate() @then('the file with the fake timestamp no longer exists') def impl(context): @@ -3053,15 +3119,17 @@ def _create_working_directory(context, working_directory, mode=''): os.mkdir(context.working_directory) -def _create_cluster(context, master_host, segment_host_list, hba_hostnames='0', with_mirrors=False, mirroring_configuration='group'): +def _create_cluster(context, master_host, segment_host_list, hba_hostnames='0', with_mirrors=False, mirroring_configuration='group', datadir_prefix='data', port_base='20500', mirror_port_base='21500'): if segment_host_list == "": segment_host_list = [] else: segment_host_list = segment_host_list.split(",") global master_data_dir - master_data_dir = os.path.join(context.working_directory, 'data/master/gpseg-1') + master_data_dir = os.path.join(context.working_directory, datadir_prefix, 'master', 'gpseg-1') os.environ['MASTER_DATA_DIRECTORY'] = master_data_dir + os.environ['PGPORT'] = '10300' + context.datadir_prefix = datadir_prefix try: with dbconn.connect(dbconn.DbURL(dbname='template1'), unsetSearchPath=False) as conn: @@ -3076,7 +3144,7 @@ def _create_cluster(context, master_host, segment_host_list, hba_hostnames='0', except: pass - testcluster = TestCluster(hosts=[master_host]+segment_host_list, base_dir=context.working_directory,hba_hostnames=hba_hostnames) + testcluster = TestCluster(hosts=[master_host]+segment_host_list, base_dir=context.working_directory, hba_hostnames=hba_hostnames, datadir_prefix=datadir_prefix, port_base=port_base, mirror_port_base=mirror_port_base) testcluster.reset_cluster() testcluster.create_cluster(with_mirrors=with_mirrors, mirroring_configuration=mirroring_configuration) context.gpexpand_mirrors_enabled = with_mirrors @@ -3097,6 +3165,10 @@ def impl(context, master_host, segment_host_list, hba_hostnames): def impl(context, master_host, segment_host_list): _create_cluster(context, master_host, segment_host_list, with_mirrors=True, mirroring_configuration='group') +@given('a cluster is created with mirrors on "{master_host}" and "{segment_host_list}" from fixture') +def impl(context, master_host, segment_host_list): + _create_cluster(context, master_host, segment_host_list, with_mirrors=True, mirroring_configuration='group', datadir_prefix='', port_base='20000', mirror_port_base='21000') + @given('a cluster is created with "{mirroring_configuration}" segment mirroring on "{master_host}" and "{segment_host_list}"') def impl(context, mirroring_configuration, master_host, segment_host_list): _create_cluster(context, master_host, segment_host_list, with_mirrors=True, mirroring_configuration=mirroring_configuration) @@ -3241,15 +3313,11 @@ def impl(context): @given('the master pid has been saved') def impl(context): - data_dir = os.path.join(context.working_directory, - 'data/master/gpseg-1') - context.master_pid = gp.get_postmaster_pid_locally(data_dir) + context.master_pid = gp.get_postmaster_pid_locally(master_data_dir) @then('verify that the master pid has not been changed') def impl(context): - data_dir = os.path.join(context.working_directory, - 'data/master/gpseg-1') - current_master_pid = gp.get_postmaster_pid_locally(data_dir) + current_master_pid = gp.get_postmaster_pid_locally(master_data_dir) if context.master_pid == current_master_pid: return @@ -3467,9 +3535,9 @@ def make_temp_dir(context, tmp_base_dir, mode=''): def impl(context, hostnames): hosts = hostnames.split(',') if hasattr(context, "working_directory"): - reset_hosts(hosts, context.working_directory) + reset_hosts(hosts, context.working_directory, context.datadir_prefix) if hasattr(context, "temp_base_dir"): - reset_hosts(hosts, context.temp_base_dir) + reset_hosts(hosts, context.temp_base_dir, context.datadir_prefix) @given('user has created expansiontest tables') @@ -4198,7 +4266,7 @@ def impl(context): cmd.run(validateAfter=True) hostname = cmd.get_stdout() # Update entry in current /etc/hosts file to add new host-address - cmd = Command(name='update hostlist with new hostname', cmdStr="sudo sed 's/%s/%s__1 %s/g' > /tmp/hosts; sudo cp -f /tmp/hosts /etc/hosts;rm /tmp/hosts" + cmd = Command(name='update hostlist with new hostname', cmdStr="sudo sed 's/%s/%s__1 %s/g' > /tmp/hosts && sudo cp -f /tmp/hosts /etc/hosts && rm /tmp/hosts" %(hostname, hostname, hostname)) cmd.run(validateAfter=True) @@ -4271,7 +4339,7 @@ def impl(context): @then('restore /etc/hosts file and cleanup hostlist file') @when('restore /etc/hosts file and cleanup hostlist file') def impl(context): - cmd = "sudo mv -f /tmp/hosts_orig /etc/hosts; rm -f /tmp/clusterConfigFile-1; rm -f /tmp/hostfile--1" + cmd = "sudo cp -f /tmp/hosts_orig /etc/hosts && sudo rm /tmp/hosts_orig && rm -f /tmp/clusterConfigFile-1 && rm -f /tmp/hostfile--1" context.execute_steps(u'''Then the user runs command "%s"''' % cmd) @given('create a gpcheckperf input host file') @@ -4357,13 +4425,13 @@ def impl(context): # Insert data into table and run checkpoint just before syncing pg_control if [[ "\$arguments" == *"pg_xlog"* ]] then - ssh cdw "source /usr/local/greengage-db-devel/greengage_path.sh; psql -c 'INSERT INTO test_recoverseg SELECT generate_series(1, 1000)' -d postgres -p 5432 -h cdw" + ssh cdw "source /usr/local/greengage-db-devel/greengage_path.sh; psql -c 'INSERT INTO test_recoverseg SELECT generate_series(1, 1000)' -d postgres -p {port} -h cdw" # run checkpoint - ssh cdw "source /usr/local/greengage-db-devel/greengage_path.sh; psql -c "CHECKPOINT" -d postgres -p 5432 -h cdw" + ssh cdw "source /usr/local/greengage-db-devel/greengage_path.sh; psql -c 'CHECKPOINT' -d postgres -p {port} -h cdw" fi /usr/bin/rsync \$arguments EOL -""" +""".format(port=os.environ.get("PGPORT")) clear_cmd_cache_script = """ cat >/tmp/clear_cmd_cache.py < 0: + context.execute_steps(u""" + Given the database is not running + And a working directory of the test as '/data/gpdata' + And the user runs command "rm -rf ~/gpAdminLogs/gpinitsystem*" + And a cluster is created with mirrors on "cdw" and "{}" from fixture + """.format(','.join('sdw{}'.format(i + 1) for i in range(segment_hosts_in_cluster)))) + else: + context.execute_steps(u""" + Given the database is not running + And the user runs command "rm -rf ~/gpAdminLogs/gpinitsystem*" + And a standard local demo cluster is created + """) diff --git a/gpMgmt/test/behave_utils/cluster_setup.py b/gpMgmt/test/behave_utils/cluster_setup.py index 61644d15cdc2..6a36319f6df9 100755 --- a/gpMgmt/test/behave_utils/cluster_setup.py +++ b/gpMgmt/test/behave_utils/cluster_setup.py @@ -20,7 +20,7 @@ def run(self, validate=True): class TestCluster: - def __init__(self, hosts = None, base_dir = '/tmp/default_gpinitsystem', hba_hostnames='0'): + def __init__(self, hosts = None, base_dir = '/tmp/default_gpinitsystem', hba_hostnames='0', datadir_prefix='data', port_base='20500', mirror_port_base='21500'): """ hosts: lists of cluster hosts. master host will be assumed to be the first element. base_dir: cluster directory @@ -29,13 +29,14 @@ def __init__(self, hosts = None, base_dir = '/tmp/default_gpinitsystem', hba_hos master_host = 'localhost' segments_host = socket.gethostname() self.hosts = [master_host, segments_host] + self.datadir_prefix = datadir_prefix if hosts: self.hosts = hosts - self.port_base = '20500' + self.port_base = port_base self.master_port = os.environ.get('PGPORT', '10300') - self.mirror_port_base = '21500' + self.mirror_port_base = mirror_port_base self.gpinitconfig_template = local_path('configs/gpinitconfig_template') self.gpinitconfig_mirror_template = local_path('configs/gpinitconfig_mirror_template') @@ -47,9 +48,9 @@ def __init__(self, hosts = None, base_dir = '/tmp/default_gpinitsystem', hba_hos self.hosts_file = os.path.join(self.base_dir, 'hosts') self.gpexpand_file = os.path.join(self.base_dir, 'gpexpand_input') - self.primary_dir = os.path.join(self.base_dir, 'data/primary') - self.mirror_dir = os.path.join(self.base_dir, 'data/mirror') - self.master_dir = os.path.join(self.base_dir, 'data/master') + self.primary_dir = os.path.join(self.base_dir, self.datadir_prefix, 'primary') + self.mirror_dir = os.path.join(self.base_dir, self.datadir_prefix, 'mirror') + self.master_dir = os.path.join(self.base_dir, self.datadir_prefix, 'master') # Test metadata # Whether to do gpinitsystem or not @@ -93,7 +94,7 @@ def _generate_gpinit_config_files(self): substitute_strings_in_file(config_template, self.init_file, transforms) def reset_cluster(self): - reset_hosts(self.hosts, test_base_dir = self.base_dir) + reset_hosts(self.hosts, self.base_dir, self.datadir_prefix) def create_cluster(self, with_mirrors=False, mirroring_configuration='group'): # Generate the config files to initialize the cluster @@ -166,11 +167,11 @@ def run_shell_command(cmdstr, cmdname = 'shell command', results={'rc':0, 'stdou print "command error: %s" % results['stderr'] return results -def reset_hosts(hosts, test_base_dir): +def reset_hosts(hosts, test_base_dir, datadir_prefix): - primary_dir = os.path.join(test_base_dir, 'data', 'primary') - mirror_dir = os.path.join(test_base_dir, 'data', 'mirror') - master_dir = os.path.join(test_base_dir, 'data', 'master') + primary_dir = os.path.join(test_base_dir, datadir_prefix, 'primary') + mirror_dir = os.path.join(test_base_dir, datadir_prefix, 'mirror') + master_dir = os.path.join(test_base_dir, datadir_prefix, 'master') host_args = " ".join(map(lambda x: "-h %s" % x, hosts)) reset_primary_dirs_cmd = "gpssh %s -e 'rm -rf %s; mkdir -p %s'" % (host_args, primary_dir, primary_dir) diff --git a/gpMgmt/test/behave_utils/utils.py b/gpMgmt/test/behave_utils/utils.py index abe4feee8f69..fe416c70f451 100644 --- a/gpMgmt/test/behave_utils/utils.py +++ b/gpMgmt/test/behave_utils/utils.py @@ -25,9 +25,7 @@ PARTITION_START_DATE = '2010-01-01' PARTITION_END_DATE = '2013-01-01' -master_data_dir = os.environ.get('MASTER_DATA_DIRECTORY') -if master_data_dir is None: - raise Exception('MASTER_DATA_DIRECTORY is not set') +master_data_dir = None def execute_sql(dbname, sql): @@ -185,10 +183,12 @@ def check_return_code(context, ret_code): def check_database_is_running(context): - if not 'PGPORT' in os.environ: - raise Exception('PGPORT should be set') + if not 'PGPORT' in os.environ or not 'MASTER_DATA_DIRECTORY' in os.environ: + return False pgport = int(os.environ['PGPORT']) + global master_data_dir + master_data_dir = os.environ['MASTER_DATA_DIRECTORY'] running_status = chk_local_db_running(os.environ.get('MASTER_DATA_DIRECTORY'), pgport) gpdb_running = running_status[0] and running_status[1] and running_status[2] and running_status[3] @@ -272,7 +272,6 @@ def create_database_if_not_exists(context, dbname, host=None, port=0, user=None) if not check_db_exists(dbname, host, port, user): create_database(context, dbname, host, port, user) context.dbname = dbname - context.conn = dbconn.connect(dbconn.DbURL(dbname=context.dbname), unsetSearchPath=False) def create_database(context, dbname=None, host=None, port=0, user=None): LOOPS = 10 @@ -877,3 +876,7 @@ def wait_for_database_dropped(dbname, remaining_attempt = 3000): if remaining_attempt == 0: raise Exception('Unable to drop the database %s !!!') % dbname time.sleep(0.1) + + +def is_concourse_cluster(context): + return context.config.tag_expression.check(context.feature.tags + ["concourse_cluster"]) diff --git a/gpcontrib/Makefile b/gpcontrib/Makefile index 17634644ecf3..7b387cd1bf5c 100644 --- a/gpcontrib/Makefile +++ b/gpcontrib/Makefile @@ -26,7 +26,8 @@ ifeq "$(enable_debug_extensions)" "yes" gp_error_handling \ gp_subtransaction_overflow \ gp_check_functions \ - arenadata_toolkit + arenadata_toolkit \ + temp_tables_stat else recurse_targets = gp_sparse_vector \ gp_distribution_policy \ @@ -39,7 +40,8 @@ else gp_error_handling \ gp_subtransaction_overflow \ gp_check_functions \ - arenadata_toolkit + arenadata_toolkit \ + temp_tables_stat endif ifeq "$(with_zstd)" "yes" @@ -106,4 +108,5 @@ installcheck: $(MAKE) -C gp_check_functions installcheck $(MAKE) -C arenadata_toolkit installcheck $(MAKE) -C arenadata_toolkit/isolation2 installcheck + $(MAKE) -C temp_tables_stat installcheck diff --git a/gpcontrib/arenadata_toolkit/isolation2/Makefile b/gpcontrib/arenadata_toolkit/isolation2/Makefile index fc0a73dc060c..eb8b5de7009f 100644 --- a/gpcontrib/arenadata_toolkit/isolation2/Makefile +++ b/gpcontrib/arenadata_toolkit/isolation2/Makefile @@ -3,6 +3,6 @@ top_builddir = ../../../ ISOLATION2_ROOT = $(top_builddir)/src/test/isolation2 installcheck: - cd $(ISOLATION2_ROOT) && ./pg_isolation2_regress $(EXTRA_REGRESS_OPTS) --psqldir='$(PSQLDIR)' \ + cd $(ISOLATION2_ROOT) && $(MAKE) install && ./pg_isolation2_regress $(EXTRA_REGRESS_OPTS) --psqldir='$(PSQLDIR)' \ --dbname=toolkitisolation --schedule=${CURDIR}/toolkit_schedule --inputdir=${CURDIR} --outputdir=${CURDIR} \ --load-extension=gp_inject_fault --load-extension=plpythonu diff --git a/gpcontrib/temp_tables_stat/.gitignore b/gpcontrib/temp_tables_stat/.gitignore new file mode 100644 index 000000000000..e710f0e47270 --- /dev/null +++ b/gpcontrib/temp_tables_stat/.gitignore @@ -0,0 +1,3 @@ +results/ +regression.diffs +regression.out diff --git a/gpcontrib/temp_tables_stat/Makefile b/gpcontrib/temp_tables_stat/Makefile new file mode 100644 index 000000000000..dddddb810203 --- /dev/null +++ b/gpcontrib/temp_tables_stat/Makefile @@ -0,0 +1,23 @@ +# gpcontrib/temp_tables_stat/Makefile + +MODULE_big = temp_tables_stat +OBJS = $(MODULE_big).o + +EXTENSION = $(MODULE_big) +PGFILEDESC = "Collect and show statistics on temporary tables" + +DATA = $(MODULE_big)--0.1.sql + +ifdef USE_PGXS +PG_CONFIG = pg_config +PGXS := $(shell $(PG_CONFIG) --pgxs) +include $(PGXS) +else +subdir = gpcontrib/temp_tables_stat +top_builddir = ../.. +include $(top_builddir)/src/Makefile.global +include $(top_srcdir)/contrib/contrib-global.mk +endif + +installcheck: + $(pg_isolation2_regress_installcheck) --dbname=temp_tables_stat_isolation temp_tables_stat diff --git a/gpcontrib/temp_tables_stat/README.md b/gpcontrib/temp_tables_stat/README.md new file mode 100644 index 000000000000..3df26fc25af9 --- /dev/null +++ b/gpcontrib/temp_tables_stat/README.md @@ -0,0 +1,44 @@ +# temp_tables_stat + +Sometimes users can create temporary tables which take significant disk space +and we need to know how much the space is being used in each session. +This extension is useful to find out how much disk space is occupied by +temporary tables and which user created them in which session. +The extension tracks the creation and deletion of temporary table files on +segments. The list of files is stored in the shared memory of each segment. +The extension adds the `tts_get_seg_files` function to get the tracked files, +their sizes, user and session where they were created from segments. + +Example + +``` +SELECT * FROM tts_get_seg_files(); +``` + +## How to create the extension + +Add temp_tables_stat to shared_preload_libraries and restart the cluster. + +``` +gpconfig -c shared_preload_libraries -v \ + "$(psql -At -c \ + "SELECT array_to_string( \ + array_append( \ + string_to_array( \ + current_setting('shared_preload_libraries'), \ + ','), \ + 'temp_tables_stat'), \ + ',')" \ + postgres)" +gpstop -ra +``` + +Create the extension in your database. + +``` +CREATE EXTENSION temp_tables_stat; +``` + +## Test + +src/test/isolation2/sql/temp_tables_stat.sql diff --git a/gpcontrib/temp_tables_stat/expected/temp_tables_stat.out b/gpcontrib/temp_tables_stat/expected/temp_tables_stat.out new file mode 100644 index 000000000000..33827eed198c --- /dev/null +++ b/gpcontrib/temp_tables_stat/expected/temp_tables_stat.out @@ -0,0 +1,1543 @@ + +1: CREATE OR REPLACE FUNCTION get_files (OUT user_id_ok bool, OUT cur_sess_id bool, OUT content int2, OUT size int8) RETURNS SETOF record AS $$ SELECT (SELECT a.oid = f.user_id FROM pg_authid a WHERE a.rolname = current_user) user_id_ok, (SELECT s.setting::int = f.sess_id FROM pg_settings s WHERE name = 'gp_session_id') cur_sess_id, content, size FROM tts_get_seg_files() f; -- $$ LANGUAGE SQL; +CREATE + +1: ! mkdir -p /tmp/tts_tblspace; + +1: CREATE TABLESPACE tts_tblspace LOCATION '/tmp/tts_tblspace'; +CREATE + +-- No tables, the files list is empty +1: SELECT * FROM tts_get_seg_files(); + user_id | sess_id | path | content | size +---------+---------+------+---------+------ +(0 rows) + +-- +-- Ordinary heap tables + +-- We can see tables created in the current session +1: CREATE TEMP TABLE t1(i INT) DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------ + t | t | 0 | 0 + t | t | 1 | 0 + t | t | 2 | 0 +(3 rows) +1: CREATE TEMP TABLE ts(i INT) TABLESPACE tts_tblspace DISTRIBUTED BY (i); +CREATE +1: CREATE TEMP TABLE t2(i INT) DISTRIBUTED BY (i); +CREATE +1: CREATE TEMP TABLE t3(i INT) DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------ + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 +(12 rows) +1: DROP TABLE ts; +DROP + +-- We can see tables created in other sessions +2: CREATE TEMP TABLE t1(i INT) DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------ + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | f | 1 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | f | 2 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | f | 0 | 0 +(12 rows) +2: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------ + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | t | 0 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | t | 1 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | t | 2 | 0 +(12 rows) +3: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------ + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 +(12 rows) + +-- Dropped tables are removed from the list in all sessions +1: DROP TABLE t2; +DROP +1: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 9 +(1 row) +2: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 9 +(1 row) +3: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 9 +(1 row) +2: DROP TABLE t1; +DROP +1: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 6 +(1 row) +2: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 6 +(1 row) +3: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 6 +(1 row) +1q: ... +2q: ... +3q: ... + +-- +-- Heap tables, on commit drop + +-- We can see tables created in the current session +1: BEGIN; +BEGIN +1: CREATE TEMP TABLE t1(i INT) ON COMMIT DROP DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------ + t | t | 1 | 0 + t | t | 2 | 0 + t | t | 0 | 0 +(3 rows) +1: CREATE TEMP TABLE ts(i INT) ON COMMIT DROP TABLESPACE tts_tblspace DISTRIBUTED BY (i); +CREATE +1: CREATE TEMP TABLE t2(i INT) ON COMMIT DROP DISTRIBUTED BY (i); +CREATE +1: CREATE TEMP TABLE t3(i INT) ON COMMIT DROP DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------ + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 +(12 rows) + +-- We can see tables created in other sessions +2: BEGIN; +BEGIN +2: CREATE TEMP TABLE t1(i INT) ON COMMIT DROP DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------ + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | f | 2 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | f | 1 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | f | 0 | 0 +(15 rows) +2: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------ + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | t | 2 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | t | 0 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | t | 1 | 0 +(15 rows) +3: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------ + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 +(15 rows) + +-- Dropped tables are removed from the list in all sessions +1: ROLLBACK; +ROLLBACK +1: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 3 +(1 row) +2: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 3 +(1 row) +3: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 3 +(1 row) +2: COMMIT; +COMMIT +1: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 0 +(1 row) +2: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 0 +(1 row) +3: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 0 +(1 row) +1q: ... +2q: ... +3q: ... + +-- +-- Ordinary AO tables +-- 4 files per AO table: data file, pg_aoseg, pg_aovisimap, pg_aovisimap_index + +-- We can see tables created in the current session +1: CREATE TEMP TABLE t1(i INT) WITH (APPENDOPTIMIZED = TRUE) DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 +(12 rows) +1: CREATE TEMP TABLE ts(i INT) WITH (APPENDOPTIMIZED = TRUE) TABLESPACE tts_tblspace DISTRIBUTED BY (i); +CREATE +1: CREATE TEMP TABLE t2(i INT) WITH (APPENDOPTIMIZED = TRUE) DISTRIBUTED BY (i); +CREATE +1: CREATE TEMP TABLE t3(i INT) WITH (APPENDOPTIMIZED = TRUE) DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 +(48 rows) +1: DROP TABLE ts; +DROP + + +-- We can see tables created in other sessions +2: CREATE TEMP TABLE t1(i INT) WITH (APPENDOPTIMIZED = TRUE) DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 +(48 rows) +2: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 +(48 rows) +3: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 +(48 rows) + +-- Dropped tables are removed from the list in all sessions +1: DROP TABLE t2; +DROP +1: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 36 +(1 row) +2: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 36 +(1 row) +3: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 36 +(1 row) +2: DROP TABLE t1; +DROP +1: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 24 +(1 row) +2: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 24 +(1 row) +3: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 24 +(1 row) +1q: ... +2q: ... +3q: ... + +-- +-- AO tables, on commit drop + +-- We can see tables created in the current session +1: BEGIN; +BEGIN +1: CREATE TEMP TABLE t1(i INT) WITH (APPENDOPTIMIZED = TRUE) ON COMMIT DROP DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 +(12 rows) +1: CREATE TEMP TABLE ts(i INT) WITH (APPENDOPTIMIZED = TRUE) ON COMMIT DROP TABLESPACE tts_tblspace DISTRIBUTED BY (i); +CREATE +1: CREATE TEMP TABLE t2(i INT) WITH (APPENDOPTIMIZED = TRUE) ON COMMIT DROP DISTRIBUTED BY (i); +CREATE +1: CREATE TEMP TABLE t3(i INT) WITH (APPENDOPTIMIZED = TRUE) ON COMMIT DROP DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 +(48 rows) + +-- We can see tables created in other sessions +2: BEGIN; +BEGIN +2: CREATE TEMP TABLE t1(i INT) WITH (APPENDOPTIMIZED = TRUE) ON COMMIT DROP DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 +(60 rows) +2: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 +(60 rows) +3: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 +(60 rows) + +-- Dropped tables are removed from the list in all sessions +1: ROLLBACK; +ROLLBACK +1: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 12 +(1 row) +2: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 12 +(1 row) +3: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 12 +(1 row) +2: COMMIT; +COMMIT +1: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 0 +(1 row) +2: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 0 +(1 row) +3: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 0 +(1 row) +1q: ... +2q: ... +3q: ... + +-- +-- Ordinary AOCO tables +-- 4 files per AOCO table: data file, pg_aocsseg, pg_aovisimap, pg_aovisimap_index + +-- We can see tables created in the current session +1: CREATE TEMP TABLE t1(i INT, j INT) WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 +(12 rows) +1: CREATE TEMP TABLE ts(i INT, j INT) WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) TABLESPACE tts_tblspace DISTRIBUTED BY (i); +CREATE +1: CREATE TEMP TABLE t2(i INT, j INT) WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) DISTRIBUTED BY (i); +CREATE +1: CREATE TEMP TABLE t3(i INT, j INT) WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 +(48 rows) +1: DROP TABLE ts; +DROP + +-- We can see tables created in other sessions +2: CREATE TEMP TABLE t1(i INT, j INT) WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 +(48 rows) +2: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 +(48 rows) +3: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 +(48 rows) + +-- Dropped tables are removed from the list in all sessions +1: DROP TABLE t2; +DROP +1: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 36 +(1 row) +2: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 36 +(1 row) +3: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 36 +(1 row) +2: DROP TABLE t1; +DROP +1: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 24 +(1 row) +2: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 24 +(1 row) +3: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 24 +(1 row) +1q: ... +2q: ... +3q: ... + + +-- +-- AOCO tables, on commit drop + +-- We can see tables created in the current session +1: BEGIN; +BEGIN +1: CREATE TEMP TABLE t1(i INT, j INT) WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) ON COMMIT DROP DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 +(12 rows) +1: CREATE TEMP TABLE ts(i INT, j INT) WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) ON COMMIT DROP TABLESPACE tts_tblspace DISTRIBUTED BY (i); +CREATE +1: CREATE TEMP TABLE t2(i INT, j INT) WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) ON COMMIT DROP DISTRIBUTED BY (i); +CREATE +1: CREATE TEMP TABLE t3(i INT, j INT) WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) ON COMMIT DROP DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 +(48 rows) + +-- We can see tables created in other sessions +2: BEGIN; +BEGIN +2: CREATE TEMP TABLE t1(i INT, j INT) WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) ON COMMIT DROP DISTRIBUTED BY (i); +CREATE +1: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 +(60 rows) +2: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 0 + t | t | 1 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 0 + t | t | 0 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 0 + t | t | 2 | 32768 +(60 rows) +3: SELECT * FROM get_files(); + user_id_ok | cur_sess_id | content | size +------------+-------------+---------+------- + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 0 + t | f | 2 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 0 + t | f | 0 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 0 + t | f | 1 | 32768 +(60 rows) + +-- Dropped tables are removed from the list in all sessions +1: ROLLBACK; +ROLLBACK +1: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 12 +(1 row) +2: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 12 +(1 row) +3: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 12 +(1 row) +2: COMMIT; +COMMIT +1: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 0 +(1 row) +2: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 0 +(1 row) +3: SELECT COUNT(*) FROM tts_get_seg_files(); + count +------- + 0 +(1 row) +1q: ... +2q: ... +3q: ... + +-- +-- Check that files size calculation takes into account all the forks +CREATE TEMP TABLE t1 WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) AS SELECT i, i j FROM generate_series(1, 100) i DISTRIBUTED BY (i); +CREATE 100 +-- t1 consists of two colums. Both column files are taken into account +SELECT content, size FROM tts_get_seg_files(); + content | size +---------+------- + 2 | 288 + 2 | 32768 + 2 | 0 + 2 | 32768 + 0 | 384 + 0 | 32768 + 0 | 0 + 0 | 32768 + 1 | 384 + 1 | 32768 + 1 | 0 + 1 | 32768 +(12 rows) +-- Vaccum adds FSM and VM +VACUUM t1; +VACUUM +SELECT content, size FROM tts_get_seg_files(); + content | size +---------+-------- + 1 | 384 + 1 | 163840 + 1 | 0 + 1 | 32768 + 2 | 288 + 2 | 163840 + 2 | 0 + 2 | 32768 + 0 | 384 + 0 | 163840 + 0 | 0 + 0 | 32768 +(12 rows) + +-- +-- Cleanup +DROP TABLESPACE tts_tblspace; +DROP +DROP FUNCTION get_files (OUT user_id_ok bool, OUT cur_sess_id bool, OUT content int2, OUT size int8); +DROP + +DROP EXTENSION temp_tables_stat; +DROP + diff --git a/gpcontrib/temp_tables_stat/sql/temp_tables_stat.sql b/gpcontrib/temp_tables_stat/sql/temp_tables_stat.sql new file mode 100644 index 000000000000..a9de510c7d75 --- /dev/null +++ b/gpcontrib/temp_tables_stat/sql/temp_tables_stat.sql @@ -0,0 +1,284 @@ +-- start_ignore +0: ! gpconfig -c shared_preload_libraries -v "$(psql -At -c "SELECT array_to_string(array_append(string_to_array(current_setting('shared_preload_libraries'), ','), 'temp_tables_stat'), ',')" postgres)"; +0: ! gpstop -raiq; + +1: CREATE EXTENSION IF NOT EXISTS temp_tables_stat; +-- end_ignore + +1: CREATE OR REPLACE FUNCTION get_files +(OUT user_id_ok bool, OUT cur_sess_id bool, OUT content int2, OUT size int8) +RETURNS SETOF record +AS $$ + SELECT (SELECT a.oid = f.user_id + FROM pg_authid a + WHERE a.rolname = current_user) user_id_ok, + (SELECT s.setting::int = f.sess_id + FROM pg_settings s + WHERE name = 'gp_session_id') cur_sess_id, + content, + size + FROM tts_get_seg_files() f; -- +$$ LANGUAGE SQL; + +1: ! mkdir -p /tmp/tts_tblspace; +1: CREATE TABLESPACE tts_tblspace LOCATION '/tmp/tts_tblspace'; + +-- No tables, the files list is empty +1: SELECT * FROM tts_get_seg_files(); + +-- +-- Ordinary heap tables + +-- We can see tables created in the current session +1: CREATE TEMP TABLE t1(i INT) DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +1: CREATE TEMP TABLE ts(i INT) + TABLESPACE tts_tblspace + DISTRIBUTED BY (i); +1: CREATE TEMP TABLE t2(i INT) DISTRIBUTED BY (i); +1: CREATE TEMP TABLE t3(i INT) DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +1: DROP TABLE ts; + +-- We can see tables created in other sessions +2: CREATE TEMP TABLE t1(i INT) DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +2: SELECT * FROM get_files(); +3: SELECT * FROM get_files(); + +-- Dropped tables are removed from the list in all sessions +1: DROP TABLE t2; +1: SELECT COUNT(*) FROM tts_get_seg_files(); +2: SELECT COUNT(*) FROM tts_get_seg_files(); +3: SELECT COUNT(*) FROM tts_get_seg_files(); +2: DROP TABLE t1; +1: SELECT COUNT(*) FROM tts_get_seg_files(); +2: SELECT COUNT(*) FROM tts_get_seg_files(); +3: SELECT COUNT(*) FROM tts_get_seg_files(); +1q: +2q: +3q: + +-- +-- Heap tables, on commit drop + +-- We can see tables created in the current session +1: BEGIN; +1: CREATE TEMP TABLE t1(i INT) ON COMMIT DROP DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +1: CREATE TEMP TABLE ts(i INT) + ON COMMIT DROP + TABLESPACE tts_tblspace + DISTRIBUTED BY (i); +1: CREATE TEMP TABLE t2(i INT) ON COMMIT DROP DISTRIBUTED BY (i); +1: CREATE TEMP TABLE t3(i INT) ON COMMIT DROP DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); + +-- We can see tables created in other sessions +2: BEGIN; +2: CREATE TEMP TABLE t1(i INT) ON COMMIT DROP DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +2: SELECT * FROM get_files(); +3: SELECT * FROM get_files(); + +-- Dropped tables are removed from the list in all sessions +1: ROLLBACK; +1: SELECT COUNT(*) FROM tts_get_seg_files(); +2: SELECT COUNT(*) FROM tts_get_seg_files(); +3: SELECT COUNT(*) FROM tts_get_seg_files(); +2: COMMIT; +1: SELECT COUNT(*) FROM tts_get_seg_files(); +2: SELECT COUNT(*) FROM tts_get_seg_files(); +3: SELECT COUNT(*) FROM tts_get_seg_files(); +1q: +2q: +3q: + +-- +-- Ordinary AO tables +-- 4 files per AO table: data file, pg_aoseg, pg_aovisimap, pg_aovisimap_index + +-- We can see tables created in the current session +1: CREATE TEMP TABLE t1(i INT) WITH (APPENDOPTIMIZED = TRUE) DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +1: CREATE TEMP TABLE ts(i INT) + WITH (APPENDOPTIMIZED = TRUE) + TABLESPACE tts_tblspace + DISTRIBUTED BY (i); +1: CREATE TEMP TABLE t2(i INT) WITH (APPENDOPTIMIZED = TRUE) DISTRIBUTED BY (i); +1: CREATE TEMP TABLE t3(i INT) WITH (APPENDOPTIMIZED = TRUE) DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +1: DROP TABLE ts; + + +-- We can see tables created in other sessions +2: CREATE TEMP TABLE t1(i INT) WITH (APPENDOPTIMIZED = TRUE) DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +2: SELECT * FROM get_files(); +3: SELECT * FROM get_files(); + +-- Dropped tables are removed from the list in all sessions +1: DROP TABLE t2; +1: SELECT COUNT(*) FROM tts_get_seg_files(); +2: SELECT COUNT(*) FROM tts_get_seg_files(); +3: SELECT COUNT(*) FROM tts_get_seg_files(); +2: DROP TABLE t1; +1: SELECT COUNT(*) FROM tts_get_seg_files(); +2: SELECT COUNT(*) FROM tts_get_seg_files(); +3: SELECT COUNT(*) FROM tts_get_seg_files(); +1q: +2q: +3q: + +-- +-- AO tables, on commit drop + +-- We can see tables created in the current session +1: BEGIN; +1: CREATE TEMP TABLE t1(i INT) WITH (APPENDOPTIMIZED = TRUE) ON COMMIT DROP DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +1: CREATE TEMP TABLE ts(i INT) + WITH (APPENDOPTIMIZED = TRUE) + ON COMMIT DROP + TABLESPACE tts_tblspace + DISTRIBUTED BY (i); +1: CREATE TEMP TABLE t2(i INT) WITH (APPENDOPTIMIZED = TRUE) ON COMMIT DROP DISTRIBUTED BY (i); +1: CREATE TEMP TABLE t3(i INT) WITH (APPENDOPTIMIZED = TRUE) ON COMMIT DROP DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); + +-- We can see tables created in other sessions +2: BEGIN; +2: CREATE TEMP TABLE t1(i INT) WITH (APPENDOPTIMIZED = TRUE) ON COMMIT DROP DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +2: SELECT * FROM get_files(); +3: SELECT * FROM get_files(); + +-- Dropped tables are removed from the list in all sessions +1: ROLLBACK; +1: SELECT COUNT(*) FROM tts_get_seg_files(); +2: SELECT COUNT(*) FROM tts_get_seg_files(); +3: SELECT COUNT(*) FROM tts_get_seg_files(); +2: COMMIT; +1: SELECT COUNT(*) FROM tts_get_seg_files(); +2: SELECT COUNT(*) FROM tts_get_seg_files(); +3: SELECT COUNT(*) FROM tts_get_seg_files(); +1q: +2q: +3q: + +-- +-- Ordinary AOCO tables +-- 4 files per AOCO table: data file, pg_aocsseg, pg_aovisimap, pg_aovisimap_index + +-- We can see tables created in the current session +1: CREATE TEMP TABLE t1(i INT, j INT) + WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) + DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +1: CREATE TEMP TABLE ts(i INT, j INT) + WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) + TABLESPACE tts_tblspace + DISTRIBUTED BY (i); +1: CREATE TEMP TABLE t2(i INT, j INT) + WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) + DISTRIBUTED BY (i); +1: CREATE TEMP TABLE t3(i INT, j INT) + WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) + DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +1: DROP TABLE ts; + +-- We can see tables created in other sessions +2: CREATE TEMP TABLE t1(i INT, j INT) + WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) + DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +2: SELECT * FROM get_files(); +3: SELECT * FROM get_files(); + +-- Dropped tables are removed from the list in all sessions +1: DROP TABLE t2; +1: SELECT COUNT(*) FROM tts_get_seg_files(); +2: SELECT COUNT(*) FROM tts_get_seg_files(); +3: SELECT COUNT(*) FROM tts_get_seg_files(); +2: DROP TABLE t1; +1: SELECT COUNT(*) FROM tts_get_seg_files(); +2: SELECT COUNT(*) FROM tts_get_seg_files(); +3: SELECT COUNT(*) FROM tts_get_seg_files(); +1q: +2q: +3q: + + +-- +-- AOCO tables, on commit drop + +-- We can see tables created in the current session +1: BEGIN; +1: CREATE TEMP TABLE t1(i INT, j INT) + WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) + ON COMMIT DROP + DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +1: CREATE TEMP TABLE ts(i INT, j INT) + WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) + ON COMMIT DROP + TABLESPACE tts_tblspace + DISTRIBUTED BY (i); +1: CREATE TEMP TABLE t2(i INT, j INT) + WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) + ON COMMIT DROP + DISTRIBUTED BY (i); +1: CREATE TEMP TABLE t3(i INT, j INT) + WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) + ON COMMIT DROP + DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); + +-- We can see tables created in other sessions +2: BEGIN; +2: CREATE TEMP TABLE t1(i INT, j INT) + WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) + ON COMMIT DROP + DISTRIBUTED BY (i); +1: SELECT * FROM get_files(); +2: SELECT * FROM get_files(); +3: SELECT * FROM get_files(); + +-- Dropped tables are removed from the list in all sessions +1: ROLLBACK; +1: SELECT COUNT(*) FROM tts_get_seg_files(); +2: SELECT COUNT(*) FROM tts_get_seg_files(); +3: SELECT COUNT(*) FROM tts_get_seg_files(); +2: COMMIT; +1: SELECT COUNT(*) FROM tts_get_seg_files(); +2: SELECT COUNT(*) FROM tts_get_seg_files(); +3: SELECT COUNT(*) FROM tts_get_seg_files(); +1q: +2q: +3q: + +-- +-- Check that files size calculation takes into account all the forks +CREATE TEMP TABLE t1 + WITH (APPENDOPTIMIZED = TRUE, ORIENTATION = COLUMN) + AS SELECT i, i j FROM generate_series(1, 100) i + DISTRIBUTED BY (i); +-- t1 consists of two colums. Both column files are taken into account +SELECT content, size FROM tts_get_seg_files(); +-- Vaccum adds FSM and VM +VACUUM t1; +SELECT content, size FROM tts_get_seg_files(); + +-- +-- Cleanup +DROP TABLESPACE tts_tblspace; +DROP FUNCTION get_files +(OUT user_id_ok bool, OUT cur_sess_id bool, OUT content int2, OUT size int8); + +DROP EXTENSION temp_tables_stat; + +-- start_ignore +! gpconfig -c shared_preload_libraries -v "$(psql -At -c "SELECT array_to_string(array_remove(string_to_array(current_setting('shared_preload_libraries'), ','), 'temp_tables_stat'), ',')" postgres)"; +! gpstop -raiq; +-- end_ignore diff --git a/gpcontrib/temp_tables_stat/temp_tables_stat--0.1.sql b/gpcontrib/temp_tables_stat/temp_tables_stat--0.1.sql new file mode 100644 index 000000000000..00b9a2b7eacd --- /dev/null +++ b/gpcontrib/temp_tables_stat/temp_tables_stat--0.1.sql @@ -0,0 +1,8 @@ +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION temp_tables_stat" to load this file. \quit + +CREATE FUNCTION tts_get_seg_files(OUT user_id oid, OUT sess_id int4, OUT path text, OUT content int2, OUT size int8) +RETURNS SETOF RECORD +AS 'MODULE_PATHNAME', 'tts_get_seg_files' +LANGUAGE C +EXECUTE ON ALL SEGMENTS; diff --git a/gpcontrib/temp_tables_stat/temp_tables_stat.c b/gpcontrib/temp_tables_stat/temp_tables_stat.c new file mode 100644 index 000000000000..2814486517f1 --- /dev/null +++ b/gpcontrib/temp_tables_stat/temp_tables_stat.c @@ -0,0 +1,402 @@ +/*---------------------------------------------------------------------- + * + * Greengage Database + * + * Copyright (c) 2025 Greengage Community + * + * Greengage Database is licensed under the Apache License Version 2.0 + * (see LICENSE & NOTICE) and is based on the PostgreSQL Database + * Management System and Greenplum Database. + * + *---------------------------------------------------------------------- + */ +#include "postgres.h" + +#include + +#include "cdb/cdbvars.h" +#include "funcapi.h" +#include "pgstat.h" +#include "storage/dsm.h" +#include "storage/ipc.h" +#include "utils/builtins.h" + +PG_MODULE_MAGIC; + +void _PG_init(void); +void _PG_fini(void); + +static file_create_hook_type prev_file_create_hook = NULL; +static file_unlink_hook_type prev_file_unlink_hook = NULL; +static shmem_startup_hook_type prev_shmem_startup_hook = NULL; + +/* + * RelFileNodeBackend-s for each temp table are stored in the list of arrays. + * The list is located in shared memory. The head node of the list (TTSHeadNode) + * is allocated using ShmemInitStruct. Next nodes (TTSNode) are allocated using + * DSM. The next node is created when array of RelFileNodeBackend-s in + * the previous one is full. It is assumed that array in the head node is large + * enough to contain all RelFileNodeBackend-s in normal case and DSM is used + * very rarely. + */ + +typedef struct TTSNode +{ + dsm_handle next; /* Handle of DSM segment with the next node */ + int num; /* Number of elements in files */ + RelFileNodeBackend files[1000000]; +} TTSNode; + +typedef struct TTSHeadNode +{ + LWLock lock; + TTSNode node; +} TTSHeadNode; + +static TTSHeadNode *head = NULL; /* Head of the list */ + +/* Get next node by current one */ +static TTSNode * +next_node(const TTSNode *node) +{ + dsm_segment *dsm_seg; + + if (node->next == DSM_HANDLE_INVALID) + return NULL; + + dsm_seg = dsm_find_mapping(node->next); + if (dsm_seg == NULL) + { + dsm_seg = dsm_attach(node->next); + dsm_pin_mapping(dsm_seg); + } + + return dsm_segment_address(dsm_seg); +} + +/* + * Returns the last node or a new node if the last one is full. + * Returns NULL when no need to add rnode to the list. + */ +static TTSNode * +get_node_to_append(RelFileNodeBackend rnode) +{ + for (TTSNode *node = &head->node;; node = next_node(node)) + { + /* Don't add rnode when it exists in the list of arrays */ + for (int i = 0; i < node->num; i++) + if (RelFileNodeBackendEquals(rnode, node->files[i])) + return NULL; + + if (node->next != DSM_HANDLE_INVALID) + continue; + + /* Create a new node if the last node is full */ + if (node->num == ARRAY_SIZE(node->files)) + { + dsm_segment *next_seg = dsm_create(sizeof(TTSNode)); + dsm_pin_mapping(next_seg); + node->next = dsm_segment_handle(next_seg); + node = dsm_segment_address(next_seg); + node->next = DSM_HANDLE_INVALID; + node->num = 0; + } + + return node; + } +} + +/* + * This function is called with the same argument when each fork is created. + * Add file info to the list if it is not there. + */ +static void +tts_file_create_hook(RelFileNodeBackend rnode) +{ + TTSNode *node; + + if (prev_file_create_hook) + (*prev_file_create_hook)(rnode); + + if (!RelFileNodeBackendIsTemp(rnode) || head == NULL) + return; + + rnode.backend = MyBackendId; + + LWLockAcquire(&head->lock, LW_EXCLUSIVE); + + node = get_node_to_append(rnode); + if (node != NULL) + node->files[node->num++] = rnode; + + LWLockRelease(&head->lock); +} + +static void +delete_from_ttsnode(TTSNode *node, int index, TTSNode *prev_node) +{ + /* Find the last node */ + TTSNode *last_node = node; + TTSNode *last_prev_node = prev_node; + + while (last_node->next != DSM_HANDLE_INVALID) + { + last_prev_node = last_node; + last_node = next_node(last_node); + } + + /* replace the deleted element with the last one */ + node->files[index] = last_node->files[last_node->num - 1]; + + if (last_node->num > 1) + last_node->num--; + else if (last_node == &head->node) + head->node.num = 0; + else + { + /* + * last_prev_node != NULL because last_node is not head. + * next_node() has been called, so the mapping exists. + */ + dsm_detach(dsm_find_mapping(last_prev_node->next)); + last_prev_node->next = DSM_HANDLE_INVALID; + } +} + +/* This function is called once for all forks. Delete file info from the list */ +static void +tts_file_unlink_hook(RelFileNodeBackend rnode) +{ + if (prev_file_unlink_hook) + (*prev_file_unlink_hook)(rnode); + + if (!RelFileNodeBackendIsTemp(rnode) || head == NULL) + return; + + rnode.backend = MyBackendId; + LWLockAcquire(&head->lock, LW_EXCLUSIVE); + + /* Find rnode in the list of arrays and delete it from the list node */ + for (TTSNode *node = &head->node, *prev_node = NULL; + node != NULL; + prev_node = node, node = next_node(node)) + { + for (int i = 0; i < node->num; i++) + if (RelFileNodeBackendEquals(rnode, node->files[i])) + { + delete_from_ttsnode(node, i, prev_node); + goto lExit; + } + } + +lExit: + LWLockRelease(&head->lock); +} + +/* Postmaster creates a new shared memory space for the head node of the list */ +static void +tts_shmem_startup(void) +{ + bool found; + int tranche_id; + static LWLockTranche tranche; + + if (prev_shmem_startup_hook) + (*prev_shmem_startup_hook)(); + + head = ShmemInitStruct("temp_tables_stat", sizeof(TTSHeadNode), &found); + if (found) + return; + + tranche_id = LWLockNewTrancheId(); + tranche.name = "temp_tables_stat"; + tranche.array_base = &head->lock; + tranche.array_stride = sizeof(head->lock); + LWLockRegisterTranche(tranche_id, &tranche); + LWLockInitialize(&head->lock, tranche_id); + head->node.next = DSM_HANDLE_INVALID; + head->node.num = 0; +} + +/* + * Get size of all files from the dirname directory, which names start + * with fn_start + */ +static int64 +tts_get_file_size(const char *dirname, const char *fn_start) +{ + struct dirent *direntry; + int64 dirsize = 0; + const size_t fn_start_len = strlen(fn_start); + DIR *dirdesc = AllocateDir(dirname); + + if (!dirdesc) + return 0; + + while ((direntry = ReadDir(dirdesc, dirname)) != NULL) + { + struct stat fst; + char fn[MAXPGPATH * 2]; + + CHECK_FOR_INTERRUPTS(); + + if (strcmp(direntry->d_name, ".") == 0 || + strcmp(direntry->d_name, "..") == 0 || + strncmp(direntry->d_name, fn_start, fn_start_len) != 0) + continue; + + snprintf(fn, sizeof(fn), "%s/%s", dirname, direntry->d_name); + + if (stat(fn, &fst) < 0) + continue; + + dirsize += fst.st_size; + } + + FreeDir(dirdesc); + return dirsize; +} + +/* Copy the files info from the list to local memory */ +static RelFileNodeBackend * +get_files(uint32 *files_num) +{ + RelFileNodeBackend *files; + + *files_num = 0; + + LWLockAcquire(&head->lock, LW_SHARED); + + /* Count files of temp tables */ + for (const TTSNode *node = &head->node; node != NULL; node = next_node(node)) + *files_num += node->num; + + /* Allocate local memory for array of the files data */ + files = palloc(sizeof(*files) * (*files_num)); + + /* Combine arrays from the list nodes into one array */ + *files_num = 0; + for (const TTSNode *node = &head->node; node != NULL; node = next_node(node)) + { + RelFileNodeBackend *dst = files + (*files_num); + memcpy(dst, node->files, sizeof(*files) * node->num); + *files_num += node->num; + } + + LWLockRelease(&head->lock); + + return files; +} + +/* Get temp tables files list on segments */ +PG_FUNCTION_INFO_V1(tts_get_seg_files); +Datum +tts_get_seg_files(PG_FUNCTION_ARGS) +{ + enum { NATTR = 5 }; + + FuncCallContext *funcctx; + const PgBackendStatus *beStatus; + const RelFileNodeBackend *file; + char *sep; + char *path; + HeapTuple tuple; + Datum values[NATTR] = {0}; + bool nulls [NATTR] = {0}; + static const PgBackendStatus *beStatuses = NULL; + + if (SRF_IS_FIRSTCALL()) + { + MemoryContext oldcontext; + TupleDesc tupdesc; + + funcctx = SRF_FIRSTCALL_INIT(); + + oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx); + + tupdesc = CreateTemplateTupleDesc(NATTR, false); + TupleDescInitEntry(tupdesc, 1, "user_id", OIDOID, -1, 0); + TupleDescInitEntry(tupdesc, 2, "sess_id", INT4OID, -1, 0); + TupleDescInitEntry(tupdesc, 3, "path", TEXTOID, -1, 0); + TupleDescInitEntry(tupdesc, 4, "content", INT2OID, -1, 0); + TupleDescInitEntry(tupdesc, 5, "size", INT8OID, -1, 0); + + funcctx->tuple_desc = BlessTupleDesc(tupdesc); + + if (head->node.num == 0) + { + MemoryContextSwitchTo(oldcontext); + SRF_RETURN_DONE(funcctx); + } + + funcctx->user_fctx = get_files(&funcctx->max_calls); + MemoryContextSwitchTo(oldcontext); + } + + funcctx = SRF_PERCALL_SETUP(); + + if (funcctx->call_cntr >= funcctx->max_calls) + SRF_RETURN_DONE(funcctx); + + if (beStatuses == NULL) + { + bool found; + Size size = mul_size(sizeof(PgBackendStatus), MaxBackends); + beStatuses = ShmemInitStruct("Backend Status Array", size, &found); + if (!found) + ereport(ERROR, (errmsg("Backend Status Array is not found"))); + } + + file = ((RelFileNodeBackend *) funcctx->user_fctx) + funcctx->call_cntr; + + beStatus = &beStatuses[file->backend - 1]; + values[0] = ObjectIdGetDatum(beStatus->st_userid); + values[1] = Int32GetDatum(beStatus->st_session_id); + path = relpathbackend(file->node, TempRelBackendId, MAIN_FORKNUM); + values[2] = CStringGetTextDatum(path); + values[3] = Int16GetDatum(GpIdentity.segindex); + sep = strrchr(path, '/'); + Assert(sep != NULL); + *sep = '\0'; + values[4] = Int64GetDatum(tts_get_file_size(path, sep + 1)); + pfree(path); + + tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); + + SRF_RETURN_NEXT(funcctx, HeapTupleGetDatum(tuple)); +} + +void +_PG_init(void) +{ + if (!process_shared_preload_libraries_in_progress) + { + ereport(ERROR, + (errmsg("temp_tables_stat is not in shared_preload_libraries"))); + } + + if (IS_QUERY_DISPATCHER()) + return; + + RequestAddinShmemSpace(sizeof(TTSHeadNode)); + + prev_file_create_hook = file_create_hook; + file_create_hook = tts_file_create_hook; + + prev_file_unlink_hook = file_unlink_hook; + file_unlink_hook = tts_file_unlink_hook; + + prev_shmem_startup_hook = shmem_startup_hook; + shmem_startup_hook = tts_shmem_startup; +} + +void +_PG_fini(void) +{ + if (IS_QUERY_DISPATCHER()) + return; + + file_create_hook = prev_file_create_hook; + file_unlink_hook = prev_file_unlink_hook; + shmem_startup_hook = prev_shmem_startup_hook; +} diff --git a/gpcontrib/temp_tables_stat/temp_tables_stat.control b/gpcontrib/temp_tables_stat/temp_tables_stat.control new file mode 100644 index 000000000000..b08ce3480f1e --- /dev/null +++ b/gpcontrib/temp_tables_stat/temp_tables_stat.control @@ -0,0 +1,5 @@ +# temp_tables_stat extension +comment = 'Collect and show statistics on temporary tables' +default_version = '0.1' +module_pathname = '$libdir/temp_tables_stat' +relocatable = true diff --git a/src/Makefile b/src/Makefile index 410873b45e06..bf593082d838 100644 --- a/src/Makefile +++ b/src/Makefile @@ -25,6 +25,7 @@ SUBDIRS = \ pl \ makefiles \ test/regress \ + test/isolation2 \ test/perl # There are too many interdependencies between the subdirectories, so diff --git a/src/Makefile.global.in b/src/Makefile.global.in index ade6431989a7..8080c0a4313a 100644 --- a/src/Makefile.global.in +++ b/src/Makefile.global.in @@ -612,13 +612,18 @@ endif pg_regress_locale_flags = $(if $(ENCODING),--encoding=$(ENCODING)) $(NOLOCALE) pg_regress_check = $(top_builddir)/src/test/regress/pg_regress --inputdir=$(srcdir) --temp-install=./tmp_check --top-builddir=$(top_builddir) $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS) -pg_regress_installcheck = $(top_builddir)/src/test/regress/pg_regress --inputdir=$(srcdir) --psqldir='$(PSQLDIR)' $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS) +pg_regress_installcheck = $(pgxsdir)/src/test/regress/pg_regress --inputdir=$(srcdir) --psqldir='$(PSQLDIR)' $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS) pg_regress_clean_files = results/ regression.diffs regression.out tmp_check/ log/ pg_isolation_regress_check = $(top_builddir)/src/test/isolation/pg_isolation_regress --inputdir=$(srcdir) --temp-install=./tmp_check --top-builddir=$(top_builddir) $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS) pg_isolation_regress_installcheck = $(top_builddir)/src/test/isolation/pg_isolation_regress --inputdir=$(srcdir) --top-builddir=$(top_builddir) $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS) +pg_isolation2_regress_installcheck = \ + $(pgxsdir)/src/test/isolation2/pg_isolation2_regress \ + --inputdir=$(srcdir) \ + --psqldir='$(PSQLDIR)' \ + $(pg_regress_locale_flags) $(EXTRA_REGRESS_OPTS) ########################################################################## # # Customization diff --git a/src/backend/access/aocs/aocs_compaction.c b/src/backend/access/aocs/aocs_compaction.c index e531714c1aa8..e0a1ac998256 100644 --- a/src/backend/access/aocs/aocs_compaction.c +++ b/src/backend/access/aocs/aocs_compaction.c @@ -108,16 +108,24 @@ AOCSSegmentFileTruncateToEOF(Relation aorel, segno = fsinfo->segno; - for (j = 0; j < fsinfo->vpinfo.nEntry; ++j) + /* + * We try to truncate all segment files beyond + * `vpinfo.nEntry`, as we may have non-empty segment files + * left by ADD COLUMN, which was rolled back. It is similar to logic in + * ao_foreach_extent_file(). + */ + for (j = 0; ; ++j) { - int64 segeof; + int64 segeof = 0; char filenamepath[MAXPGPATH]; - AOCSVPInfoEntry *entry; File fd; int32 fileSegNo; - entry = getAOCSVPEntry(fsinfo, j); - segeof = entry->eof; + if (j < fsinfo->vpinfo.nEntry) + { + AOCSVPInfoEntry *entry = getAOCSVPEntry(fsinfo, j); + segeof = entry->eof; + } /* Open and truncate the relation segfile to its eof */ MakeAOSegmentFileName(aorel, segno, j, &fileSegNo, filenamepath); @@ -162,6 +170,9 @@ AOCSSegmentFileTruncateToEOF(Relation aorel, segno, fileSegNo, segeof); + + if (j >= fsinfo->vpinfo.nEntry) + break; } } } diff --git a/src/backend/access/aocs/aocssegfiles.c b/src/backend/access/aocs/aocssegfiles.c index f93e380d248f..6312528c9c53 100644 --- a/src/backend/access/aocs/aocssegfiles.c +++ b/src/backend/access/aocs/aocssegfiles.c @@ -61,8 +61,7 @@ static AOCSFileSegInfo **GetAllAOCSFileSegInfo_pg_aocsseg_rel( - int numOfColumsn, - char *relationName, + Relation rel, Relation pg_aocsseg_rel, Snapshot appendOnlyMetaDataSnapshot, int32 *totalseg); @@ -116,6 +115,7 @@ InsertInitialAOCSFileSegInfo(Relation prel, int32 segno, int32 nvp) segtup = heap_form_tuple(RelationGetDescr(segrel), values, nulls); CatalogTupleInsert(segrel, segtup); + heap_freeze_tuple_wal_logged(segrel, segtup); heap_freetuple(segtup); heap_close(segrel, RowExclusiveLock); @@ -127,6 +127,68 @@ InsertInitialAOCSFileSegInfo(Relation prel, int32 segno, int32 nvp) pfree(values); } +/* + * This is a routine to extract the vpinfo underlying the untoasted datum from + * the pg_aocsseg relation row, given the aocs relation's relnatts, into the supplied + * AOCSFileSegInfo structure. + * + * Sometimes the number of columns represented in the vpinfo inside pg_aocsseg + * the row may not match pg_class.relnatts. For instance, when we do an ADD + * COLUMN operation, we will have lesser number of columns in the table row + * than pg_class.relnatts. + * On the other hand, following an aborted ADD COLUMN operation, + * the number of columns in the table row will be + * greater than pg_class.relnatts. + */ +static void +deformAOCSVPInfo(Relation rel, struct varlena *v, AOCSFileSegInfo *aocs_seginfo) +{ + int16 relnatts = RelationGetNumberOfAttributes(rel); + struct varlena *dv = pg_detoast_datum(v); + int source_size = VARSIZE(dv); + int target_size = aocs_vpinfo_size(relnatts); + + + if (source_size <= target_size) + { + /* The source fits into the target, simply memcpy. */ + memcpy(&aocs_seginfo->vpinfo, dv, source_size); + Assert(aocs_seginfo->vpinfo.nEntry <= relnatts); + } + else + { + /* + * We have more columns represented in the vpinfo recorded inside the + * pg_aocsseg row, than pg_class.relnatts. Perform additional validation + * on these extra column entries and then simply copy over relnatts + * worth of entries from within the datum. + */ + AOCSVPInfo *vpInfo = (AOCSVPInfo *) dv; + + for (int i = relnatts; i < vpInfo->nEntry; ++i) + { + /* + * These extra entries must have be the initial frozen inserts + * from when InsertInitialAOCSFileSegInfo() was called during + * an aborted ADD COLUMN operation. Such entries should have eofs = 0, + * indicating that there is no data. If not, there is something + * seriously wrong. Yell appropriately. + */ + if(vpInfo->entry[i].eof > 0 || vpInfo->entry[i].eof_uncompressed > 0) + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("For relation \"%s\" aborted column %d has non-zero eof %d or non-zero uncompressed eof %d", + RelationGetRelationName(rel), i, (int) vpInfo->entry[i].eof, (int) vpInfo->entry[i].eof_uncompressed))); + } + + memcpy(&aocs_seginfo->vpinfo, dv, aocs_vpinfo_size(relnatts)); + aocs_seginfo->vpinfo.nEntry = relnatts; + } + + if (dv != v) + pfree(dv); +} + /* * GetAOCSFileSegInfo. * @@ -223,15 +285,9 @@ GetAOCSFileSegInfo(Relation prel, seginfo ->state = DatumGetInt16(d[Anum_pg_aocs_state - 1]); Assert(!null[Anum_pg_aocs_vpinfo - 1]); - { - struct varlena *v = (struct varlena *) DatumGetPointer(d[Anum_pg_aocs_vpinfo - 1]); - struct varlena *dv = pg_detoast_datum(v); - - Assert(VARSIZE(dv) <= aocs_vpinfo_size(nvp)); - memcpy(&seginfo->vpinfo, dv, aocs_vpinfo_size(nvp)); - if (dv != v) - pfree(dv); - } + deformAOCSVPInfo(prel, + (struct varlena *) DatumGetPointer(d[Anum_pg_aocs_vpinfo - 1]), + seginfo); pfree(d); pfree(null); @@ -255,9 +311,7 @@ GetAllAOCSFileSegInfo(Relation prel, pg_aocsseg_rel = relation_open(prel->rd_appendonly->segrelid, AccessShareLock); - results = GetAllAOCSFileSegInfo_pg_aocsseg_rel( - RelationGetNumberOfAttributes(prel), - RelationGetRelationName(prel), + results = GetAllAOCSFileSegInfo_pg_aocsseg_rel(prel, pg_aocsseg_rel, appendOnlyMetaDataSnapshot, totalseg); @@ -285,17 +339,13 @@ aocsFileSegInfoCmp(const void *left, const void *right) return 0; } - static AOCSFileSegInfo ** -GetAllAOCSFileSegInfo_pg_aocsseg_rel(int numOfColumns, - char *relationName, +GetAllAOCSFileSegInfo_pg_aocsseg_rel(Relation rel, Relation pg_aocsseg_rel, Snapshot snapshot, int32 *totalseg) { - int32 nvp = numOfColumns; - HeapScanDesc scan; HeapTuple tup; @@ -327,7 +377,7 @@ GetAllAOCSFileSegInfo_pg_aocsseg_rel(int numOfColumns, allseg = (AOCSFileSegInfo **) repalloc(allseg, sizeof(AOCSFileSegInfo *) * seginfo_slot_no); } - aocs_seginfo = (AOCSFileSegInfo *) palloc0(aocsfileseginfo_size(nvp)); + aocs_seginfo = (AOCSFileSegInfo *) palloc0(aocsfileseginfo_size(RelationGetNumberOfAttributes(rel))); allseg[cur_seg] = aocs_seginfo; @@ -364,20 +414,7 @@ GetAllAOCSFileSegInfo_pg_aocsseg_rel(int numOfColumns, aocs_seginfo->state = DatumGetInt16(d[Anum_pg_aocs_state - 1]); Assert(!null[Anum_pg_aocs_vpinfo - 1]); - { - struct varlena *v = (struct varlena *) DatumGetPointer(d[Anum_pg_aocs_vpinfo - 1]); - struct varlena *dv = pg_detoast_datum(v); - - /* - * VARSIZE(dv) may be less than aocs_vpinfo_size, in case of add - * column, we try to do a ctas from old table to new table. - */ - Assert(VARSIZE(dv) <= aocs_vpinfo_size(nvp)); - - memcpy(&aocs_seginfo->vpinfo, dv, VARSIZE(dv)); - if (dv != v) - pfree(dv); - } + deformAOCSVPInfo(rel, (struct varlena *) DatumGetPointer(d[Anum_pg_aocs_vpinfo - 1]), aocs_seginfo); ++cur_seg; } @@ -911,11 +948,15 @@ UpdateAOCSFileSegInfo(AOCSInsertDesc idesc) &null[Anum_pg_aocs_vpinfo - 1]); Assert(!null[Anum_pg_aocs_vpinfo - 1]); - struct varlena *v = (struct varlena *) DatumGetPointer(d_tmp); - struct varlena *dv = pg_detoast_datum(v); - Assert(VARSIZE(dv) == aocs_vpinfo_size(nvp)); - AOCSVPInfo *oldvpinfo = (AOCSVPInfo *) dv; + AOCSFileSegInfo *seginfo; + seginfo = (AOCSFileSegInfo *) palloc0(aocsfileseginfo_size(nvp)); + + deformAOCSVPInfo(prel, + (struct varlena *) DatumGetPointer(d_tmp), + seginfo); + + AOCSVPInfo *oldvpinfo = &seginfo->vpinfo; /* * Number of columns fetched from vpinfo should match number of attributes @@ -961,11 +1002,6 @@ UpdateAOCSFileSegInfo(AOCSInsertDesc idesc) } } - if (dv != v) - { - pfree(dv); - } - d[Anum_pg_aocs_vpinfo - 1] = PointerGetDatum(vpinfo); null[Anum_pg_aocs_vpinfo - 1] = false; repl[Anum_pg_aocs_vpinfo - 1] = true; @@ -976,6 +1012,7 @@ UpdateAOCSFileSegInfo(AOCSInsertDesc idesc) pfree(newtup); pfree(vpinfo); + pfree(seginfo); heap_endscan(scan); heap_close(segrel, RowExclusiveLock); @@ -1334,8 +1371,7 @@ gp_aocsseg_internal(PG_FUNCTION_ARGS, Oid aocsRelOid) pg_aocsseg_rel = heap_open(aocsRel->rd_appendonly->segrelid, AccessShareLock); context->aocsSegfileArray = GetAllAOCSFileSegInfo_pg_aocsseg_rel( - aocsRel->rd_rel->relnatts, - RelationGetRelationName(aocsRel), + aocsRel, pg_aocsseg_rel, appendOnlyMetaDataSnapshot, &context->totalAocsSegFiles); @@ -1544,8 +1580,7 @@ gp_aocsseg_history(PG_FUNCTION_ARGS) pg_aocsseg_rel = heap_open(aocsRel->rd_appendonly->segrelid, AccessShareLock); context->aocsSegfileArray = GetAllAOCSFileSegInfo_pg_aocsseg_rel( - RelationGetNumberOfAttributes(aocsRel), - RelationGetRelationName(aocsRel), + aocsRel, pg_aocsseg_rel, SnapshotAny, //Get ALL tuples from pg_aocsseg_ % including aborted and in - progress ones. & context->totalAocsSegFiles); diff --git a/src/backend/access/appendonly/appendonlywriter.c b/src/backend/access/appendonly/appendonlywriter.c index d6124d62a7c4..bab8aff66432 100644 --- a/src/backend/access/appendonly/appendonlywriter.c +++ b/src/backend/access/appendonly/appendonlywriter.c @@ -2117,6 +2117,7 @@ AtEOXact_AppendOnly_Relation(AORelHashEntry aoentry, TransactionId currentXid) { int i; bool entry_updated = false; + bool aborted = false; /* * Only look at tables that are marked in use currently @@ -2140,6 +2141,11 @@ AtEOXact_AppendOnly_Relation(AORelHashEntry aoentry, TransactionId currentXid) } /* bingo! */ + if (segfilestat->aborted) + { + aborted = true; + } + AtEOXact_AppendOnly_StateTransition(aoentry, i, segfilestat); entry_updated = true; } @@ -2152,16 +2158,13 @@ AtEOXact_AppendOnly_Relation(AORelHashEntry aoentry, TransactionId currentXid) ereportif(Debug_appendonly_print_segfile_choice, LOG, (errmsg("AtEOXact_AppendOnly: updated txns_using_rel, it is now %d", aoentry->txns_using_rel))); - } - if (test_AppendOnlyHash_eviction_vs_just_marking_not_inuse) - { /* - * If no transaction is using this entry, it can be removed if - * hash-table gets full. So perform the same here if the above GUC is - * set. + * If the transaction was aborted, AO hash entry may contain not valid + * data left from the transaction. We remove the hash entry to allow + * the entry re-creation with the correct data on the next hash access. */ - if (!is_entry_in_use_by_other_transactions(aoentry)) + if (aborted && !is_entry_in_use_by_other_transactions(aoentry)) { AORelRemoveHashEntry(aoentry->key.relid); } diff --git a/src/backend/access/transam/test/xact_test.c b/src/backend/access/transam/test/xact_test.c index cbb89b2db3d2..1bfc3a6994f2 100644 --- a/src/backend/access/transam/test/xact_test.c +++ b/src/backend/access/transam/test/xact_test.c @@ -16,6 +16,8 @@ mock_TransactionIdDidAbortForReader(TransactionId xid) return xid > 100; } +#define in_oom_error_trouble(...) (false) + #include "../xact.c" static void diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index c99a8ae10f98..5ab34980c88f 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -1283,6 +1283,9 @@ StandbyTransactionIdIsPrepared(TransactionId xid) * files, so we cannot use ReadTwoPhaseFile() here. Fortunately, this * isn't needed until we try to use Hot Standby. */ + if (Gp_role == GP_ROLE_UTILITY) + return false; + elog(ERROR, "Hot Standby not supported"); #if 0 char *buf; @@ -1883,7 +1886,8 @@ GetOldestPreparedTransaction() void StandbyRecoverPreparedTransactions(bool overwriteOK) { - elog(ERROR, "Hot Standby not supported"); + if (Gp_role != GP_ROLE_UTILITY) + elog(ERROR, "Hot Standby not supported"); } /* diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 6b5acd8cead7..8fc8a42c6d91 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -3423,16 +3423,15 @@ AbortTransaction(void) cdbcomponent_cleanupIdleQEs(false); } - /* - * If memprot decides to kill process, make sure we destroy all processes - * so that all mem/resource will be freed - */ - if (elog_geterrcode() == ERRCODE_GP_MEMPROT_KILL) + /* It's an OOM error. Get rid of all gangs and their resources. */ + if (in_oom_error_trouble()) DisconnectAndDestroyAllGangs(true); /* Release resource group slot at the end of a transaction */ if (ShouldUnassignResGroup()) UnassignResGroup(); + + reset_oom_flag(); } /* diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 70becd09f32f..9818512b650e 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -12100,6 +12100,7 @@ XLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, int reqLen, goto next_record_is_invalid; } + errno = 0; if (read(readFile, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ) { char fname[MAXFNAMELEN]; diff --git a/src/backend/access/transam/xlogutils.c b/src/backend/access/transam/xlogutils.c index b2e915c12c8d..a90400377df5 100644 --- a/src/backend/access/transam/xlogutils.c +++ b/src/backend/access/transam/xlogutils.c @@ -313,6 +313,7 @@ XLogReadBufferExtended(RelFileNode rnode, ForkNumber forknum, /* Open the relation at smgr level */ smgr = smgropen(rnode, InvalidBackendId); + smgr->smgr_which = RELSTORAGE_HEAP; /* * Create the target file if it doesn't already exist. This lets us cope diff --git a/src/backend/catalog/storage.c b/src/backend/catalog/storage.c index e10be851a33b..4c64261be26f 100644 --- a/src/backend/catalog/storage.c +++ b/src/backend/catalog/storage.c @@ -114,6 +114,7 @@ RelationCreateStorage(RelFileNode rnode, char relpersistence, char relstorage) } srel = smgropen(rnode, backend); + srel->smgr_which = relstorage; smgrcreate(srel, MAIN_FORKNUM, false); if (needs_wal) @@ -372,6 +373,7 @@ smgrDoPendingDeletes(bool isCommit) srel = smgropen(pending->relnode.node, pending->relnode.isTempRelation ? TempRelBackendId : InvalidBackendId); + srel->smgr_which = 0; /* allocate the initial array, or extend it, if needed */ if (maxrels == 0) @@ -541,6 +543,7 @@ smgr_redo(XLogRecPtr beginLoc, XLogRecPtr lsn, XLogRecord *record) SMgrRelation reln; reln = smgropen(xlrec->rnode, InvalidBackendId); + reln->smgr_which = 0; smgrcreate(reln, xlrec->forkNum, true); } else if (info == XLOG_SMGR_CREATE_PDL) @@ -563,6 +566,7 @@ smgr_redo(XLogRecPtr beginLoc, XLogRecPtr lsn, XLogRecord *record) }; SMgrRelation reln = smgropen(xlrec->createrec.rnode, InvalidBackendId); + reln->smgr_which = xlrec->relstorage; smgrcreate(reln, xlrec->createrec.forkNum, true); PdlRedoAdd(&pd); @@ -574,6 +578,7 @@ smgr_redo(XLogRecPtr beginLoc, XLogRecPtr lsn, XLogRecord *record) Relation rel; reln = smgropen(xlrec->rnode, InvalidBackendId); + reln->smgr_which = 0; /* * Forcibly create relation if it doesn't exist (which suggests that diff --git a/src/backend/cdb/cdbappendonlystoragewrite.c b/src/backend/cdb/cdbappendonlystoragewrite.c index 8ed3eba8446f..c25d77ba3c71 100755 --- a/src/backend/cdb/cdbappendonlystoragewrite.c +++ b/src/backend/cdb/cdbappendonlystoragewrite.c @@ -266,6 +266,7 @@ AppendOnlyStorageWrite_TransactionCreateFile(AppendOnlyStorageWrite *storageWrit SMgrRelation reln; reln = smgropen(relFileNode->node, relFileNode->backend); + reln->smgr_which = RELSTORAGE_AOROWS; /* The file might already exist. that's OK */ // WALREP_FIXME: Pass isRedo == true, so that you don't get an error if it diff --git a/src/backend/cdb/cdbdtxrecovery.c b/src/backend/cdb/cdbdtxrecovery.c index ec7ea21099da..cd83c41e84ec 100644 --- a/src/backend/cdb/cdbdtxrecovery.c +++ b/src/backend/cdb/cdbdtxrecovery.c @@ -643,11 +643,17 @@ redoDistributedCommitRecord(TMGXACT_LOG *gxact_log) if (i == *shmNumCommittedGxacts) { #ifdef FAULT_INJECTOR + static int save_max_tm_gxacts = -1; + if (save_max_tm_gxacts < 0) + save_max_tm_gxacts = max_tm_gxacts; + if (SIMPLE_FAULT_INJECTOR("standby_gxacts_overflow") == FaultInjectorTypeSkip) { max_tm_gxacts = 1; elog(LOG, "Committed gid array length: %d", *shmNumCommittedGxacts); } + else + max_tm_gxacts = save_max_tm_gxacts; #endif /* diff --git a/src/backend/cdb/cdbllize.c b/src/backend/cdb/cdbllize.c index f860cd09bea3..11eb32f1420f 100644 --- a/src/backend/cdb/cdbllize.c +++ b/src/backend/cdb/cdbllize.c @@ -432,28 +432,16 @@ ParallelizeCorrelatedSubPlanMutator(Node *node, ParallelizeCorrelatedPlanWalkerC if (node == NULL) return NULL; +#ifdef USE_ASSERT_CHECKING if (IsA(node, FunctionScan)) { RangeTblEntry *rte; - ListCell *lc; rte = rt_fetch(((Scan *) node)->scanrelid, ctx->rtable); Assert(rte->rtekind == RTE_FUNCTION); - - foreach(lc, rte->functions) - { - RangeTblFunction *rtfunc = (RangeTblFunction *) lfirst(lc); - - if (rtfunc->funcexpr && - ContainsParamWalker(rtfunc->funcexpr, NULL /* ctx */ ) && ctx->subPlanDistributed) - { - ereport(ERROR, - (errcode(ERRCODE_GP_FEATURE_NOT_YET), - errmsg("cannot parallelize that query yet"), - errdetail("In a subquery FROM clause, a function invocation cannot contain a correlated reference."))); - } - } + Assert(rte->functions == NIL); } +#endif /* * If the ModifyTable node appears inside the correlated Subplan, it has @@ -465,6 +453,7 @@ ParallelizeCorrelatedSubPlanMutator(Node *node, ParallelizeCorrelatedPlanWalkerC if (IsA(node, SeqScan) ||IsA(node, ShareInputScan) ||IsA(node, ExternalScan) + ||IsA(node, FunctionScan) ||(IsA(node, SubqueryScan) && IsA(((SubqueryScan *) node)->subplan, ModifyTable)) ||IsA(node,ModifyTable)) { @@ -479,9 +468,29 @@ ParallelizeCorrelatedSubPlanMutator(Node *node, ParallelizeCorrelatedPlanWalkerC * unnest(array[typoutput, typsend]) from pg_type) then 'upg_catalog.' * else 'pg_catalog.' end) FROM pg_proc p; **/ - Assert(scanPlan->flow); + Assert(scanPlan->flow && ctx->currentPlanFlow); + + if (scanPlan->flow->locustype == CdbLocusType_General) + return node; + if (scanPlan->flow->locustype == CdbLocusType_Entry) - return (Node *) node; + { + if (ctx->currentPlanFlow->locustype == CdbLocusType_Entry) + return node; + + if (ctx->currentPlanFlow->locustype == CdbLocusType_General) + return node; + } + + if (IsA(node, FunctionScan)) + { + FunctionScan *fscan = (FunctionScan *) node; + + if (ContainsParamWalker((Node *) fscan->functions, NULL /* ctx */ )) + ereport(ERROR, + (errcode(ERRCODE_GP_FEATURE_NOT_YET), + errmsg("cannot materialize function with correlated parameters"))); + } /** * Steps: @@ -602,6 +611,13 @@ ParallelizeCorrelatedSubPlanMutator(Node *node, ParallelizeCorrelatedPlanWalkerC broadcastPlan(scanPlan, false /* stable */ , false /* rescannable */ , ctx->currentPlanFlow->numsegments /* numsegments */ ); } + else if (ctx->currentPlanFlow->locustype == CdbLocusType_SegmentGeneral && + scanPlan->flow->locustype == CdbLocusType_Entry) + { + /* We still need broadcast from entry-db to one segment. */ + broadcastPlan(scanPlan, false /* stable */ , false /* rescannable */ , + 1 /* numsegments */ ); + } else { focusPlan(scanPlan, false /* stable */ , false /* rescannable */ ); diff --git a/src/backend/cdb/cdbtm.c b/src/backend/cdb/cdbtm.c index 5b83cf391865..b7fdc2ae3165 100644 --- a/src/backend/cdb/cdbtm.c +++ b/src/backend/cdb/cdbtm.c @@ -1086,7 +1086,12 @@ rollbackDtxTransaction(void) return; } - doNotifyingAbort(); + /* Do we have enough memory for the dispatch? */ + if (!in_oom_error_trouble()) + { + doNotifyingAbort(); + } + clearAndResetGxact(); return; diff --git a/src/backend/cdb/cdbutil.c b/src/backend/cdb/cdbutil.c index 10edeed25aed..b9a63fc61514 100644 --- a/src/backend/cdb/cdbutil.c +++ b/src/backend/cdb/cdbutil.c @@ -920,9 +920,6 @@ cdbcomponent_recycleIdleQE(SegmentDatabaseDescriptor *segdbDesc, bool forceDestr cdbinfo = segdbDesc->segment_database_info; isWriter = segdbDesc->isWriter; - /* update num of active QEs */ - DECR_COUNT(cdbinfo, numActiveQEs); - oldContext = MemoryContextSwitchTo(CdbComponentsContext); if (forceDestroy || !cleanupQE(segdbDesc)) @@ -957,13 +954,24 @@ cdbcomponent_recycleIdleQE(SegmentDatabaseDescriptor *segdbDesc, bool forceDestr lastWriter = cell, cell = lnext(cell)) ; if (lastWriter) + { +#ifdef FAULT_INJECTOR + if (SIMPLE_FAULT_INJECTOR("cdb_freelist_append_oom") == FaultInjectorTypeSkip) + { + ereport(ERROR, (errcode(ERRCODE_GP_MEMPROT_KILL), + errmsg("out of memory was emulated"))); + } +#endif lappend_cell(segdbDesc->segment_database_info->freelist, lastWriter, segdbDesc); + } else segdbDesc->segment_database_info->freelist = lcons(segdbDesc, segdbDesc->segment_database_info->freelist); } + /* update num of active and idle QEs */ + DECR_COUNT(cdbinfo, numActiveQEs); INCR_COUNT(cdbinfo, numIdleQEs); MemoryContextSwitchTo(oldContext); @@ -979,6 +987,8 @@ cdbcomponent_recycleIdleQE(SegmentDatabaseDescriptor *segdbDesc, bool forceDestr markCurrentGxactWriterGangLost(); } + DECR_COUNT(cdbinfo, numActiveQEs); + MemoryContextSwitchTo(oldContext); } diff --git a/src/backend/cdb/dispatcher/cdbconn.c b/src/backend/cdb/dispatcher/cdbconn.c index 26c48b9b0e43..0c1a42893545 100644 --- a/src/backend/cdb/dispatcher/cdbconn.c +++ b/src/backend/cdb/dispatcher/cdbconn.c @@ -100,16 +100,18 @@ cdbconn_createSegmentDescriptor(struct CdbComponentDatabaseInfo *cdbinfo, int id void cdbconn_termSegmentDescriptor(SegmentDatabaseDescriptor *segdbDesc) { - CdbComponentDatabases *cdbs; - Assert(CdbComponentsContext); - cdbs = segdbDesc->segment_database_info->cdbs; + /* Don't bother, since the gang would eventually be destroyed. */ + if (!in_oom_error_trouble()) + { + CdbComponentDatabases *cdbs = segdbDesc->segment_database_info->cdbs; - /* put qe identifier to free list for reuse */ - cdbs->freeCounterList = lappend_int(cdbs->freeCounterList, segdbDesc->identifier); + cdbconn_disconnect(segdbDesc); - cdbconn_disconnect(segdbDesc); + /* Put QE identifier to free list for reuse. */ + cdbs->freeCounterList = lappend_int(cdbs->freeCounterList, segdbDesc->identifier); + } if (segdbDesc->whoami != NULL) { diff --git a/src/backend/cdb/dispatcher/cdbdisp.c b/src/backend/cdb/dispatcher/cdbdisp.c index 4fc6b42a4f2e..924557a63acc 100644 --- a/src/backend/cdb/dispatcher/cdbdisp.c +++ b/src/backend/cdb/dispatcher/cdbdisp.c @@ -327,6 +327,7 @@ cdbdisp_makeDispatcherState(bool isExtendedQuery) handle->dispatcherState->allocatedGangs = NIL; handle->dispatcherState->largestGangSize = 0; handle->dispatcherState->rootGangSize = 0; + handle->dispatcherState->destroyIdleReaderGang = false; return handle->dispatcherState; } @@ -365,8 +366,7 @@ cdbdisp_destroyDispatcherState(CdbDispatcherState *ds) if (!ds) return; #ifdef USE_ASSERT_CHECKING - /* Disallow reentrance. */ - Assert (!ds->isGangDestroying); + Assert(!ds->isGangDestroying || ds->forceDestroyGang); ds->isGangDestroying = true; #endif @@ -403,6 +403,12 @@ cdbdisp_destroyDispatcherState(CdbDispatcherState *ds) RecycleGang(gp, ds->forceDestroyGang); } + /* + * Destroy all the idle reader gangs when flag destroyIdleReaderGang is true + */ + if (ds->destroyIdleReaderGang) + cdbcomponent_cleanupIdleQEs(false); + ds->allocatedGangs = NIL; ds->dispatchParams = NULL; ds->primaryResults = NULL; @@ -516,7 +522,16 @@ cleanup_dispatcher_handle(dispatcher_handle_t *h) return; } - cdbdisp_cancelDispatch(h->dispatcherState); + if (in_oom_error_trouble()) + { + /* We'll reset the session anyway. */ + h->dispatcherState->forceDestroyGang = true; + } + else + { + cdbdisp_cancelDispatch(h->dispatcherState); + } + cdbdisp_destroyDispatcherState(h->dispatcherState); } diff --git a/src/backend/cdb/dispatcher/cdbdisp_async.c b/src/backend/cdb/dispatcher/cdbdisp_async.c index c41dbe55a72d..279b50cc7e34 100644 --- a/src/backend/cdb/dispatcher/cdbdisp_async.c +++ b/src/backend/cdb/dispatcher/cdbdisp_async.c @@ -685,6 +685,8 @@ checkDispatchResult(CdbDispatcherState *ds, int timeout_sec) handlePollSuccess(pParms, fds); } + SIMPLE_FAULT_INJECTOR("check_dispatch_result_end"); + pfree(fds); } diff --git a/src/backend/cdb/dispatcher/cdbdisp_query.c b/src/backend/cdb/dispatcher/cdbdisp_query.c index ff804b1f8c81..5176ca06be0d 100644 --- a/src/backend/cdb/dispatcher/cdbdisp_query.c +++ b/src/backend/cdb/dispatcher/cdbdisp_query.c @@ -485,6 +485,23 @@ cdbdisp_dispatchCommandInternal(DispatchCommandQueryParms *pQueryParms, */ ds = cdbdisp_makeDispatcherState(false); + /* + * Reader gangs use local snapshot to access catalog, as a result, it will + * not synchronize with the global snapshot from write gang which will lead + * to inconsistent visibilty of catalog table. Considering the case: + * + * select * from t, t t1; -- create a reader gang. + * begin; + * create role r1; + * set role r1; -- set command will also dispatched to idle reader gang + * + * When set role command dispatched to reader gang, reader gang cannot see + * the new tuple t1 in catalog table pg_auth. + * To fix this issue, we should drop the idle reader gangs after each + * utility statement which may modify the catalog table. + */ + ds->destroyIdleReaderGang = true; + queryText = buildGpQueryString(pQueryParms, &queryTextLength); /* diff --git a/src/backend/cdb/endpoint/cdbendpoint.c b/src/backend/cdb/endpoint/cdbendpoint.c index d59e6b8f4044..087978f9f46e 100644 --- a/src/backend/cdb/endpoint/cdbendpoint.c +++ b/src/backend/cdb/endpoint/cdbendpoint.c @@ -915,6 +915,37 @@ Endpoint return res; } +/* + * sharedEndpointsContain - Check if there's an endpoint with given receiver pid + * and session id. + */ +bool +sharedEndpointsContain(int receiverPid, int sessionId) +{ + bool res = false; + + Assert(receiverPid != InvalidPid); + Assert(sessionId != InvalidEndpointSessionId); + + LWLockAcquire(ParallelCursorEndpointLock, LW_SHARED); + + for (int i = 0; i < MAX_ENDPOINT_SIZE; ++i) + { + if (!sharedEndpoints[i].empty && + sharedEndpoints[i].sessionID == sessionId && + sharedEndpoints[i].receiverPid == receiverPid && + sharedEndpoints[i].databaseID == MyDatabaseId) + { + res = true; + break; + } + } + + LWLockRelease(ParallelCursorEndpointLock); + + return res; +} + /* * Find the token from the hash table based on given session id and user. */ diff --git a/src/backend/cdb/endpoint/cdbendpointretrieve.c b/src/backend/cdb/endpoint/cdbendpointretrieve.c index 5a0ea62d01ec..a358cd665a0b 100644 --- a/src/backend/cdb/endpoint/cdbendpointretrieve.c +++ b/src/backend/cdb/endpoint/cdbendpointretrieve.c @@ -32,6 +32,7 @@ #include "postgres.h" #include "access/xact.h" +#include "nodes/parsenodes.h" #include "storage/ipc.h" #include "utils/backend_cancel.h" #include "utils/dynahash.h" @@ -156,6 +157,12 @@ AuthEndpoint(Oid userID, const char *tokenStr) return found; } +int +RetrieveSessionId(void) +{ + return RetrieveCtl.sessionID; +} + /* * GetRetrieveStmtTupleDesc - Gets TupleDesc for the given retrieve statement. * @@ -403,6 +410,12 @@ validate_retrieve_endpoint(Endpoint *endpoint, const char *endpointName) endpointName, endpoint->receiverPid), errdetail("An endpoint can only be attached by one retrieving session."))); } + + if (ShouldUseRetrieveResGroup()) + { + /* We should have assigned the resource group already. */ + Assert(ResGroupIsAssigned() || ResGroupIsBypassed()); + } } /* @@ -749,6 +762,15 @@ retrieve_exit_callback(int code, Datum arg) detach_receiver_mq(entry); } entryHTB = NULL; + + /* + * Unassign resource group once at process exit. + * Called here after all endpoint cleanup is done. + */ + if (ShouldUnassignResGroup()) + { + UnassignResGroup(); + } } /* @@ -772,7 +794,15 @@ retrieve_xact_callback(XactEvent ev, void *arg pg_attribute_unused()) retrieve_cancel_action(RetrieveCtl.current_entry, "Endpoint retrieve statement aborted"); finish_retrieve(true); + } + /* + * Unassign resource group once at transaction abort. + * Called here after all endpoint cleanup is done. + */ + if (ShouldUnassignResGroup()) + { + UnassignResGroup(); } } } diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c index 984163fa5a78..c43c3dc9fa6e 100644 --- a/src/backend/commands/dropcmds.c +++ b/src/backend/commands/dropcmds.c @@ -26,6 +26,7 @@ #include "nodes/makefuncs.h" #include "parser/parse_type.h" #include "utils/builtins.h" +#include "utils/guc.h" #include "utils/syscache.h" #include "cdb/cdbvars.h" @@ -57,10 +58,12 @@ RemoveObjects(DropStmt *stmt) ObjectAddresses *objects; ListCell *cell1; ListCell *cell2 = NULL; + ListCell *next; + ListCell *prev = NULL; objects = new_object_addresses(); - foreach(cell1, stmt->objects) + for (cell1 = list_head(stmt->objects); cell1; cell1 = next) { ObjectAddress address; List *objname = lfirst(cell1); @@ -68,6 +71,8 @@ RemoveObjects(DropStmt *stmt) Relation relation = NULL; Oid namespaceId; + next = lnext(cell1); + if (stmt->arguments) { cell2 = (!cell2 ? list_head(stmt->arguments) : lnext(cell2)); @@ -90,6 +95,12 @@ RemoveObjects(DropStmt *stmt) { Assert(stmt->missing_ok); does_not_exist_skipping(stmt->removeType, objname, objargs); + + if (gp_dispatch_drop_always) + prev = cell1; + else + stmt->objects = list_delete_cell(stmt->objects, cell1, prev); + continue; } @@ -129,6 +140,8 @@ RemoveObjects(DropStmt *stmt) heap_close(relation, NoLock); add_exact_object_address(&address, objects); + + prev = cell1; } /* Here we really delete them. */ diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index f8ed7cdd0141..b31f722a56be 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -1199,6 +1199,8 @@ RemoveRelations(DropStmt *drop) ObjectAddresses *objects; char relkind; ListCell *cell; + ListCell *next; + ListCell *prev = NULL; int flags = 0; LOCKMODE lockmode = AccessExclusiveLock; @@ -1266,13 +1268,15 @@ RemoveRelations(DropStmt *drop) /* Lock and validate each relation; build a list of object addresses */ objects = new_object_addresses(); - foreach(cell, drop->objects) + for (cell = list_head(drop->objects); cell; cell = next) { RangeVar *rel = makeRangeVarFromNameList((List *) lfirst(cell)); Oid relOid; ObjectAddress obj; struct DropRelationCallbackState state; + next = lnext(cell); + /* * These next few steps are a great deal like relation_openrv, but we * don't bother building a relcache entry since we don't need it. @@ -1298,6 +1302,13 @@ RemoveRelations(DropStmt *drop) if (!OidIsValid(relOid)) { DropErrorMsgNonExistent(rel, relkind, drop->missing_ok); + Assert(drop->missing_ok); + + if (gp_dispatch_drop_always) + prev = cell; + else + drop->objects = list_delete_cell(drop->objects, cell, prev); + continue; } @@ -1339,6 +1350,8 @@ RemoveRelations(DropStmt *drop) obj.objectSubId = 0; add_exact_object_address(&obj, objects); + + prev = cell; } performMultipleDeletions(objects, drop->behavior, flags); @@ -13156,6 +13169,7 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace, LOCKMODE lockmode) newrnode.relNode = newrelfilenode; newrnode.spcNode = newTableSpace; dstrel = smgropen(newrnode, rel->rd_backend); + dstrel->smgr_which = rel->rd_rel->relstorage; RelationOpenSmgr(rel); diff --git a/src/backend/executor/nodeHashjoin.c b/src/backend/executor/nodeHashjoin.c index 51138b421194..8de1f8eb12e4 100644 --- a/src/backend/executor/nodeHashjoin.c +++ b/src/backend/executor/nodeHashjoin.c @@ -1197,6 +1197,8 @@ ExecHashJoinGetSavedTuple(HashJoinState *hjstate, void ExecReScanHashJoin(HashJoinState *node) { + HashJoinTable hashtable = node->hj_HashTable; + /* * In a multi-batch join, we currently have to do rescans the hard way, * primarily because batch temp files may have already been released. But @@ -1204,12 +1206,12 @@ ExecReScanHashJoin(HashJoinState *node) * inner subnode, then we can just re-use the existing hash table without * rebuilding it. */ - if (node->hj_HashTable != NULL) + if (hashtable != NULL) { - node->hj_HashTable->first_pass = false; + hashtable->first_pass = false; if (node->js.ps.righttree->chgParam == NULL && - !node->hj_HashTable->eagerlyReleased) + !hashtable->eagerlyReleased) { /* * Okay to reuse the hash table; needn't rescan inner, either. @@ -1218,7 +1220,7 @@ ExecReScanHashJoin(HashJoinState *node) * inner-tuple match flags contained in the table. */ if (HJ_FILL_INNER(node)) - ExecHashTableResetMatchFlags(node->hj_HashTable); + ExecHashTableResetMatchFlags(hashtable); /* * Also, we need to reset our state about the emptiness of the @@ -1231,30 +1233,58 @@ ExecReScanHashJoin(HashJoinState *node) */ node->hj_OuterNotEmpty = false; + /* + * Outer batch files have to be cleared before restarting the hash + * join, because they will be written again when batch 0 is + * processed. + */ + if (hashtable->outerBatchFile) + { + for (int i = 0; i < hashtable->nbatch; i++) + { + if (hashtable->outerBatchFile[i]) + { + BufFileClose(hashtable->outerBatchFile[i]); + hashtable->outerBatchFile[i] = NULL; + } + } + } + /* ExecHashJoin can skip the BUILD_HASHTABLE step */ node->hj_JoinState = HJ_NEED_NEW_OUTER; - if (node->hj_HashTable->nbatch > 1) + if (hashtable->nbatch > 1) { + /* + * If we rescan in the middle of a batch, inner batch file for + * the current batch is actually deleted, its contents only + * present in the hash table. We must spill it to disk to not + * lose it. + */ + if (node->reuse_hashtable && + hashtable->innerBatchFile[hashtable->curbatch] == NULL) + { + SpillCurrentBatch(node); + } /* Force reloading batch 0 upon next ExecHashJoin */ - node->hj_HashTable->curbatch = -1; + hashtable->curbatch = -1; } else { /* MPP-1600: reset the batch number */ - node->hj_HashTable->curbatch = 0; + hashtable->curbatch = 0; } } else { /* must destroy and rebuild hash table */ - if (!node->hj_HashTable->eagerlyReleased) + if (!hashtable->eagerlyReleased) { HashState *hashState = (HashState *) innerPlanState(node); - ExecHashTableDestroy(hashState, node->hj_HashTable); + ExecHashTableDestroy(hashState, hashtable); } - pfree(node->hj_HashTable); + pfree(hashtable); node->hj_HashTable = NULL; node->hj_JoinState = HJ_BUILD_HASHTABLE; diff --git a/src/backend/executor/nodeShareInputScan.c b/src/backend/executor/nodeShareInputScan.c index 0a5f19da9ef4..f8e911020256 100644 --- a/src/backend/executor/nodeShareInputScan.c +++ b/src/backend/executor/nodeShareInputScan.c @@ -531,6 +531,7 @@ static int retry_read(int fd, char *buf, int rsize) Assert(rsize > 0); read_retry: + errno = 0; sz = read(fd, buf, rsize); if (sz > 0) return sz; @@ -549,6 +550,7 @@ static int retry_write(int fd, char *buf, int wsize) Assert(wsize > 0); write_retry: + errno = 0; sz = write(fd, buf, wsize); if(sz > 0) return sz; diff --git a/src/backend/gporca/data/dxl/minidump/3WayJoinOnMultiDistributionColumnsTables.mdp b/src/backend/gporca/data/dxl/minidump/3WayJoinOnMultiDistributionColumnsTables.mdp index 06044c94eae1..475951ca45af 100644 --- a/src/backend/gporca/data/dxl/minidump/3WayJoinOnMultiDistributionColumnsTables.mdp +++ b/src/backend/gporca/data/dxl/minidump/3WayJoinOnMultiDistributionColumnsTables.mdp @@ -2762,7 +2762,7 @@ - + @@ -2797,7 +2797,7 @@ - + @@ -2842,7 +2842,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/3WayJoinOnMultiDistributionColumnsTablesNoMotion.mdp b/src/backend/gporca/data/dxl/minidump/3WayJoinOnMultiDistributionColumnsTablesNoMotion.mdp index 54391c6a0c68..4e5cd9228054 100644 --- a/src/backend/gporca/data/dxl/minidump/3WayJoinOnMultiDistributionColumnsTablesNoMotion.mdp +++ b/src/backend/gporca/data/dxl/minidump/3WayJoinOnMultiDistributionColumnsTablesNoMotion.mdp @@ -2762,7 +2762,7 @@ t1.a = t2.a and t2.a = t3.a and t1.b = t3.b and t2.b = t3.b; - + @@ -2797,7 +2797,7 @@ t1.a = t2.a and t2.a = t3.a and t1.b = t3.b and t2.b = t3.b; - + @@ -2842,7 +2842,7 @@ t1.a = t2.a and t2.a = t3.a and t1.b = t3.b and t2.b = t3.b; - + diff --git a/src/backend/gporca/data/dxl/minidump/3WayJoinUsingOperatorsOfNonDefaultOpfamily.mdp b/src/backend/gporca/data/dxl/minidump/3WayJoinUsingOperatorsOfNonDefaultOpfamily.mdp index b0ab8f2b1737..9d0177067ed1 100644 --- a/src/backend/gporca/data/dxl/minidump/3WayJoinUsingOperatorsOfNonDefaultOpfamily.mdp +++ b/src/backend/gporca/data/dxl/minidump/3WayJoinUsingOperatorsOfNonDefaultOpfamily.mdp @@ -396,10 +396,10 @@ - + - + @@ -413,7 +413,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/4WayJoinInferredPredsRemovedWith2Motion.mdp b/src/backend/gporca/data/dxl/minidump/4WayJoinInferredPredsRemovedWith2Motion.mdp index d16f62c4b029..8d586464d0b6 100644 --- a/src/backend/gporca/data/dxl/minidump/4WayJoinInferredPredsRemovedWith2Motion.mdp +++ b/src/backend/gporca/data/dxl/minidump/4WayJoinInferredPredsRemovedWith2Motion.mdp @@ -4649,10 +4649,10 @@ explain select * from cs catalog_sales, it item, sr store_returns, ss store_sale - + - + @@ -4693,7 +4693,7 @@ explain select * from cs catalog_sales, it item, sr store_returns, ss store_sale - + @@ -4744,7 +4744,7 @@ explain select * from cs catalog_sales, it item, sr store_returns, ss store_sale - + @@ -4784,7 +4784,7 @@ explain select * from cs catalog_sales, it item, sr store_returns, ss store_sale - + @@ -4853,7 +4853,7 @@ explain select * from cs catalog_sales, it item, sr store_returns, ss store_sale - + @@ -4876,7 +4876,7 @@ explain select * from cs catalog_sales, it item, sr store_returns, ss store_sale - + diff --git a/src/backend/gporca/data/dxl/minidump/AddPredsInSubqueries.mdp b/src/backend/gporca/data/dxl/minidump/AddPredsInSubqueries.mdp index 1186187c9927..7034e6e9fc11 100644 --- a/src/backend/gporca/data/dxl/minidump/AddPredsInSubqueries.mdp +++ b/src/backend/gporca/data/dxl/minidump/AddPredsInSubqueries.mdp @@ -395,7 +395,7 @@ - + @@ -409,7 +409,7 @@ - + @@ -456,7 +456,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/AnySubqueryWithAllSubqueryInScalar.mdp b/src/backend/gporca/data/dxl/minidump/AnySubqueryWithAllSubqueryInScalar.mdp index aeb7a19a87f9..bf89cd2e3869 100644 --- a/src/backend/gporca/data/dxl/minidump/AnySubqueryWithAllSubqueryInScalar.mdp +++ b/src/backend/gporca/data/dxl/minidump/AnySubqueryWithAllSubqueryInScalar.mdp @@ -445,7 +445,7 @@ - + @@ -456,7 +456,7 @@ - + @@ -492,20 +492,20 @@ - + - + - + @@ -518,7 +518,7 @@ - + @@ -529,7 +529,7 @@ - + @@ -546,7 +546,7 @@ - + @@ -559,7 +559,7 @@ - + @@ -570,12 +570,12 @@ - + - + diff --git a/src/backend/gporca/data/dxl/minidump/AnySubqueryWithSubqueryInScalar.mdp b/src/backend/gporca/data/dxl/minidump/AnySubqueryWithSubqueryInScalar.mdp index 5f2a982eddd8..373a0e79e1bc 100644 --- a/src/backend/gporca/data/dxl/minidump/AnySubqueryWithSubqueryInScalar.mdp +++ b/src/backend/gporca/data/dxl/minidump/AnySubqueryWithSubqueryInScalar.mdp @@ -361,7 +361,7 @@ - + @@ -372,7 +372,7 @@ - + @@ -408,20 +408,20 @@ - + - + - + diff --git a/src/backend/gporca/data/dxl/minidump/BitmapIndex-ChooseHashJoin.mdp b/src/backend/gporca/data/dxl/minidump/BitmapIndex-ChooseHashJoin.mdp index 9d740a9a4ffa..55d14286ea6b 100644 --- a/src/backend/gporca/data/dxl/minidump/BitmapIndex-ChooseHashJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/BitmapIndex-ChooseHashJoin.mdp @@ -3459,7 +3459,7 @@ - + @@ -3479,7 +3479,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/BroadcastSkewedHashjoin.mdp b/src/backend/gporca/data/dxl/minidump/BroadcastSkewedHashjoin.mdp index b9f2191540dc..a75c805a02aa 100644 --- a/src/backend/gporca/data/dxl/minidump/BroadcastSkewedHashjoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/BroadcastSkewedHashjoin.mdp @@ -3114,7 +3114,7 @@ Intent: The join should pick up a Broadcast over Redistribute. The hashjoin is s - + @@ -3134,7 +3134,7 @@ Intent: The join should pick up a Broadcast over Redistribute. The hashjoin is s - + diff --git a/src/backend/gporca/data/dxl/minidump/CArrayExpansionTest/JoinWithInListExpand.mdp b/src/backend/gporca/data/dxl/minidump/CArrayExpansionTest/JoinWithInListExpand.mdp index 8ea4e3ab8803..b72d5adf37ed 100644 --- a/src/backend/gporca/data/dxl/minidump/CArrayExpansionTest/JoinWithInListExpand.mdp +++ b/src/backend/gporca/data/dxl/minidump/CArrayExpansionTest/JoinWithInListExpand.mdp @@ -558,7 +558,7 @@ select a,b from foo, bar where foo.a in (1,2,3,4,5,6) and foo.a = bar.c; - + @@ -572,7 +572,7 @@ select a,b from foo, bar where foo.a in (1,2,3,4,5,6) and foo.a = bar.c; - + diff --git a/src/backend/gporca/data/dxl/minidump/CArrayExpansionTest/JoinWithInListNoExpand.mdp b/src/backend/gporca/data/dxl/minidump/CArrayExpansionTest/JoinWithInListNoExpand.mdp index 805677f90b67..3c5a43f2136d 100644 --- a/src/backend/gporca/data/dxl/minidump/CArrayExpansionTest/JoinWithInListNoExpand.mdp +++ b/src/backend/gporca/data/dxl/minidump/CArrayExpansionTest/JoinWithInListNoExpand.mdp @@ -558,7 +558,7 @@ select a,b from foo, bar where foo.a in (1,2,3,4,5,6) and foo.a = bar.c; - + @@ -572,7 +572,7 @@ select a,b from foo, bar where foo.a in (1,2,3,4,5,6) and foo.a = bar.c; - + diff --git a/src/backend/gporca/data/dxl/minidump/CJoinOrderDPTest/JoinOrderWithDP.mdp b/src/backend/gporca/data/dxl/minidump/CJoinOrderDPTest/JoinOrderWithDP.mdp index acd2519ed0ae..eef46476c611 100644 --- a/src/backend/gporca/data/dxl/minidump/CJoinOrderDPTest/JoinOrderWithDP.mdp +++ b/src/backend/gporca/data/dxl/minidump/CJoinOrderDPTest/JoinOrderWithDP.mdp @@ -3666,7 +3666,7 @@ INNER JOIN (SELECT FOO10.i1 AS i1 FROM foo10 FOO10 WHERE FOO10.i2 = 'EN' ) FOO1 - + @@ -3680,7 +3680,7 @@ INNER JOIN (SELECT FOO10.i1 AS i1 FROM foo10 FOO10 WHERE FOO10.i2 = 'EN' ) FOO1 - + @@ -3719,7 +3719,7 @@ INNER JOIN (SELECT FOO10.i1 AS i1 FROM foo10 FOO10 WHERE FOO10.i2 = 'EN' ) FOO1 - + @@ -3736,7 +3736,7 @@ INNER JOIN (SELECT FOO10.i1 AS i1 FROM foo10 FOO10 WHERE FOO10.i2 = 'EN' ) FOO1 - + @@ -3778,7 +3778,7 @@ INNER JOIN (SELECT FOO10.i1 AS i1 FROM foo10 FOO10 WHERE FOO10.i2 = 'EN' ) FOO1 - + @@ -3798,7 +3798,7 @@ INNER JOIN (SELECT FOO10.i1 AS i1 FROM foo10 FOO10 WHERE FOO10.i2 = 'EN' ) FOO1 - + @@ -3818,13 +3818,49 @@ INNER JOIN (SELECT FOO10.i1 AS i1 FROM foo10 FOO10 WHERE FOO10.i2 = 'EN' ) FOO1 - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3852,7 +3888,7 @@ INNER JOIN (SELECT FOO10.i1 AS i1 FROM foo10 FOO10 WHERE FOO10.i2 = 'EN' ) FOO1 - + @@ -3959,42 +3995,6 @@ INNER JOIN (SELECT FOO10.i1 AS i1 FROM foo10 FOO10 WHERE FOO10.i2 = 'EN' ) FOO1 - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/backend/gporca/data/dxl/minidump/CJoinOrderDPTest/JoinOrderWithOutDP.mdp b/src/backend/gporca/data/dxl/minidump/CJoinOrderDPTest/JoinOrderWithOutDP.mdp index 5a37a3c5a423..851ce181fd5e 100644 --- a/src/backend/gporca/data/dxl/minidump/CJoinOrderDPTest/JoinOrderWithOutDP.mdp +++ b/src/backend/gporca/data/dxl/minidump/CJoinOrderDPTest/JoinOrderWithOutDP.mdp @@ -1764,10 +1764,10 @@ INNER JOIN (SELECT FOO10.i1 AS i1 - + - + @@ -1781,7 +1781,7 @@ INNER JOIN (SELECT FOO10.i1 AS i1 - + @@ -1795,13 +1795,49 @@ INNER JOIN (SELECT FOO10.i1 AS i1 - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1823,7 +1859,7 @@ INNER JOIN (SELECT FOO10.i1 AS i1 - + @@ -1840,13 +1876,49 @@ INNER JOIN (SELECT FOO10.i1 AS i1 - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1871,7 +1943,7 @@ INNER JOIN (SELECT FOO10.i1 AS i1 - + @@ -1891,13 +1963,49 @@ INNER JOIN (SELECT FOO10.i1 AS i1 - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1925,7 +2033,7 @@ INNER JOIN (SELECT FOO10.i1 AS i1 - + @@ -1952,9 +2060,9 @@ INNER JOIN (SELECT FOO10.i1 AS i1 - + - + @@ -1977,23 +2085,55 @@ INNER JOIN (SELECT FOO10.i1 AS i1 - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -2002,6 +2142,11 @@ INNER JOIN (SELECT FOO10.i1 AS i1 + + + + + @@ -2029,121 +2174,13 @@ INNER JOIN (SELECT FOO10.i1 AS i1 - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/NoOpMotionUsesOnlyGroupOutputColumns.mdp b/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/NoOpMotionUsesOnlyGroupOutputColumns.mdp index 1a5cf7967191..b783e5339c20 100644 --- a/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/NoOpMotionUsesOnlyGroupOutputColumns.mdp +++ b/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/NoOpMotionUsesOnlyGroupOutputColumns.mdp @@ -280,7 +280,7 @@ EXPLAIN SELECT b, a FROM foo UNION ALL SELECT b, a FROM foo INTERSECT ALL SELECT - + @@ -294,7 +294,7 @@ EXPLAIN SELECT b, a FROM foo UNION ALL SELECT b, a FROM foo INTERSECT ALL SELECT - + @@ -354,7 +354,7 @@ EXPLAIN SELECT b, a FROM foo UNION ALL SELECT b, a FROM foo INTERSECT ALL SELECT - + @@ -373,7 +373,7 @@ EXPLAIN SELECT b, a FROM foo UNION ALL SELECT b, a FROM foo INTERSECT ALL SELECT - + diff --git a/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/RedundantMotionParallelUnionAll.mdp b/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/RedundantMotionParallelUnionAll.mdp index f3fca3c3b9ec..f667b16ce001 100644 --- a/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/RedundantMotionParallelUnionAll.mdp +++ b/src/backend/gporca/data/dxl/minidump/CPhysicalParallelUnionAllTest/RedundantMotionParallelUnionAll.mdp @@ -338,7 +338,7 @@ select * from t, (select * from t union all select * from t) tt where t.c = tt.c - + @@ -358,7 +358,7 @@ select * from t, (select * from t union all select * from t) tt where t.c = tt.c - + diff --git a/src/backend/gporca/data/dxl/minidump/CTAS-With-Global-Local-Agg.mdp b/src/backend/gporca/data/dxl/minidump/CTAS-With-Global-Local-Agg.mdp index ab8105763192..f4ba34106361 100644 --- a/src/backend/gporca/data/dxl/minidump/CTAS-With-Global-Local-Agg.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTAS-With-Global-Local-Agg.mdp @@ -710,10 +710,10 @@ - + - + @@ -727,7 +727,7 @@ - + @@ -741,7 +741,7 @@ - + @@ -752,7 +752,7 @@ - + @@ -770,7 +770,7 @@ - + @@ -781,7 +781,7 @@ - + @@ -799,7 +799,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTE-4.mdp b/src/backend/gporca/data/dxl/minidump/CTE-4.mdp index 18b2a55be650..3d9d2722fd0a 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE-4.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE-4.mdp @@ -274,7 +274,7 @@ - + @@ -294,7 +294,7 @@ - + @@ -352,7 +352,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTE-5.mdp b/src/backend/gporca/data/dxl/minidump/CTE-5.mdp index b4c7ba98385c..cfc937601821 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE-5.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE-5.mdp @@ -457,7 +457,7 @@ - + @@ -483,7 +483,7 @@ - + @@ -514,7 +514,7 @@ - + @@ -534,7 +534,7 @@ - + @@ -552,7 +552,7 @@ - + @@ -570,7 +570,7 @@ - + @@ -657,7 +657,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTE-Join-Redistribute-Producer.mdp b/src/backend/gporca/data/dxl/minidump/CTE-Join-Redistribute-Producer.mdp index 0c9fe27c814d..a4a1309b8b04 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE-Join-Redistribute-Producer.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE-Join-Redistribute-Producer.mdp @@ -413,7 +413,7 @@ with v as (select * from t1) select * from v v1, v v2 where v1.b=v2.b; - + @@ -433,7 +433,7 @@ with v as (select * from t1) select * from v v1, v v2 where v1.b=v2.b; - + @@ -511,7 +511,7 @@ with v as (select * from t1) select * from v v1, v v2 where v1.b=v2.b; - + diff --git a/src/backend/gporca/data/dxl/minidump/CTE-NoPushProperties.mdp b/src/backend/gporca/data/dxl/minidump/CTE-NoPushProperties.mdp index 436d6cada583..b33efdce81f7 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE-NoPushProperties.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE-NoPushProperties.mdp @@ -1110,7 +1110,7 @@ - + @@ -1136,7 +1136,7 @@ - + @@ -1244,7 +1244,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTE-PushProperties.mdp b/src/backend/gporca/data/dxl/minidump/CTE-PushProperties.mdp index a8a3e0b73786..7c79a0383d5e 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE-PushProperties.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE-PushProperties.mdp @@ -1100,7 +1100,7 @@ - + @@ -1126,7 +1126,7 @@ - + @@ -1260,7 +1260,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTE-volatile.mdp b/src/backend/gporca/data/dxl/minidump/CTE-volatile.mdp index e8d0a788bec2..31686aebd31c 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE-volatile.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE-volatile.mdp @@ -413,7 +413,7 @@ - + @@ -433,7 +433,7 @@ - + @@ -523,7 +523,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTE15HAReplicated.mdp b/src/backend/gporca/data/dxl/minidump/CTE15HAReplicated.mdp index d9d3f7db9c7d..5ed0472b73a2 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE15HAReplicated.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE15HAReplicated.mdp @@ -416,10 +416,10 @@ - + - + @@ -436,7 +436,7 @@ - + @@ -516,7 +516,7 @@ - + @@ -593,7 +593,7 @@ - + @@ -609,7 +609,7 @@ - + @@ -674,7 +674,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTE15Replicated.mdp b/src/backend/gporca/data/dxl/minidump/CTE15Replicated.mdp index 9ca88440bfb9..c4769642361a 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE15Replicated.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE15Replicated.mdp @@ -429,10 +429,10 @@ - + - + @@ -449,7 +449,7 @@ - + @@ -545,7 +545,7 @@ - + @@ -622,7 +622,7 @@ - + @@ -638,7 +638,7 @@ - + @@ -703,7 +703,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTE25Replicated.mdp b/src/backend/gporca/data/dxl/minidump/CTE25Replicated.mdp index b232e19e35d0..47459a772912 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE25Replicated.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE25Replicated.mdp @@ -406,10 +406,10 @@ - + - + @@ -426,7 +426,7 @@ - + @@ -514,7 +514,7 @@ - + @@ -529,7 +529,7 @@ - + @@ -538,7 +538,7 @@ - + @@ -555,7 +555,7 @@ - + @@ -649,7 +649,7 @@ - + @@ -666,7 +666,7 @@ - + @@ -724,7 +724,7 @@ - + @@ -738,7 +738,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTE2HAReplicated.mdp b/src/backend/gporca/data/dxl/minidump/CTE2HAReplicated.mdp index 01b70c864463..e3adf6d4c862 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE2HAReplicated.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE2HAReplicated.mdp @@ -385,10 +385,10 @@ - + - + @@ -405,7 +405,7 @@ - + @@ -485,7 +485,7 @@ - + @@ -500,7 +500,7 @@ - + @@ -509,7 +509,7 @@ - + @@ -520,13 +520,23 @@ - + + + + + + + + + + + - + @@ -602,21 +612,11 @@ - - - - - - - - - - - + @@ -700,7 +700,7 @@ - + @@ -722,7 +722,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTE2Replicated.mdp b/src/backend/gporca/data/dxl/minidump/CTE2Replicated.mdp index e57fdf24ef56..69b92b0fc41c 100644 --- a/src/backend/gporca/data/dxl/minidump/CTE2Replicated.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTE2Replicated.mdp @@ -398,10 +398,10 @@ - + - + @@ -418,7 +418,7 @@ - + @@ -514,7 +514,7 @@ - + @@ -529,7 +529,7 @@ - + @@ -538,7 +538,7 @@ - + @@ -549,13 +549,23 @@ - + + + + + + + + + + + - + @@ -631,21 +641,11 @@ - - - - - - - - - - - + @@ -729,7 +729,7 @@ - + @@ -751,7 +751,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTEMergeGroupsCircularDeriveStats.mdp b/src/backend/gporca/data/dxl/minidump/CTEMergeGroupsCircularDeriveStats.mdp index 8a832e348f4d..20b72323e6db 100644 --- a/src/backend/gporca/data/dxl/minidump/CTEMergeGroupsCircularDeriveStats.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTEMergeGroupsCircularDeriveStats.mdp @@ -254,7 +254,7 @@ - + @@ -274,7 +274,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTEMergeGroupsCircularDeriveStats2.mdp b/src/backend/gporca/data/dxl/minidump/CTEMergeGroupsCircularDeriveStats2.mdp new file mode 100644 index 000000000000..68c8400dd801 --- /dev/null +++ b/src/backend/gporca/data/dxl/minidump/CTEMergeGroupsCircularDeriveStats2.mdp @@ -0,0 +1,595 @@ + + + Hash Join + Hash Cond: (t1.c = t3.a) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: t1.c + -> Hash Join + Hash Cond: (t1.a = t2.b) + -> Seq Scan on t1 + -> Hash + -> Broadcast Motion 3:3 (slice1; segments: 3) + -> Seq Scan on t2 + -> Hash + -> Redistribute Motion 3:3 (slice3; segments: 3) + Hash Key: t3.a + -> Seq Scan on t3 + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/CTEWithMergedGroup.mdp b/src/backend/gporca/data/dxl/minidump/CTEWithMergedGroup.mdp index d04d6fd0f91f..866cc2bce1ef 100644 --- a/src/backend/gporca/data/dxl/minidump/CTEWithMergedGroup.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTEWithMergedGroup.mdp @@ -428,7 +428,7 @@ - + @@ -439,7 +439,7 @@ - + @@ -450,7 +450,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CTEinlining.mdp b/src/backend/gporca/data/dxl/minidump/CTEinlining.mdp index 3abba40eb64d..45cc33c6c235 100644 --- a/src/backend/gporca/data/dxl/minidump/CTEinlining.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTEinlining.mdp @@ -201,7 +201,7 @@ explain with v as (select x,y from bar) select v1.x from v v1, v v2 where v1.x = - + @@ -212,7 +212,7 @@ explain with v as (select x,y from bar) select v1.x from v v1, v v2 where v1.x = - + diff --git a/src/backend/gporca/data/dxl/minidump/CTG-Join.mdp b/src/backend/gporca/data/dxl/minidump/CTG-Join.mdp index 1a0fdf1e75cb..dad240cd30fb 100644 --- a/src/backend/gporca/data/dxl/minidump/CTG-Join.mdp +++ b/src/backend/gporca/data/dxl/minidump/CTG-Join.mdp @@ -95,7 +95,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CapGbCardToSelectCard.mdp b/src/backend/gporca/data/dxl/minidump/CapGbCardToSelectCard.mdp index 5c53d2133a03..067230d417d3 100644 --- a/src/backend/gporca/data/dxl/minidump/CapGbCardToSelectCard.mdp +++ b/src/backend/gporca/data/dxl/minidump/CapGbCardToSelectCard.mdp @@ -10891,7 +10891,7 @@ group by item.i_item_id, item.i_item_desc, item.i_current_price; - + @@ -10908,7 +10908,7 @@ group by item.i_item_id, item.i_item_desc, item.i_current_price; - + @@ -10929,7 +10929,7 @@ group by item.i_item_id, item.i_item_desc, item.i_current_price; - + @@ -10957,7 +10957,7 @@ group by item.i_item_id, item.i_item_desc, item.i_current_price; - + @@ -10978,7 +10978,7 @@ group by item.i_item_id, item.i_item_desc, item.i_current_price; - + diff --git a/src/backend/gporca/data/dxl/minidump/Coalesce-With-Subquery.mdp b/src/backend/gporca/data/dxl/minidump/Coalesce-With-Subquery.mdp index 07b21608cfcb..51012d97c3b2 100644 --- a/src/backend/gporca/data/dxl/minidump/Coalesce-With-Subquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/Coalesce-With-Subquery.mdp @@ -855,7 +855,7 @@ - + @@ -923,7 +923,7 @@ - + @@ -957,7 +957,7 @@ - + @@ -990,7 +990,7 @@ - + @@ -1105,7 +1105,7 @@ - + @@ -1124,7 +1124,7 @@ - + @@ -1137,7 +1137,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CoerceToDomain.mdp b/src/backend/gporca/data/dxl/minidump/CoerceToDomain.mdp index a6ff05add566..cda4f0642141 100644 --- a/src/backend/gporca/data/dxl/minidump/CoerceToDomain.mdp +++ b/src/backend/gporca/data/dxl/minidump/CoerceToDomain.mdp @@ -1934,7 +1934,7 @@ SELECT * FROM information_schema.tables; - + @@ -2098,7 +2098,7 @@ SELECT * FROM information_schema.tables; - + @@ -2163,7 +2163,7 @@ SELECT * FROM information_schema.tables; - + diff --git a/src/backend/gporca/data/dxl/minidump/ConstTblGetUnderSubqWithNoOuterRef.mdp b/src/backend/gporca/data/dxl/minidump/ConstTblGetUnderSubqWithNoOuterRef.mdp index b5f1bc1ee31e..b8d848cb94f7 100644 --- a/src/backend/gporca/data/dxl/minidump/ConstTblGetUnderSubqWithNoOuterRef.mdp +++ b/src/backend/gporca/data/dxl/minidump/ConstTblGetUnderSubqWithNoOuterRef.mdp @@ -473,7 +473,7 @@ SELECT * FROM foo,bar WHERE a=(VALUES (1)); - + @@ -493,7 +493,7 @@ SELECT * FROM foo,bar WHERE a=(VALUES (1)); - + @@ -515,7 +515,7 @@ SELECT * FROM foo,bar WHERE a=(VALUES (1)); - + @@ -529,7 +529,7 @@ SELECT * FROM foo,bar WHERE a=(VALUES (1)); - + diff --git a/src/backend/gporca/data/dxl/minidump/ConstTblGetUnderSubqWithOuterRef.mdp b/src/backend/gporca/data/dxl/minidump/ConstTblGetUnderSubqWithOuterRef.mdp index 7cd5a3d47a88..18ccf6afa8c3 100644 --- a/src/backend/gporca/data/dxl/minidump/ConstTblGetUnderSubqWithOuterRef.mdp +++ b/src/backend/gporca/data/dxl/minidump/ConstTblGetUnderSubqWithOuterRef.mdp @@ -282,7 +282,7 @@ SELECT * FROM foo,bar WHERE a=(SELECT c); - + @@ -302,7 +302,7 @@ SELECT * FROM foo,bar WHERE a=(SELECT c); - + diff --git a/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomInsert.mdp b/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomInsert.mdp index d86fbcd370b8..78ced4cef6be 100644 --- a/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomInsert.mdp +++ b/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomInsert.mdp @@ -645,7 +645,7 @@ explain analyze insert into t1 select t2.a,t3.b from t2, t3 where t2.a = t3.a; - + @@ -667,7 +667,7 @@ explain analyze insert into t1 select t2.a,t3.b from t2, t3 where t2.a = t3.a; - + @@ -684,7 +684,7 @@ explain analyze insert into t1 select t2.a,t3.b from t2, t3 where t2.a = t3.a; - + diff --git a/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomSelect.mdp b/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomSelect.mdp index 8e31860de745..798beaf08934 100644 --- a/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomSelect.mdp +++ b/src/backend/gporca/data/dxl/minidump/ConvertHashToRandomSelect.mdp @@ -205,7 +205,7 @@ - + @@ -225,7 +225,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/CorrelatedNLJWithTrueConditionNeededProjection.mdp b/src/backend/gporca/data/dxl/minidump/CorrelatedNLJWithTrueConditionNeededProjection.mdp new file mode 100644 index 000000000000..46e96deeecba --- /dev/null +++ b/src/backend/gporca/data/dxl/minidump/CorrelatedNLJWithTrueConditionNeededProjection.mdp @@ -0,0 +1,699 @@ + + + Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..431.00 rows=8 width=6) + -> Seq Scan on t1 (cost=0.00..431.00 rows=3 width=6) + SubPlan 1 (slice0) + -> Limit (cost=0.00..431.00 rows=3 width=4) + -> Materialize (cost=0.00..431.00 rows=3 width=4) + -> Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..431.00 rows=8 width=4) + -> Seq Scan on t1 t1_1 (cost=0.00..431.00 rows=3 width=4) + SubPlan 2 (slice0) + -> Result (cost=0.00..431.00 rows=2 width=4) + Filter: ((t2.int_t2 = t1.int_t1) OR (t1.text_t1 = '0'::text)) + -> Materialize (cost=0.00..431.00 rows=2 width=4) + -> Gather Motion 3:1 (slice3; segments: 3) (cost=0.00..431.00 rows=4 width=4) + -> Seq Scan on t2 (cost=0.00..431.00 rows=2 width=4) + Optimizer: Pivotal Optimizer (GPORCA) + (16 rows) + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/CorrelatedSubqueryWithAggWindowFunc.mdp b/src/backend/gporca/data/dxl/minidump/CorrelatedSubqueryWithAggWindowFunc.mdp index e0e0d83658fb..42d0542131d9 100644 --- a/src/backend/gporca/data/dxl/minidump/CorrelatedSubqueryWithAggWindowFunc.mdp +++ b/src/backend/gporca/data/dxl/minidump/CorrelatedSubqueryWithAggWindowFunc.mdp @@ -441,7 +441,7 @@ explain select C.i from C where C.i in (select avg(i) over (partition by i) from - + @@ -452,7 +452,7 @@ explain select C.i from C where C.i in (select avg(i) over (partition by i) from - + @@ -470,7 +470,7 @@ explain select C.i from C where C.i in (select avg(i) over (partition by i) from - + diff --git a/src/backend/gporca/data/dxl/minidump/DML-With-HJ-And-UniversalChild.mdp b/src/backend/gporca/data/dxl/minidump/DML-With-HJ-And-UniversalChild.mdp index 6fc615f2028d..a23420b746a1 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-With-HJ-And-UniversalChild.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-With-HJ-And-UniversalChild.mdp @@ -714,7 +714,7 @@ - + @@ -732,7 +732,7 @@ - + @@ -749,7 +749,7 @@ - + @@ -791,25 +791,25 @@ - + - + - + - + diff --git a/src/backend/gporca/data/dxl/minidump/DML-With-WindowFunc-OuterRef.mdp b/src/backend/gporca/data/dxl/minidump/DML-With-WindowFunc-OuterRef.mdp index 4c092069a62c..ba724194cfef 100644 --- a/src/backend/gporca/data/dxl/minidump/DML-With-WindowFunc-OuterRef.mdp +++ b/src/backend/gporca/data/dxl/minidump/DML-With-WindowFunc-OuterRef.mdp @@ -360,10 +360,10 @@ - + - + @@ -377,7 +377,7 @@ - + @@ -391,7 +391,7 @@ - + @@ -402,7 +402,7 @@ - + @@ -513,9 +513,9 @@ - + - + @@ -523,38 +523,19 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/DPE-IN.mdp b/src/backend/gporca/data/dxl/minidump/DPE-IN.mdp index 250cd95d37ec..14a1d6cdd0e5 100644 --- a/src/backend/gporca/data/dxl/minidump/DPE-IN.mdp +++ b/src/backend/gporca/data/dxl/minidump/DPE-IN.mdp @@ -822,7 +822,7 @@ select * from P,X where P.a=X.a and X.a in (1,2); - + @@ -839,7 +839,7 @@ select * from P,X where P.a=X.a and X.a in (1,2); - + diff --git a/src/backend/gporca/data/dxl/minidump/DPE-NOT-IN.mdp b/src/backend/gporca/data/dxl/minidump/DPE-NOT-IN.mdp index f645acb14b3c..660b509ee6f7 100644 --- a/src/backend/gporca/data/dxl/minidump/DPE-NOT-IN.mdp +++ b/src/backend/gporca/data/dxl/minidump/DPE-NOT-IN.mdp @@ -806,7 +806,7 @@ select * from P,X where P.a=X.a and X.a not in (1,2); - + @@ -823,7 +823,7 @@ select * from P,X where P.a=X.a and X.a not in (1,2); - + diff --git a/src/backend/gporca/data/dxl/minidump/DPE-with-unsupported-pred.mdp b/src/backend/gporca/data/dxl/minidump/DPE-with-unsupported-pred.mdp index 93ae575dfbde..a4dbc7e92a92 100644 --- a/src/backend/gporca/data/dxl/minidump/DPE-with-unsupported-pred.mdp +++ b/src/backend/gporca/data/dxl/minidump/DPE-with-unsupported-pred.mdp @@ -2010,7 +2010,7 @@ - + @@ -2039,7 +2039,7 @@ - + @@ -2068,10 +2068,37 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2127,7 +2154,7 @@ - + @@ -2136,7 +2163,7 @@ - + @@ -2168,7 +2195,7 @@ - + @@ -2182,7 +2209,7 @@ - + @@ -2197,7 +2224,7 @@ - + @@ -2211,7 +2238,7 @@ - + @@ -2235,7 +2262,7 @@ - + @@ -2244,7 +2271,7 @@ - + @@ -2328,33 +2355,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/backend/gporca/data/dxl/minidump/DPv2GreedyOnly.mdp b/src/backend/gporca/data/dxl/minidump/DPv2GreedyOnly.mdp index 8a2c83685765..bcb890ab4b17 100644 --- a/src/backend/gporca/data/dxl/minidump/DPv2GreedyOnly.mdp +++ b/src/backend/gporca/data/dxl/minidump/DPv2GreedyOnly.mdp @@ -5924,7 +5924,7 @@ - + @@ -5962,7 +5962,7 @@ - + @@ -5988,7 +5988,7 @@ - + @@ -6020,7 +6020,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DPv2MinCardOnly.mdp b/src/backend/gporca/data/dxl/minidump/DPv2MinCardOnly.mdp index 94180731987c..09c737ddb219 100644 --- a/src/backend/gporca/data/dxl/minidump/DPv2MinCardOnly.mdp +++ b/src/backend/gporca/data/dxl/minidump/DPv2MinCardOnly.mdp @@ -5924,7 +5924,7 @@ - + @@ -5962,7 +5962,7 @@ - + @@ -5988,7 +5988,7 @@ - + @@ -6020,7 +6020,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DPv2QueryOnly.mdp b/src/backend/gporca/data/dxl/minidump/DPv2QueryOnly.mdp index ad9e673745ce..7099f6416960 100644 --- a/src/backend/gporca/data/dxl/minidump/DPv2QueryOnly.mdp +++ b/src/backend/gporca/data/dxl/minidump/DPv2QueryOnly.mdp @@ -5924,7 +5924,7 @@ - + @@ -5956,7 +5956,7 @@ - + @@ -5994,7 +5994,7 @@ - + @@ -6026,7 +6026,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DQA-InnerJoin-GroupBy-HashAggregate.mdp b/src/backend/gporca/data/dxl/minidump/DQA-InnerJoin-GroupBy-HashAggregate.mdp index 2a176955ff4f..f1c30deb8035 100644 --- a/src/backend/gporca/data/dxl/minidump/DQA-InnerJoin-GroupBy-HashAggregate.mdp +++ b/src/backend/gporca/data/dxl/minidump/DQA-InnerJoin-GroupBy-HashAggregate.mdp @@ -467,7 +467,7 @@ - + @@ -493,7 +493,7 @@ - + @@ -521,7 +521,7 @@ - + @@ -558,7 +558,7 @@ - + @@ -583,7 +583,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Date-TimeStamp-HashJoin.mdp b/src/backend/gporca/data/dxl/minidump/Date-TimeStamp-HashJoin.mdp index 1ba74b493678..fbc7b00e5b27 100644 --- a/src/backend/gporca/data/dxl/minidump/Date-TimeStamp-HashJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/Date-TimeStamp-HashJoin.mdp @@ -286,7 +286,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Delete-With-Limit-In-Subquery.mdp b/src/backend/gporca/data/dxl/minidump/Delete-With-Limit-In-Subquery.mdp index 7e1292b5dbb0..492c795ed794 100644 --- a/src/backend/gporca/data/dxl/minidump/Delete-With-Limit-In-Subquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/Delete-With-Limit-In-Subquery.mdp @@ -724,7 +724,7 @@ - + @@ -742,7 +742,7 @@ - + @@ -759,7 +759,7 @@ - + @@ -773,39 +773,10 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -962,6 +933,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/DeleteMismatchedDistribution.mdp b/src/backend/gporca/data/dxl/minidump/DeleteMismatchedDistribution.mdp index ea408e2ccb04..a74761faa6fb 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteMismatchedDistribution.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteMismatchedDistribution.mdp @@ -340,7 +340,7 @@ - + @@ -360,7 +360,7 @@ - + @@ -377,7 +377,7 @@ - + @@ -391,7 +391,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DeleteRandomlyDistributedTableJoin.mdp b/src/backend/gporca/data/dxl/minidump/DeleteRandomlyDistributedTableJoin.mdp index d639a120e0bc..837de8f2ed91 100644 --- a/src/backend/gporca/data/dxl/minidump/DeleteRandomlyDistributedTableJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/DeleteRandomlyDistributedTableJoin.mdp @@ -280,7 +280,7 @@ - + @@ -298,7 +298,7 @@ - + @@ -315,7 +315,7 @@ - + @@ -329,7 +329,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DisableBroadcastThreshold.mdp b/src/backend/gporca/data/dxl/minidump/DisableBroadcastThreshold.mdp index ef232c025b20..fbe2949b6b2f 100644 --- a/src/backend/gporca/data/dxl/minidump/DisableBroadcastThreshold.mdp +++ b/src/backend/gporca/data/dxl/minidump/DisableBroadcastThreshold.mdp @@ -2602,10 +2602,10 @@ - + - + @@ -2619,7 +2619,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DiscardRedistributeHashJoin.mdp b/src/backend/gporca/data/dxl/minidump/DiscardRedistributeHashJoin.mdp index 3b52b4232c67..314c53cb74ff 100644 --- a/src/backend/gporca/data/dxl/minidump/DiscardRedistributeHashJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/DiscardRedistributeHashJoin.mdp @@ -291,7 +291,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/DynamicIndexGet-OuterRefs.mdp b/src/backend/gporca/data/dxl/minidump/DynamicIndexGet-OuterRefs.mdp index 924b4463dc19..62bdbcb40795 100644 --- a/src/backend/gporca/data/dxl/minidump/DynamicIndexGet-OuterRefs.mdp +++ b/src/backend/gporca/data/dxl/minidump/DynamicIndexGet-OuterRefs.mdp @@ -1301,7 +1301,7 @@ - + @@ -1312,7 +1312,7 @@ - + @@ -1361,7 +1361,7 @@ - + @@ -1382,7 +1382,7 @@ - + @@ -1405,7 +1405,7 @@ - + @@ -1443,7 +1443,7 @@ - + @@ -1466,7 +1466,7 @@ - + @@ -1483,7 +1483,7 @@ - + @@ -1502,7 +1502,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EagerAggEmptyInput.mdp b/src/backend/gporca/data/dxl/minidump/EagerAggEmptyInput.mdp index 6dc17a937936..e2d7a976be9e 100644 --- a/src/backend/gporca/data/dxl/minidump/EagerAggEmptyInput.mdp +++ b/src/backend/gporca/data/dxl/minidump/EagerAggEmptyInput.mdp @@ -336,7 +336,7 @@ - + @@ -356,7 +356,7 @@ - + @@ -383,7 +383,7 @@ - + @@ -405,7 +405,7 @@ - + @@ -430,7 +430,7 @@ - + @@ -447,7 +447,7 @@ - + @@ -474,7 +474,7 @@ - + @@ -496,7 +496,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EagerAggExpression.mdp b/src/backend/gporca/data/dxl/minidump/EagerAggExpression.mdp index bedfbf5a9c0d..2859094717d4 100644 --- a/src/backend/gporca/data/dxl/minidump/EagerAggExpression.mdp +++ b/src/backend/gporca/data/dxl/minidump/EagerAggExpression.mdp @@ -3330,7 +3330,7 @@ - + @@ -3341,7 +3341,7 @@ - + @@ -3352,7 +3352,7 @@ - + @@ -3375,7 +3375,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EagerAggGroupColumnInJoin.mdp b/src/backend/gporca/data/dxl/minidump/EagerAggGroupColumnInJoin.mdp index 0f6647f3f48d..d2fb5ae9c818 100644 --- a/src/backend/gporca/data/dxl/minidump/EagerAggGroupColumnInJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/EagerAggGroupColumnInJoin.mdp @@ -332,7 +332,7 @@ - + @@ -349,7 +349,7 @@ - + @@ -376,7 +376,7 @@ - + @@ -398,7 +398,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EagerAggMax.mdp b/src/backend/gporca/data/dxl/minidump/EagerAggMax.mdp index f1c941a62956..77afdb1bebfc 100644 --- a/src/backend/gporca/data/dxl/minidump/EagerAggMax.mdp +++ b/src/backend/gporca/data/dxl/minidump/EagerAggMax.mdp @@ -335,7 +335,7 @@ - + @@ -355,7 +355,7 @@ - + @@ -382,7 +382,7 @@ - + @@ -404,7 +404,7 @@ - + @@ -429,7 +429,7 @@ - + @@ -446,7 +446,7 @@ - + @@ -473,7 +473,7 @@ - + @@ -495,7 +495,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EagerAggMaxWithNestedLoop.mdp b/src/backend/gporca/data/dxl/minidump/EagerAggMaxWithNestedLoop.mdp index c208249d4fa0..260b36cce4c0 100644 --- a/src/backend/gporca/data/dxl/minidump/EagerAggMaxWithNestedLoop.mdp +++ b/src/backend/gporca/data/dxl/minidump/EagerAggMaxWithNestedLoop.mdp @@ -4295,10 +4295,10 @@ - + - + @@ -4318,7 +4318,7 @@ - + @@ -4332,9 +4332,9 @@ - + - + @@ -4345,7 +4345,7 @@ - + @@ -4367,7 +4367,7 @@ - + @@ -4392,7 +4392,7 @@ - + @@ -4409,7 +4409,7 @@ - + @@ -4417,9 +4417,9 @@ - + - + @@ -4436,7 +4436,7 @@ - + @@ -4453,49 +4453,10 @@ - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -4571,6 +4532,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/EagerAggMinMax.mdp b/src/backend/gporca/data/dxl/minidump/EagerAggMinMax.mdp index 1195be500b0b..00dae3b82f0b 100644 --- a/src/backend/gporca/data/dxl/minidump/EagerAggMinMax.mdp +++ b/src/backend/gporca/data/dxl/minidump/EagerAggMinMax.mdp @@ -3337,7 +3337,7 @@ - + @@ -3351,7 +3351,7 @@ - + @@ -3365,7 +3365,7 @@ - + @@ -3398,7 +3398,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EagerAggSubquery.mdp b/src/backend/gporca/data/dxl/minidump/EagerAggSubquery.mdp index cc49f23a7aea..4f7ff27f129f 100644 --- a/src/backend/gporca/data/dxl/minidump/EagerAggSubquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/EagerAggSubquery.mdp @@ -381,7 +381,7 @@ - + @@ -398,7 +398,7 @@ - + @@ -425,7 +425,7 @@ - + @@ -447,7 +447,7 @@ - + @@ -472,7 +472,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EagerAggUnsupportedAgg.mdp b/src/backend/gporca/data/dxl/minidump/EagerAggUnsupportedAgg.mdp index 0a80e9a1d7fe..94e56c962479 100644 --- a/src/backend/gporca/data/dxl/minidump/EagerAggUnsupportedAgg.mdp +++ b/src/backend/gporca/data/dxl/minidump/EagerAggUnsupportedAgg.mdp @@ -3373,7 +3373,7 @@ - + @@ -3393,7 +3393,7 @@ - + @@ -3436,7 +3436,7 @@ - + @@ -3461,7 +3461,7 @@ - + @@ -3481,7 +3481,7 @@ - + @@ -3529,7 +3529,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EffectOfLocalPredOnJoin.mdp b/src/backend/gporca/data/dxl/minidump/EffectOfLocalPredOnJoin.mdp index 82090c324cf1..448e96ca8e1c 100644 --- a/src/backend/gporca/data/dxl/minidump/EffectOfLocalPredOnJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/EffectOfLocalPredOnJoin.mdp @@ -533,7 +533,7 @@ - + @@ -553,7 +553,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EffectOfLocalPredOnJoin2.mdp b/src/backend/gporca/data/dxl/minidump/EffectOfLocalPredOnJoin2.mdp index 22a3dca3f5eb..6dfd22eff94c 100644 --- a/src/backend/gporca/data/dxl/minidump/EffectOfLocalPredOnJoin2.mdp +++ b/src/backend/gporca/data/dxl/minidump/EffectOfLocalPredOnJoin2.mdp @@ -10287,7 +10287,7 @@ - + @@ -10355,7 +10355,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EffectOfLocalPredOnJoin3.mdp b/src/backend/gporca/data/dxl/minidump/EffectOfLocalPredOnJoin3.mdp index c90cfcff930d..338fc13839d2 100644 --- a/src/backend/gporca/data/dxl/minidump/EffectOfLocalPredOnJoin3.mdp +++ b/src/backend/gporca/data/dxl/minidump/EffectOfLocalPredOnJoin3.mdp @@ -13134,7 +13134,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EffectsOfJoinFilter.mdp b/src/backend/gporca/data/dxl/minidump/EffectsOfJoinFilter.mdp index 19ac993efc17..06f017598d56 100644 --- a/src/backend/gporca/data/dxl/minidump/EffectsOfJoinFilter.mdp +++ b/src/backend/gporca/data/dxl/minidump/EffectsOfJoinFilter.mdp @@ -445,7 +445,7 @@ - + @@ -465,7 +465,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EqualityJoin.mdp b/src/backend/gporca/data/dxl/minidump/EqualityJoin.mdp index 89175d6f67e3..e782f8eef783 100644 --- a/src/backend/gporca/data/dxl/minidump/EqualityJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/EqualityJoin.mdp @@ -421,7 +421,7 @@ - + @@ -441,7 +441,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EquiJoinOnExpr-Supported.mdp b/src/backend/gporca/data/dxl/minidump/EquiJoinOnExpr-Supported.mdp index 2e1385e3633a..624810c7fedb 100644 --- a/src/backend/gporca/data/dxl/minidump/EquiJoinOnExpr-Supported.mdp +++ b/src/backend/gporca/data/dxl/minidump/EquiJoinOnExpr-Supported.mdp @@ -1241,7 +1241,7 @@ - + @@ -1303,7 +1303,7 @@ - + @@ -1378,7 +1378,7 @@ - + @@ -1441,7 +1441,7 @@ - + @@ -1505,7 +1505,7 @@ - + @@ -1556,7 +1556,7 @@ - + @@ -1613,7 +1613,7 @@ - + @@ -1658,7 +1658,7 @@ - + @@ -1691,7 +1691,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EquiJoinOnExpr-Unsupported.mdp b/src/backend/gporca/data/dxl/minidump/EquiJoinOnExpr-Unsupported.mdp index 9888d5ea0fb5..2f602914c797 100644 --- a/src/backend/gporca/data/dxl/minidump/EquiJoinOnExpr-Unsupported.mdp +++ b/src/backend/gporca/data/dxl/minidump/EquiJoinOnExpr-Unsupported.mdp @@ -1179,7 +1179,7 @@ - + @@ -1244,7 +1244,7 @@ - + @@ -1444,7 +1444,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Equiv-HashedDistr-1.mdp b/src/backend/gporca/data/dxl/minidump/Equiv-HashedDistr-1.mdp index 6ab86c1b281d..a0a3b7346a89 100644 --- a/src/backend/gporca/data/dxl/minidump/Equiv-HashedDistr-1.mdp +++ b/src/backend/gporca/data/dxl/minidump/Equiv-HashedDistr-1.mdp @@ -1937,7 +1937,7 @@ - + @@ -1948,7 +1948,7 @@ - + @@ -1957,7 +1957,7 @@ - + @@ -1966,7 +1966,7 @@ - + @@ -1979,7 +1979,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Equiv-HashedDistr-2.mdp b/src/backend/gporca/data/dxl/minidump/Equiv-HashedDistr-2.mdp index 81e16b4dc0dd..3c78762b11bc 100644 --- a/src/backend/gporca/data/dxl/minidump/Equiv-HashedDistr-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/Equiv-HashedDistr-2.mdp @@ -1939,7 +1939,7 @@ - + @@ -1953,7 +1953,7 @@ - + @@ -1965,7 +1965,7 @@ - + @@ -1974,7 +1974,7 @@ - + @@ -1987,7 +1987,7 @@ - + @@ -2089,7 +2089,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EquivClassesAndOr.mdp b/src/backend/gporca/data/dxl/minidump/EquivClassesAndOr.mdp index c6af5632172e..0708e3cf185a 100644 --- a/src/backend/gporca/data/dxl/minidump/EquivClassesAndOr.mdp +++ b/src/backend/gporca/data/dxl/minidump/EquivClassesAndOr.mdp @@ -347,7 +347,7 @@ - + @@ -382,7 +382,7 @@ - + @@ -423,7 +423,7 @@ - + @@ -454,7 +454,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/EquivClassesIntersect.mdp b/src/backend/gporca/data/dxl/minidump/EquivClassesIntersect.mdp index 9a1a74e61f2d..63c769b17c8c 100644 --- a/src/backend/gporca/data/dxl/minidump/EquivClassesIntersect.mdp +++ b/src/backend/gporca/data/dxl/minidump/EquivClassesIntersect.mdp @@ -298,7 +298,7 @@ - + @@ -309,7 +309,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Equivalence-class-project-over-LOJ.mdp b/src/backend/gporca/data/dxl/minidump/Equivalence-class-project-over-LOJ.mdp index 8010a11dfa9f..6907e80b36f6 100644 --- a/src/backend/gporca/data/dxl/minidump/Equivalence-class-project-over-LOJ.mdp +++ b/src/backend/gporca/data/dxl/minidump/Equivalence-class-project-over-LOJ.mdp @@ -379,7 +379,7 @@ - + @@ -397,7 +397,7 @@ - + @@ -408,7 +408,7 @@ - + @@ -424,20 +424,20 @@ - + - + - + diff --git a/src/backend/gporca/data/dxl/minidump/EstimateJoinRowsForCastPredicates.mdp b/src/backend/gporca/data/dxl/minidump/EstimateJoinRowsForCastPredicates.mdp index 65991b52b0a2..316419add787 100644 --- a/src/backend/gporca/data/dxl/minidump/EstimateJoinRowsForCastPredicates.mdp +++ b/src/backend/gporca/data/dxl/minidump/EstimateJoinRowsForCastPredicates.mdp @@ -518,7 +518,7 @@ explain select * from A,B where A.j=B.j; - + diff --git a/src/backend/gporca/data/dxl/minidump/Except-Volatile-Func.mdp b/src/backend/gporca/data/dxl/minidump/Except-Volatile-Func.mdp index 895d06aaebc2..3adb73a984d3 100644 --- a/src/backend/gporca/data/dxl/minidump/Except-Volatile-Func.mdp +++ b/src/backend/gporca/data/dxl/minidump/Except-Volatile-Func.mdp @@ -112,7 +112,7 @@ - + @@ -125,7 +125,7 @@ - + @@ -140,7 +140,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Except.mdp b/src/backend/gporca/data/dxl/minidump/Except.mdp index fe6ebd6d32ef..5e5f40efa86f 100644 --- a/src/backend/gporca/data/dxl/minidump/Except.mdp +++ b/src/backend/gporca/data/dxl/minidump/Except.mdp @@ -321,7 +321,7 @@ - + @@ -332,7 +332,7 @@ - + @@ -345,7 +345,7 @@ - + @@ -360,7 +360,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ExceptAllCompatibleDataType.mdp b/src/backend/gporca/data/dxl/minidump/ExceptAllCompatibleDataType.mdp index 5ca667abe343..cbd19f8b4591 100644 --- a/src/backend/gporca/data/dxl/minidump/ExceptAllCompatibleDataType.mdp +++ b/src/backend/gporca/data/dxl/minidump/ExceptAllCompatibleDataType.mdp @@ -416,7 +416,7 @@ - + @@ -430,7 +430,7 @@ - + @@ -464,7 +464,7 @@ - + @@ -489,7 +489,7 @@ - + @@ -506,7 +506,7 @@ - + @@ -522,7 +522,7 @@ - + @@ -541,7 +541,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ExceptHashCompatibleRange.mdp b/src/backend/gporca/data/dxl/minidump/ExceptHashCompatibleRange.mdp index 778cdc59e553..ff5080ab8ff6 100644 --- a/src/backend/gporca/data/dxl/minidump/ExceptHashCompatibleRange.mdp +++ b/src/backend/gporca/data/dxl/minidump/ExceptHashCompatibleRange.mdp @@ -150,7 +150,7 @@ - + @@ -163,7 +163,7 @@ - + @@ -178,7 +178,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ExpandFullOuterJoin.mdp b/src/backend/gporca/data/dxl/minidump/ExpandFullOuterJoin.mdp index 2d99d8ed9984..55354272d4c3 100644 --- a/src/backend/gporca/data/dxl/minidump/ExpandFullOuterJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/ExpandFullOuterJoin.mdp @@ -224,7 +224,7 @@ select * from t full join s on t1 = s1; - + @@ -238,7 +238,7 @@ select * from t full join s on t1 = s1; - + @@ -252,7 +252,7 @@ select * from t full join s on t1 = s1; - + @@ -347,7 +347,7 @@ select * from t full join s on t1 = s1; - + @@ -442,7 +442,7 @@ select * from t full join s on t1 = s1; - + @@ -455,7 +455,7 @@ select * from t full join s on t1 = s1; - + @@ -544,7 +544,7 @@ select * from t full join s on t1 = s1; - + @@ -558,7 +558,7 @@ select * from t full join s on t1 = s1; - + diff --git a/src/backend/gporca/data/dxl/minidump/ExpandFullOuterJoin2.mdp b/src/backend/gporca/data/dxl/minidump/ExpandFullOuterJoin2.mdp index 1124f6f06863..9e0a68066fdb 100644 --- a/src/backend/gporca/data/dxl/minidump/ExpandFullOuterJoin2.mdp +++ b/src/backend/gporca/data/dxl/minidump/ExpandFullOuterJoin2.mdp @@ -206,7 +206,7 @@ select * from s full join s s1 on s.a = s1.a where s.a is null; - + @@ -220,7 +220,7 @@ select * from s full join s s1 on s.a = s1.a where s.a is null; - + @@ -238,7 +238,7 @@ select * from s full join s s1 on s.a = s1.a where s.a is null; - + @@ -325,7 +325,7 @@ select * from s full join s s1 on s.a = s1.a where s.a is null; - + @@ -412,7 +412,7 @@ select * from s full join s s1 on s.a = s1.a where s.a is null; - + @@ -425,7 +425,7 @@ select * from s full join s s1 on s.a = s1.a where s.a is null; - + @@ -508,7 +508,7 @@ select * from s full join s s1 on s.a = s1.a where s.a is null; - + @@ -522,7 +522,7 @@ select * from s full join s s1 on s.a = s1.a where s.a is null; - + diff --git a/src/backend/gporca/data/dxl/minidump/ExpandJoinOrder.mdp b/src/backend/gporca/data/dxl/minidump/ExpandJoinOrder.mdp index 10e17cadbdd9..ccc12733d65c 100644 --- a/src/backend/gporca/data/dxl/minidump/ExpandJoinOrder.mdp +++ b/src/backend/gporca/data/dxl/minidump/ExpandJoinOrder.mdp @@ -868,7 +868,7 @@ - + @@ -970,7 +970,7 @@ - + @@ -1107,7 +1107,7 @@ - + @@ -1209,7 +1209,7 @@ - + @@ -1348,7 +1348,7 @@ - + @@ -1516,7 +1516,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ExpandNAryJoinGreedyWithLOJOnly.mdp b/src/backend/gporca/data/dxl/minidump/ExpandNAryJoinGreedyWithLOJOnly.mdp index f115f5dc540d..abcafd950b1f 100644 --- a/src/backend/gporca/data/dxl/minidump/ExpandNAryJoinGreedyWithLOJOnly.mdp +++ b/src/backend/gporca/data/dxl/minidump/ExpandNAryJoinGreedyWithLOJOnly.mdp @@ -3937,7 +3937,7 @@ - + @@ -3960,7 +3960,7 @@ - + @@ -3989,7 +3989,7 @@ - + @@ -4020,7 +4020,7 @@ - + @@ -4083,7 +4083,7 @@ - + @@ -4105,7 +4105,7 @@ - + @@ -4169,7 +4169,7 @@ - + @@ -4194,7 +4194,7 @@ - + @@ -4247,7 +4247,7 @@ - + @@ -4266,7 +4266,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ExtractPredicateFromDisj.mdp b/src/backend/gporca/data/dxl/minidump/ExtractPredicateFromDisj.mdp index 66206122f4ca..0e2baf0b7bd0 100644 --- a/src/backend/gporca/data/dxl/minidump/ExtractPredicateFromDisj.mdp +++ b/src/backend/gporca/data/dxl/minidump/ExtractPredicateFromDisj.mdp @@ -14565,7 +14565,7 @@ WHERE ((sale_type = 's'::text AND dyear = 2001 AND year_total > 0::numeric) O - + @@ -14603,7 +14603,7 @@ WHERE ((sale_type = 's'::text AND dyear = 2001 AND year_total > 0::numeric) O - + @@ -14696,7 +14696,7 @@ WHERE ((sale_type = 's'::text AND dyear = 2001 AND year_total > 0::numeric) O - + @@ -14737,7 +14737,7 @@ WHERE ((sale_type = 's'::text AND dyear = 2001 AND year_total > 0::numeric) O - + @@ -14795,7 +14795,7 @@ WHERE ((sale_type = 's'::text AND dyear = 2001 AND year_total > 0::numeric) O - + @@ -14842,7 +14842,7 @@ WHERE ((sale_type = 's'::text AND dyear = 2001 AND year_total > 0::numeric) O - + @@ -14873,7 +14873,7 @@ WHERE ((sale_type = 's'::text AND dyear = 2001 AND year_total > 0::numeric) O - + diff --git a/src/backend/gporca/data/dxl/minidump/ExtractPredicateFromDisjWithComputedColumns.mdp b/src/backend/gporca/data/dxl/minidump/ExtractPredicateFromDisjWithComputedColumns.mdp index 51122f17d2ca..54dc106cf0ea 100644 --- a/src/backend/gporca/data/dxl/minidump/ExtractPredicateFromDisjWithComputedColumns.mdp +++ b/src/backend/gporca/data/dxl/minidump/ExtractPredicateFromDisjWithComputedColumns.mdp @@ -462,7 +462,7 @@ where (cd.dyear = 2001 and s.tickets_cnt > 3) or (cd.dmoy = 4 and s.tickets_c - + @@ -497,7 +497,7 @@ where (cd.dyear = 2001 and s.tickets_cnt > 3) or (cd.dmoy = 4 and s.tickets_c - + @@ -529,49 +529,26 @@ where (cd.dyear = 2001 and s.tickets_cnt > 3) or (cd.dmoy = 4 and s.tickets_c - - - - - - - - - - - - - - - - - - - - - - - - + - - + + - + - - + + - - + + - - + + @@ -587,22 +564,22 @@ where (cd.dyear = 2001 and s.tickets_cnt > 3) or (cd.dmoy = 4 and s.tickets_c - + - + - - + + - - + + - - + + @@ -615,41 +592,75 @@ where (cd.dyear = 2001 and s.tickets_cnt > 3) or (cd.dmoy = 4 and s.tickets_c - + + + + + + + + + + + + + + + + + + + + + + + + - - + + - + - - + + - - + + - - + + - - + + + + + + + + + + + + + - - - - - - - - - - + + + + + + + + + + @@ -672,7 +683,7 @@ where (cd.dyear = 2001 and s.tickets_cnt > 3) or (cd.dmoy = 4 and s.tickets_c - + @@ -713,9 +724,9 @@ where (cd.dyear = 2001 and s.tickets_cnt > 3) or (cd.dmoy = 4 and s.tickets_c - + - + @@ -804,9 +815,9 @@ where (cd.dyear = 2001 and s.tickets_cnt > 3) or (cd.dmoy = 4 and s.tickets_c - + - + @@ -887,43 +898,32 @@ where (cd.dyear = 2001 and s.tickets_cnt > 3) or (cd.dmoy = 4 and s.tickets_c - + - - + + - - + + - - + + - - - - - - - - - - - - - + + - - - - - - - - - - + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/Factorized-Preds.mdp b/src/backend/gporca/data/dxl/minidump/Factorized-Preds.mdp index 93d4eabf9230..3c38393f9f22 100644 --- a/src/backend/gporca/data/dxl/minidump/Factorized-Preds.mdp +++ b/src/backend/gporca/data/dxl/minidump/Factorized-Preds.mdp @@ -278,7 +278,7 @@ - + @@ -298,7 +298,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/FullJoin-NonDefaultOpfamily.mdp b/src/backend/gporca/data/dxl/minidump/FullJoin-NonDefaultOpfamily.mdp index 1f5cf56d1589..f90f7d9adee6 100644 --- a/src/backend/gporca/data/dxl/minidump/FullJoin-NonDefaultOpfamily.mdp +++ b/src/backend/gporca/data/dxl/minidump/FullJoin-NonDefaultOpfamily.mdp @@ -352,7 +352,7 @@ - + @@ -366,7 +366,7 @@ - + @@ -453,7 +453,7 @@ - + @@ -540,7 +540,7 @@ - + @@ -553,7 +553,7 @@ - + @@ -694,7 +694,7 @@ - + @@ -708,7 +708,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/FullJoin-Subquery-CastedPredicates.mdp b/src/backend/gporca/data/dxl/minidump/FullJoin-Subquery-CastedPredicates.mdp index cdffe31e27dd..355f7f5f18b2 100644 --- a/src/backend/gporca/data/dxl/minidump/FullJoin-Subquery-CastedPredicates.mdp +++ b/src/backend/gporca/data/dxl/minidump/FullJoin-Subquery-CastedPredicates.mdp @@ -490,7 +490,7 @@ - + @@ -513,7 +513,7 @@ - + @@ -654,7 +654,7 @@ - + @@ -678,7 +678,7 @@ - + @@ -703,7 +703,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/FullOuterJoin-NullRejectingLHS1.mdp b/src/backend/gporca/data/dxl/minidump/FullOuterJoin-NullRejectingLHS1.mdp index 595aea9b962b..9696295fc1d9 100644 --- a/src/backend/gporca/data/dxl/minidump/FullOuterJoin-NullRejectingLHS1.mdp +++ b/src/backend/gporca/data/dxl/minidump/FullOuterJoin-NullRejectingLHS1.mdp @@ -264,7 +264,7 @@ - + @@ -284,7 +284,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/FullOuterJoin-NullRejectingLHS2.mdp b/src/backend/gporca/data/dxl/minidump/FullOuterJoin-NullRejectingLHS2.mdp index 8ec9d9a28d59..ec2fa7ccbc87 100644 --- a/src/backend/gporca/data/dxl/minidump/FullOuterJoin-NullRejectingLHS2.mdp +++ b/src/backend/gporca/data/dxl/minidump/FullOuterJoin-NullRejectingLHS2.mdp @@ -336,7 +336,7 @@ - + @@ -347,7 +347,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/GreedyNAryDelayCrossJoin.mdp b/src/backend/gporca/data/dxl/minidump/GreedyNAryDelayCrossJoin.mdp index bce7e4afc819..08d2d089905b 100644 --- a/src/backend/gporca/data/dxl/minidump/GreedyNAryDelayCrossJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/GreedyNAryDelayCrossJoin.mdp @@ -1280,7 +1280,7 @@ EXPLAIN SELECT * FROM t1, t2, t3, t4 where b = c; - + @@ -1300,7 +1300,7 @@ EXPLAIN SELECT * FROM t1, t2, t3, t4 where b = c; - + @@ -1322,7 +1322,7 @@ EXPLAIN SELECT * FROM t1, t2, t3, t4 where b = c; - + @@ -1341,7 +1341,7 @@ EXPLAIN SELECT * FROM t1, t2, t3, t4 where b = c; - + diff --git a/src/backend/gporca/data/dxl/minidump/GreedyNAryJoin.mdp b/src/backend/gporca/data/dxl/minidump/GreedyNAryJoin.mdp index 71636d0afc41..61b30c16e1f5 100644 --- a/src/backend/gporca/data/dxl/minidump/GreedyNAryJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/GreedyNAryJoin.mdp @@ -1144,10 +1144,10 @@ EXPLAIN SELECT * FROM t1 INNER JOIN t2 ON a =b INNER JOIN t3 ON b = c; - + - + @@ -1164,7 +1164,7 @@ EXPLAIN SELECT * FROM t1 INNER JOIN t2 ON a =b INNER JOIN t3 ON b = c; - + @@ -1181,53 +1181,53 @@ EXPLAIN SELECT * FROM t1 INNER JOIN t2 ON a =b INNER JOIN t3 ON b = c; + - - + - + + + + + + + + + + + + + + + + + + + + + + + + - + - - - - - - - - - - - - - - - - - - - - - - - @@ -1251,30 +1251,30 @@ EXPLAIN SELECT * FROM t1 INNER JOIN t2 ON a =b INNER JOIN t3 ON b = c; + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/backend/gporca/data/dxl/minidump/GreedyNAryJoinWithDisconnectedEdges.mdp b/src/backend/gporca/data/dxl/minidump/GreedyNAryJoinWithDisconnectedEdges.mdp index 57490d5fd937..1f70e88d0e89 100644 --- a/src/backend/gporca/data/dxl/minidump/GreedyNAryJoinWithDisconnectedEdges.mdp +++ b/src/backend/gporca/data/dxl/minidump/GreedyNAryJoinWithDisconnectedEdges.mdp @@ -3765,7 +3765,7 @@ - + @@ -3821,7 +3821,7 @@ - + @@ -3879,7 +3879,7 @@ - + @@ -3931,7 +3931,7 @@ - + @@ -3981,7 +3981,7 @@ - + @@ -4021,7 +4021,7 @@ - + @@ -4059,7 +4059,7 @@ - + @@ -4087,7 +4087,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/GroupByOuterRef.mdp b/src/backend/gporca/data/dxl/minidump/GroupByOuterRef.mdp index 30b8e4b2de45..eaa2b3e350a2 100644 --- a/src/backend/gporca/data/dxl/minidump/GroupByOuterRef.mdp +++ b/src/backend/gporca/data/dxl/minidump/GroupByOuterRef.mdp @@ -328,7 +328,7 @@ where t.a in (select count(s.i) from s); - + diff --git a/src/backend/gporca/data/dxl/minidump/GroupingOnSameTblCol-2.mdp b/src/backend/gporca/data/dxl/minidump/GroupingOnSameTblCol-2.mdp index 073663571b27..2b1048201f7f 100644 --- a/src/backend/gporca/data/dxl/minidump/GroupingOnSameTblCol-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/GroupingOnSameTblCol-2.mdp @@ -4117,7 +4117,7 @@ - + @@ -4128,21 +4128,21 @@ - + - + - + @@ -4175,7 +4175,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/HAWQ-TPCH-Stat-Derivation.mdp b/src/backend/gporca/data/dxl/minidump/HAWQ-TPCH-Stat-Derivation.mdp index 1b1c27ad308b..677bae97123d 100644 --- a/src/backend/gporca/data/dxl/minidump/HAWQ-TPCH-Stat-Derivation.mdp +++ b/src/backend/gporca/data/dxl/minidump/HAWQ-TPCH-Stat-Derivation.mdp @@ -6379,10 +6379,10 @@ ORDER BY s_name; - + - + @@ -6398,7 +6398,7 @@ ORDER BY s_name; - + @@ -6416,7 +6416,7 @@ ORDER BY s_name; - + @@ -6436,7 +6436,7 @@ ORDER BY s_name; - + @@ -6458,7 +6458,7 @@ ORDER BY s_name; - + @@ -6512,7 +6512,7 @@ ORDER BY s_name; - + @@ -6528,7 +6528,7 @@ ORDER BY s_name; - + @@ -6546,229 +6546,128 @@ ORDER BY s_name; - + - + - + - - + + - - + + - - + + - - - - + - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + + - + + + + + + + - - - - - - - - - - - - - + + - + + + + + + + + + + + + + + + - - - - - + - + - - - - - - - - - - - - - - + + + - + + + + + + + + + + - + @@ -6777,34 +6676,150 @@ ORDER BY s_name; - - + + - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/HJN-DPE-Bitmap-Outer-Child.mdp b/src/backend/gporca/data/dxl/minidump/HJN-DPE-Bitmap-Outer-Child.mdp index da79ae41674d..1c244ae8eb1a 100644 --- a/src/backend/gporca/data/dxl/minidump/HJN-DPE-Bitmap-Outer-Child.mdp +++ b/src/backend/gporca/data/dxl/minidump/HJN-DPE-Bitmap-Outer-Child.mdp @@ -828,7 +828,7 @@ select * from dbs_target, dbs_helper where dbs_target.c1 = dbs_helper.c1 and dbs - + @@ -854,7 +854,7 @@ select * from dbs_target, dbs_helper where dbs_target.c1 = dbs_helper.c1 and dbs - + diff --git a/src/backend/gporca/data/dxl/minidump/HJN-DeeperOuter.mdp b/src/backend/gporca/data/dxl/minidump/HJN-DeeperOuter.mdp index 816ed4d36510..0bb128831a21 100644 --- a/src/backend/gporca/data/dxl/minidump/HJN-DeeperOuter.mdp +++ b/src/backend/gporca/data/dxl/minidump/HJN-DeeperOuter.mdp @@ -359,7 +359,7 @@ SELECT z.*,x.* FROM x,y,z WHERE x.i=y.i AND x.i=z.i; - + @@ -382,7 +382,7 @@ SELECT z.*,x.* FROM x,y,z WHERE x.i=y.i AND x.i=z.i; - + @@ -444,7 +444,7 @@ SELECT z.*,x.* FROM x,y,z WHERE x.i=y.i AND x.i=z.i; - + @@ -468,7 +468,7 @@ SELECT z.*,x.* FROM x,y,z WHERE x.i=y.i AND x.i=z.i; - + diff --git a/src/backend/gporca/data/dxl/minidump/HJN-Redistribute-One-Side.mdp b/src/backend/gporca/data/dxl/minidump/HJN-Redistribute-One-Side.mdp index e512f35217e5..ad5f2bd9526a 100644 --- a/src/backend/gporca/data/dxl/minidump/HJN-Redistribute-One-Side.mdp +++ b/src/backend/gporca/data/dxl/minidump/HJN-Redistribute-One-Side.mdp @@ -4554,7 +4554,7 @@ - + @@ -4637,7 +4637,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/HashJoinOnRelabeledColumns.mdp b/src/backend/gporca/data/dxl/minidump/HashJoinOnRelabeledColumns.mdp index b867dca16756..1afd66e01001 100644 --- a/src/backend/gporca/data/dxl/minidump/HashJoinOnRelabeledColumns.mdp +++ b/src/backend/gporca/data/dxl/minidump/HashJoinOnRelabeledColumns.mdp @@ -268,7 +268,7 @@ - + @@ -282,7 +282,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/IN-ArrayCmp.mdp b/src/backend/gporca/data/dxl/minidump/IN-ArrayCmp.mdp index f4076348ca59..bf6558140698 100644 --- a/src/backend/gporca/data/dxl/minidump/IN-ArrayCmp.mdp +++ b/src/backend/gporca/data/dxl/minidump/IN-ArrayCmp.mdp @@ -254,7 +254,7 @@ - + @@ -274,7 +274,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InSubqueryWithNotNullCol.mdp b/src/backend/gporca/data/dxl/minidump/InSubqueryWithNotNullCol.mdp index 7b1b33fa5fcc..306a5c187932 100644 --- a/src/backend/gporca/data/dxl/minidump/InSubqueryWithNotNullCol.mdp +++ b/src/backend/gporca/data/dxl/minidump/InSubqueryWithNotNullCol.mdp @@ -426,7 +426,7 @@ select * - + @@ -440,7 +440,7 @@ select * - + @@ -489,7 +489,7 @@ select * - + @@ -534,7 +534,7 @@ select * - + @@ -573,7 +573,7 @@ select * - + @@ -606,7 +606,7 @@ select * - + diff --git a/src/backend/gporca/data/dxl/minidump/IndexApply-ForPartialIndex.mdp b/src/backend/gporca/data/dxl/minidump/IndexApply-ForPartialIndex.mdp index 7992d82d8789..f768f1ff16a7 100644 --- a/src/backend/gporca/data/dxl/minidump/IndexApply-ForPartialIndex.mdp +++ b/src/backend/gporca/data/dxl/minidump/IndexApply-ForPartialIndex.mdp @@ -390,7 +390,7 @@ explain select t1.a from t1, foo_prt t2, t3 where (t1.b = t2.a) and t2.a = t3.b; - + @@ -401,7 +401,7 @@ explain select t1.a from t1, foo_prt t2, t3 where (t1.b = t2.a) and t2.a = t3.b; - + @@ -465,7 +465,7 @@ explain select t1.a from t1, foo_prt t2, t3 where (t1.b = t2.a) and t2.a = t3.b; - + diff --git a/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondDisjointWithHashedDistr.mdp b/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondDisjointWithHashedDistr.mdp index 98017cc41251..5513be15cedc 100644 --- a/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondDisjointWithHashedDistr.mdp +++ b/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondDisjointWithHashedDistr.mdp @@ -827,7 +827,7 @@ - + @@ -850,7 +850,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondIntersectWithHashedDistr.mdp b/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondIntersectWithHashedDistr.mdp index 89a2813898aa..dd3102970530 100644 --- a/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondIntersectWithHashedDistr.mdp +++ b/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondIntersectWithHashedDistr.mdp @@ -833,7 +833,7 @@ - + @@ -856,7 +856,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondMatchHashedDistr.mdp b/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondMatchHashedDistr.mdp index c05a408cb562..19a475821ffc 100644 --- a/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondMatchHashedDistr.mdp +++ b/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondMatchHashedDistr.mdp @@ -805,7 +805,7 @@ - + @@ -825,7 +825,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondSubsetOfHashedDistr.mdp b/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondSubsetOfHashedDistr.mdp index 98017cc41251..5513be15cedc 100644 --- a/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondSubsetOfHashedDistr.mdp +++ b/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondSubsetOfHashedDistr.mdp @@ -827,7 +827,7 @@ - + @@ -850,7 +850,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondSupersetOfHashedDistr.mdp b/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondSupersetOfHashedDistr.mdp index 292aefe624e2..5e46dd96112b 100644 --- a/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondSupersetOfHashedDistr.mdp +++ b/src/backend/gporca/data/dxl/minidump/IndexApply-IndexCondSupersetOfHashedDistr.mdp @@ -819,7 +819,7 @@ - + @@ -839,7 +839,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/IndexApply-InnerSelect-PartTable2.mdp b/src/backend/gporca/data/dxl/minidump/IndexApply-InnerSelect-PartTable2.mdp index 71aad8aff3cd..9d30106a6798 100644 --- a/src/backend/gporca/data/dxl/minidump/IndexApply-InnerSelect-PartTable2.mdp +++ b/src/backend/gporca/data/dxl/minidump/IndexApply-InnerSelect-PartTable2.mdp @@ -406,7 +406,7 @@ select * from bar, (select * from foo where foo.a in (select h.a from bar h, bar - + @@ -426,7 +426,7 @@ select * from bar, (select * from foo where foo.a in (select h.a from bar h, bar - + diff --git a/src/backend/gporca/data/dxl/minidump/IndexGet-OuterRefs.mdp b/src/backend/gporca/data/dxl/minidump/IndexGet-OuterRefs.mdp index e415f19da763..2c0c7a671b42 100644 --- a/src/backend/gporca/data/dxl/minidump/IndexGet-OuterRefs.mdp +++ b/src/backend/gporca/data/dxl/minidump/IndexGet-OuterRefs.mdp @@ -263,7 +263,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/IndexScanWithNestedCTEAndSetOp.mdp b/src/backend/gporca/data/dxl/minidump/IndexScanWithNestedCTEAndSetOp.mdp index a82aa41348eb..0655e7768952 100644 --- a/src/backend/gporca/data/dxl/minidump/IndexScanWithNestedCTEAndSetOp.mdp +++ b/src/backend/gporca/data/dxl/minidump/IndexScanWithNestedCTEAndSetOp.mdp @@ -353,7 +353,7 @@ SELECT a FROM y WHERE (a IN (SELECT b FROM bar WHERE b = 2)); - + @@ -364,7 +364,7 @@ SELECT a FROM y WHERE (a IN (SELECT b FROM bar WHERE b = 2)); - + @@ -375,7 +375,7 @@ SELECT a FROM y WHERE (a IN (SELECT b FROM bar WHERE b = 2)); - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicates.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicates.mdp index 34606cff1bc5..19e1fb8a6fbc 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicates.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicates.mdp @@ -346,7 +346,7 @@ explain select 1+row_number() over(partition by foo.c) from foo, bar where foo.a - + @@ -357,7 +357,7 @@ explain select 1+row_number() over(partition by foo.c) from foo, bar where foo.a - + @@ -371,7 +371,7 @@ explain select 1+row_number() over(partition by foo.c) from foo, bar where foo.a - + @@ -384,7 +384,7 @@ explain select 1+row_number() over(partition by foo.c) from foo, bar where foo.a - + @@ -399,7 +399,7 @@ explain select 1+row_number() over(partition by foo.c) from foo, bar where foo.a - + @@ -415,7 +415,7 @@ explain select 1+row_number() over(partition by foo.c) from foo, bar where foo.a - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-oid-oid.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-oid-oid.mdp index b74ce8ae5cfa..ab19aab072b4 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-oid-oid.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-oid-oid.mdp @@ -228,7 +228,7 @@ - + @@ -242,7 +242,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-txt-txt.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-txt-txt.mdp index 7a1f86558c23..63bb25d1fa04 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-txt-txt.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-txt-txt.mdp @@ -251,7 +251,7 @@ - + @@ -265,7 +265,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-vc-txt.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-vc-txt.mdp index cd91c9fae878..32ea8a9100f5 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-vc-txt.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-vc-txt.mdp @@ -306,7 +306,7 @@ - + @@ -320,7 +320,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-vc-vc.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-vc-vc.mdp index f790297dc19d..0c0ef5acf4b3 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-vc-vc.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-vc-vc.mdp @@ -273,7 +273,7 @@ - + @@ -287,7 +287,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-vcpart-txt.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-vcpart-txt.mdp index 5223ea1e1e36..c8ea7ec05890 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-vcpart-txt.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesBCC-vcpart-txt.mdp @@ -750,7 +750,7 @@ - + @@ -767,7 +767,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesForLimit.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesForLimit.mdp index a528f5cc71c3..dab3172086a4 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesForLimit.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesForLimit.mdp @@ -276,7 +276,7 @@ a < 2 should also be outside the limit but not below. - + @@ -287,14 +287,14 @@ a < 2 should also be outside the limit but not below. - + - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesForPartSQ.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesForPartSQ.mdp index c45e042050b0..f61435fbe58a 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesForPartSQ.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesForPartSQ.mdp @@ -400,7 +400,7 @@ - + @@ -414,7 +414,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesFromExistsSubquery.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesFromExistsSubquery.mdp index 1945d4e5826f..e766ceba146a 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesFromExistsSubquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesFromExistsSubquery.mdp @@ -353,7 +353,7 @@ - + @@ -367,7 +367,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesFromMultiSubquery.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesFromMultiSubquery.mdp index edbd285db97f..0336085d0614 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesFromMultiSubquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesFromMultiSubquery.mdp @@ -520,32 +520,9 @@ - - - - - - - - - - - - - - - - - - - - - - - - + - + @@ -565,20 +542,10 @@ - - - - - - - - - - - + - + @@ -601,17 +568,17 @@ - - + + - - + + - + - + @@ -635,16 +602,16 @@ - + - - + + - + - + @@ -663,60 +630,79 @@ - - - + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -727,15 +713,12 @@ - + - - - @@ -745,11 +728,14 @@ - + - + + + + @@ -757,48 +743,48 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + - + @@ -809,15 +795,12 @@ - + - - - @@ -827,11 +810,14 @@ - + - + + + + @@ -839,48 +825,48 @@ - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - + + + - + @@ -890,36 +876,50 @@ - - - - - - - + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesInnerOfLOJ.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesInnerOfLOJ.mdp index 1e23b81210e6..4ed811e6053a 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesInnerOfLOJ.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesInnerOfLOJ.mdp @@ -352,7 +352,7 @@ - + @@ -363,7 +363,7 @@ - + @@ -380,7 +380,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesIntFromExistsSubquery.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesIntFromExistsSubquery.mdp index 31945f698bc0..0f7bcb35abb5 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesIntFromExistsSubquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesIntFromExistsSubquery.mdp @@ -411,7 +411,7 @@ - + @@ -434,7 +434,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesIntFromSubquery.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesIntFromSubquery.mdp index c45be27f1009..8f6c2e9f84c6 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesIntFromSubquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesIntFromSubquery.mdp @@ -341,7 +341,7 @@ - + @@ -355,7 +355,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesJoinSubquery.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesJoinSubquery.mdp index a5dd436fab08..6390f9288a71 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesJoinSubquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesJoinSubquery.mdp @@ -486,7 +486,7 @@ - + @@ -524,7 +524,7 @@ - + @@ -572,7 +572,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InferPredicatesMultiColumns.mdp b/src/backend/gporca/data/dxl/minidump/InferPredicatesMultiColumns.mdp index 959aad4e8047..cb10c4b0a92f 100644 --- a/src/backend/gporca/data/dxl/minidump/InferPredicatesMultiColumns.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferPredicatesMultiColumns.mdp @@ -426,7 +426,7 @@ - + @@ -449,7 +449,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InferredPredicatesConstraintSimplification.mdp b/src/backend/gporca/data/dxl/minidump/InferredPredicatesConstraintSimplification.mdp index 767d5c43aaef..aab7c10e0fa4 100644 --- a/src/backend/gporca/data/dxl/minidump/InferredPredicatesConstraintSimplification.mdp +++ b/src/backend/gporca/data/dxl/minidump/InferredPredicatesConstraintSimplification.mdp @@ -402,7 +402,7 @@ - + @@ -419,7 +419,7 @@ - + @@ -470,7 +470,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InnerJoinBroadcastTableHashSpec.mdp b/src/backend/gporca/data/dxl/minidump/InnerJoinBroadcastTableHashSpec.mdp index 57bbbd79a075..3aa0fa96bd75 100644 --- a/src/backend/gporca/data/dxl/minidump/InnerJoinBroadcastTableHashSpec.mdp +++ b/src/backend/gporca/data/dxl/minidump/InnerJoinBroadcastTableHashSpec.mdp @@ -363,7 +363,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1, t2 WHERE a1 = b2 GROUP BY b2 ORDER BY b2; - + @@ -379,7 +379,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1, t2 WHERE a1 = b2 GROUP BY b2 ORDER BY b2; - + @@ -397,7 +397,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1, t2 WHERE a1 = b2 GROUP BY b2 ORDER BY b2; - + @@ -420,7 +420,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1, t2 WHERE a1 = b2 GROUP BY b2 ORDER BY b2; - + @@ -438,7 +438,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1, t2 WHERE a1 = b2 GROUP BY b2 ORDER BY b2; - + diff --git a/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExcept.mdp b/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExcept.mdp index ff2c009499f4..4333cbeab6b1 100644 --- a/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExcept.mdp +++ b/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExcept.mdp @@ -298,7 +298,7 @@ ON (a.col = b.col); - + @@ -320,7 +320,7 @@ ON (a.col = b.col); - + @@ -334,7 +334,7 @@ ON (a.col = b.col); - + @@ -374,7 +374,7 @@ ON (a.col = b.col); - + @@ -387,7 +387,7 @@ ON (a.col = b.col); - + @@ -402,7 +402,7 @@ ON (a.col = b.col); - + @@ -421,7 +421,7 @@ ON (a.col = b.col); - + diff --git a/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExceptAll.mdp b/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExceptAll.mdp index ac8725550f94..001f5f60c2b8 100644 --- a/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExceptAll.mdp +++ b/src/backend/gporca/data/dxl/minidump/InnerJoinOverJoinExceptAll.mdp @@ -336,7 +336,7 @@ ON (a.col = b.col); - + @@ -358,7 +358,7 @@ ON (a.col = b.col); - + @@ -372,7 +372,7 @@ ON (a.col = b.col); - + @@ -412,7 +412,7 @@ ON (a.col = b.col); - + @@ -437,7 +437,7 @@ ON (a.col = b.col); - + @@ -450,7 +450,7 @@ ON (a.col = b.col); - + @@ -465,7 +465,7 @@ ON (a.col = b.col); - + diff --git a/src/backend/gporca/data/dxl/minidump/InnerJoinReplicatedTableHashSpec.mdp b/src/backend/gporca/data/dxl/minidump/InnerJoinReplicatedTableHashSpec.mdp index 6ac1e7bf4692..581acdf46307 100644 --- a/src/backend/gporca/data/dxl/minidump/InnerJoinReplicatedTableHashSpec.mdp +++ b/src/backend/gporca/data/dxl/minidump/InnerJoinReplicatedTableHashSpec.mdp @@ -361,7 +361,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1, t2 WHERE a1 = b2 GROUP BY b2 ORDER BY b2; - + @@ -377,7 +377,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1, t2 WHERE a1 = b2 GROUP BY b2 ORDER BY b2; - + @@ -395,7 +395,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1, t2 WHERE a1 = b2 GROUP BY b2 ORDER BY b2; - + @@ -418,7 +418,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1, t2 WHERE a1 = b2 GROUP BY b2 ORDER BY b2; - + @@ -436,7 +436,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1, t2 WHERE a1 = b2 GROUP BY b2 ORDER BY b2; - + @@ -455,7 +455,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1, t2 WHERE a1 = b2 GROUP BY b2 ORDER BY b2; - + diff --git a/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp b/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp index b30a407031ed..50b7b3aab77d 100644 --- a/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp +++ b/src/backend/gporca/data/dxl/minidump/Insert-With-HJ-CTE-Agg.mdp @@ -511,7 +511,7 @@ - + @@ -549,7 +549,7 @@ - + @@ -581,7 +581,7 @@ - + @@ -609,7 +609,7 @@ - + @@ -632,7 +632,7 @@ - + @@ -655,7 +655,7 @@ - + @@ -680,7 +680,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/InsertNonSingleton.mdp b/src/backend/gporca/data/dxl/minidump/InsertNonSingleton.mdp index c199c55019c6..481a4ca4cfbb 100644 --- a/src/backend/gporca/data/dxl/minidump/InsertNonSingleton.mdp +++ b/src/backend/gporca/data/dxl/minidump/InsertNonSingleton.mdp @@ -304,7 +304,7 @@ EXPLAIN INSERT INTO snackbox SELECT a FROM (SELECT c FROM hottoast LIMIT 3) hott - + @@ -326,7 +326,7 @@ EXPLAIN INSERT INTO snackbox SELECT a FROM (SELECT c FROM hottoast LIMIT 3) hott - + @@ -340,7 +340,7 @@ EXPLAIN INSERT INTO snackbox SELECT a FROM (SELECT c FROM hottoast LIMIT 3) hott - + @@ -351,7 +351,7 @@ EXPLAIN INSERT INTO snackbox SELECT a FROM (SELECT c FROM hottoast LIMIT 3) hott - + diff --git a/src/backend/gporca/data/dxl/minidump/Intersect-OuterRefs.mdp b/src/backend/gporca/data/dxl/minidump/Intersect-OuterRefs.mdp index 8de33211bc95..0932785d1cdf 100644 --- a/src/backend/gporca/data/dxl/minidump/Intersect-OuterRefs.mdp +++ b/src/backend/gporca/data/dxl/minidump/Intersect-OuterRefs.mdp @@ -1416,7 +1416,7 @@ - + @@ -1436,7 +1436,7 @@ - + @@ -1523,7 +1523,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Intersect-Volatile-Func.mdp b/src/backend/gporca/data/dxl/minidump/Intersect-Volatile-Func.mdp index a59de422794e..bb90193c8550 100644 --- a/src/backend/gporca/data/dxl/minidump/Intersect-Volatile-Func.mdp +++ b/src/backend/gporca/data/dxl/minidump/Intersect-Volatile-Func.mdp @@ -112,7 +112,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JOIN-NonRedistributableCol.mdp b/src/backend/gporca/data/dxl/minidump/JOIN-NonRedistributableCol.mdp index ffa6ff1a5381..220af1e5fb61 100644 --- a/src/backend/gporca/data/dxl/minidump/JOIN-NonRedistributableCol.mdp +++ b/src/backend/gporca/data/dxl/minidump/JOIN-NonRedistributableCol.mdp @@ -273,7 +273,7 @@ explain select * from foo, testhstore where foo.b = testhstore.h; - + @@ -290,7 +290,7 @@ explain select * from foo, testhstore where foo.b = testhstore.h; - + diff --git a/src/backend/gporca/data/dxl/minidump/JOIN-Pred-Cast-Int4.mdp b/src/backend/gporca/data/dxl/minidump/JOIN-Pred-Cast-Int4.mdp index bb02b0cbd584..05c767e122f8 100644 --- a/src/backend/gporca/data/dxl/minidump/JOIN-Pred-Cast-Int4.mdp +++ b/src/backend/gporca/data/dxl/minidump/JOIN-Pred-Cast-Int4.mdp @@ -456,7 +456,7 @@ - + @@ -470,7 +470,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JOIN-Pred-Cast-Varchar.mdp b/src/backend/gporca/data/dxl/minidump/JOIN-Pred-Cast-Varchar.mdp index 4f81ecc0e8a6..3b5c10f88f8e 100644 --- a/src/backend/gporca/data/dxl/minidump/JOIN-Pred-Cast-Varchar.mdp +++ b/src/backend/gporca/data/dxl/minidump/JOIN-Pred-Cast-Varchar.mdp @@ -652,7 +652,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JOIN-cast2text-int4-Eq-cast2text-double.mdp b/src/backend/gporca/data/dxl/minidump/JOIN-cast2text-int4-Eq-cast2text-double.mdp index 0df2ae9e6b6e..292c09fdbc6a 100644 --- a/src/backend/gporca/data/dxl/minidump/JOIN-cast2text-int4-Eq-cast2text-double.mdp +++ b/src/backend/gporca/data/dxl/minidump/JOIN-cast2text-int4-Eq-cast2text-double.mdp @@ -477,7 +477,7 @@ - + @@ -491,7 +491,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JOIN-int4-Eq-double.mdp b/src/backend/gporca/data/dxl/minidump/JOIN-int4-Eq-double.mdp index 5e72b633a132..63dc2dde69b3 100644 --- a/src/backend/gporca/data/dxl/minidump/JOIN-int4-Eq-double.mdp +++ b/src/backend/gporca/data/dxl/minidump/JOIN-int4-Eq-double.mdp @@ -456,7 +456,7 @@ - + @@ -470,7 +470,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JOIN-int4-Eq-int2.mdp b/src/backend/gporca/data/dxl/minidump/JOIN-int4-Eq-int2.mdp index df18f20696c9..ea318e4177a3 100644 --- a/src/backend/gporca/data/dxl/minidump/JOIN-int4-Eq-int2.mdp +++ b/src/backend/gporca/data/dxl/minidump/JOIN-int4-Eq-int2.mdp @@ -355,7 +355,7 @@ - + @@ -369,7 +369,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Join-Disj-Subqs.mdp b/src/backend/gporca/data/dxl/minidump/Join-Disj-Subqs.mdp index 4c76be1dce60..2f2de0ed099d 100644 --- a/src/backend/gporca/data/dxl/minidump/Join-Disj-Subqs.mdp +++ b/src/backend/gporca/data/dxl/minidump/Join-Disj-Subqs.mdp @@ -988,7 +988,7 @@ OR - + diff --git a/src/backend/gporca/data/dxl/minidump/Join-INDF.mdp b/src/backend/gporca/data/dxl/minidump/Join-INDF.mdp index 2bc54c8025df..373a0be9c14f 100644 --- a/src/backend/gporca/data/dxl/minidump/Join-INDF.mdp +++ b/src/backend/gporca/data/dxl/minidump/Join-INDF.mdp @@ -347,7 +347,7 @@ select * from foo, foo2 where foo.a is not distinct from foo2.a; - + @@ -364,7 +364,7 @@ select * from foo, foo2 where foo.a is not distinct from foo2.a; - + diff --git a/src/backend/gporca/data/dxl/minidump/Join-Varchar-Equality.mdp b/src/backend/gporca/data/dxl/minidump/Join-Varchar-Equality.mdp index 8abb5beae924..e1dd56b70c4d 100644 --- a/src/backend/gporca/data/dxl/minidump/Join-Varchar-Equality.mdp +++ b/src/backend/gporca/data/dxl/minidump/Join-Varchar-Equality.mdp @@ -3840,7 +3840,7 @@ - + @@ -3860,7 +3860,7 @@ - + @@ -3880,7 +3880,7 @@ - + @@ -3915,7 +3915,7 @@ - + @@ -3952,7 +3952,7 @@ - + @@ -3975,7 +3975,7 @@ - + @@ -4010,7 +4010,7 @@ - + @@ -4047,7 +4047,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinArityAssociativityCommutativityAboveLimit.mdp b/src/backend/gporca/data/dxl/minidump/JoinArityAssociativityCommutativityAboveLimit.mdp index c9f81b465662..56f38af7f478 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinArityAssociativityCommutativityAboveLimit.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinArityAssociativityCommutativityAboveLimit.mdp @@ -339,7 +339,7 @@ - + @@ -353,7 +353,7 @@ - + @@ -404,7 +404,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinArityAssociativityCommutativityAtLimit.mdp b/src/backend/gporca/data/dxl/minidump/JoinArityAssociativityCommutativityAtLimit.mdp index 6e16970c61ca..84172c12264c 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinArityAssociativityCommutativityAtLimit.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinArityAssociativityCommutativityAtLimit.mdp @@ -336,10 +336,10 @@ - + - + @@ -353,7 +353,7 @@ - + @@ -404,7 +404,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinArityAssociativityCommutativityBelowLimit.mdp b/src/backend/gporca/data/dxl/minidump/JoinArityAssociativityCommutativityBelowLimit.mdp index a2d7c774aa9a..b42351e85bed 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinArityAssociativityCommutativityBelowLimit.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinArityAssociativityCommutativityBelowLimit.mdp @@ -339,7 +339,7 @@ - + @@ -353,7 +353,7 @@ - + @@ -377,7 +377,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinCitextVarchar.mdp b/src/backend/gporca/data/dxl/minidump/JoinCitextVarchar.mdp index 66809635252b..4119513c9f1d 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinCitextVarchar.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinCitextVarchar.mdp @@ -350,7 +350,7 @@ - + @@ -370,7 +370,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinColWithOnlyNDV.mdp b/src/backend/gporca/data/dxl/minidump/JoinColWithOnlyNDV.mdp index 0a08bbcecbd9..abeede746366 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinColWithOnlyNDV.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinColWithOnlyNDV.mdp @@ -11702,7 +11702,7 @@ - + @@ -11890,7 +11890,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinCombinedHashSpecNullsNotColocated.mdp b/src/backend/gporca/data/dxl/minidump/JoinCombinedHashSpecNullsNotColocated.mdp index 85c8d5042c6f..9534d9f83bc7 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinCombinedHashSpecNullsNotColocated.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinCombinedHashSpecNullsNotColocated.mdp @@ -365,7 +365,7 @@ - + @@ -379,7 +379,7 @@ - + @@ -396,7 +396,7 @@ - + @@ -415,7 +415,7 @@ - + @@ -443,7 +443,7 @@ - + @@ -544,7 +544,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinDefaultOpfamiliesUsingNonDefaultOpfamilyOp.mdp b/src/backend/gporca/data/dxl/minidump/JoinDefaultOpfamiliesUsingNonDefaultOpfamilyOp.mdp index 5b18586455df..aafb97f440b7 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinDefaultOpfamiliesUsingNonDefaultOpfamilyOp.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinDefaultOpfamiliesUsingNonDefaultOpfamilyOp.mdp @@ -336,7 +336,7 @@ - + @@ -350,7 +350,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinNDVRemain.mdp b/src/backend/gporca/data/dxl/minidump/JoinNDVRemain.mdp index d77343ee7ee6..83809aca8118 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinNDVRemain.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinNDVRemain.mdp @@ -3158,7 +3158,7 @@ select * from customer_address, store where customer_address.ca_county::text = s - + @@ -3292,7 +3292,7 @@ select * from customer_address, store where customer_address.ca_county::text = s - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinOnViewWithCastedColumn.mdp b/src/backend/gporca/data/dxl/minidump/JoinOnViewWithCastedColumn.mdp index 9642c794de11..aa319d29aded 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinOnViewWithCastedColumn.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinOnViewWithCastedColumn.mdp @@ -348,7 +348,7 @@ - + @@ -368,7 +368,7 @@ - + @@ -394,7 +394,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinOnViewWithCastedColumnAndSubqueryInPredicate.mdp b/src/backend/gporca/data/dxl/minidump/JoinOnViewWithCastedColumnAndSubqueryInPredicate.mdp index 6746a8f1f0f9..1b6bbcf4fb64 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinOnViewWithCastedColumnAndSubqueryInPredicate.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinOnViewWithCastedColumnAndSubqueryInPredicate.mdp @@ -393,7 +393,7 @@ - + @@ -413,7 +413,7 @@ - + @@ -439,7 +439,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinOnViewWithMixOfPushableAndNonpushablePredicates.mdp b/src/backend/gporca/data/dxl/minidump/JoinOnViewWithMixOfPushableAndNonpushablePredicates.mdp index f878d9de07ef..bdc457969a84 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinOnViewWithMixOfPushableAndNonpushablePredicates.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinOnViewWithMixOfPushableAndNonpushablePredicates.mdp @@ -381,7 +381,7 @@ - + @@ -401,7 +401,7 @@ - + @@ -426,7 +426,7 @@ - + @@ -451,7 +451,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinOnViewWithSetReturningColumn.mdp b/src/backend/gporca/data/dxl/minidump/JoinOnViewWithSetReturningColumn.mdp index 8e236754848c..783b12914fca 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinOnViewWithSetReturningColumn.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinOnViewWithSetReturningColumn.mdp @@ -318,7 +318,7 @@ - + @@ -338,7 +338,7 @@ - + @@ -363,7 +363,7 @@ - + @@ -386,7 +386,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinOnViewWithVolatileColumn.mdp b/src/backend/gporca/data/dxl/minidump/JoinOnViewWithVolatileColumn.mdp index e7bf9e03b502..be01160107b8 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinOnViewWithVolatileColumn.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinOnViewWithVolatileColumn.mdp @@ -372,7 +372,7 @@ - + @@ -392,7 +392,7 @@ - + @@ -417,7 +417,7 @@ - + @@ -442,7 +442,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinOptimizationLevelGreedyNonPartTblInnerJoin.mdp b/src/backend/gporca/data/dxl/minidump/JoinOptimizationLevelGreedyNonPartTblInnerJoin.mdp index 3aa1bdf56048..836132437297 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinOptimizationLevelGreedyNonPartTblInnerJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinOptimizationLevelGreedyNonPartTblInnerJoin.mdp @@ -2871,7 +2871,7 @@ - + @@ -2903,7 +2903,7 @@ - + @@ -2941,7 +2941,7 @@ - + @@ -2973,7 +2973,7 @@ - + @@ -2998,7 +2998,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinOptimizationLevelQuery3WayHashJoinPartTbl.mdp b/src/backend/gporca/data/dxl/minidump/JoinOptimizationLevelQuery3WayHashJoinPartTbl.mdp index cdc51ac13a67..5f3c433e2250 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinOptimizationLevelQuery3WayHashJoinPartTbl.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinOptimizationLevelQuery3WayHashJoinPartTbl.mdp @@ -1146,7 +1146,7 @@ - + @@ -1172,7 +1172,7 @@ - + @@ -1204,7 +1204,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinOptimizationLevelQueryNonPartTblInnerJoin.mdp b/src/backend/gporca/data/dxl/minidump/JoinOptimizationLevelQueryNonPartTblInnerJoin.mdp index bd4f69298c5b..29c61db75650 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinOptimizationLevelQueryNonPartTblInnerJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinOptimizationLevelQueryNonPartTblInnerJoin.mdp @@ -2871,7 +2871,7 @@ - + @@ -2903,7 +2903,7 @@ - + @@ -2941,7 +2941,7 @@ - + @@ -2973,7 +2973,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinOrderDPE.mdp b/src/backend/gporca/data/dxl/minidump/JoinOrderDPE.mdp index 880f60c1e3bb..bc7acebf9603 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinOrderDPE.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinOrderDPE.mdp @@ -1685,7 +1685,7 @@ - + @@ -1717,7 +1717,7 @@ - + @@ -1737,7 +1737,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/JoinTinterval.mdp b/src/backend/gporca/data/dxl/minidump/JoinTinterval.mdp index 063ea5b5bc10..0eee3b87b0e7 100644 --- a/src/backend/gporca/data/dxl/minidump/JoinTinterval.mdp +++ b/src/backend/gporca/data/dxl/minidump/JoinTinterval.mdp @@ -314,7 +314,7 @@ - + @@ -331,7 +331,7 @@ - + @@ -348,7 +348,7 @@ - + @@ -367,7 +367,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LASJ-Not-In-Force-Broadcast.mdp b/src/backend/gporca/data/dxl/minidump/LASJ-Not-In-Force-Broadcast.mdp index 9575d801d76c..30545ab7daa7 100644 --- a/src/backend/gporca/data/dxl/minidump/LASJ-Not-In-Force-Broadcast.mdp +++ b/src/backend/gporca/data/dxl/minidump/LASJ-Not-In-Force-Broadcast.mdp @@ -1142,7 +1142,7 @@ - + @@ -1153,7 +1153,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJ-HashJoin-MultiDistKeys-WithComplexPreds.mdp b/src/backend/gporca/data/dxl/minidump/LOJ-HashJoin-MultiDistKeys-WithComplexPreds.mdp index 8a99df389484..21e7f83cbcfc 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJ-HashJoin-MultiDistKeys-WithComplexPreds.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJ-HashJoin-MultiDistKeys-WithComplexPreds.mdp @@ -290,7 +290,7 @@ - + @@ -310,7 +310,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJ-IndexApply-CompsiteKey-Equiv.mdp b/src/backend/gporca/data/dxl/minidump/LOJ-IndexApply-CompsiteKey-Equiv.mdp index d5bd415c820c..354cdad1b8e9 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJ-IndexApply-CompsiteKey-Equiv.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJ-IndexApply-CompsiteKey-Equiv.mdp @@ -5,27 +5,35 @@ Left outer index NL join with multiple distribution keys and the same composite create table foo(a varchar, b int, c int) distributed by(a,b); create table bar(a varchar, b int, c int) distributed by(a,b); create table zoo(a varchar, b int, c int) with(appendonly=true) distributed by(a,b); + +insert into foo (select gen, gen, gen from generate_series(1, 10) gen); +insert into zoo (select gen, gen, gen from generate_series(1, 10) gen); +insert into bar (select gen, gen, gen from generate_series(1, 10) gen); + +analyze foo; +analyze zoo; +analyze bar; + create index bar_idx_ab on bar(b,a); create index zoo_idx_ab on zoo(b,a); set optimizer_enable_hashjoin=off; explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left join zoo on zoo.a=foo.a and zoo.b=foo.b; - QUERY PLAN - Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..1295.00 rows=3 width=48) - -> Nested Loop Left Join (cost=0.00..1295.00 rows=1 width=48) + QUERY PLAN + Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..922.61 rows=10 width=30) + -> Nested Loop Left Join (cost=0.00..922.61 rows=4 width=30) Join Filter: true - -> Nested Loop Left Join (cost=0.00..433.00 rows=1 width=32) + -> Nested Loop Left Join (cost=0.00..491.00 rows=4 width=20) Join Filter: true - -> Table Scan on foo (cost=0.00..431.00 rows=1 width=16) - -> Index Scan using bar_idx_ab on bar (cost=0.00..2.00 rows=1 width=16) - Index Cond: bar.b = foo.b AND bar.a::text = foo.a::text - -> Bitmap Table Scan on zoo (cost=0.00..862.00 rows=1 width=16) - Recheck Cond: zoo.a::text = foo.a::text AND zoo.b = foo.b + -> Seq Scan on foo (cost=0.00..431.00 rows=4 width=10) + -> Index Scan using bar_idx_ab on bar (cost=0.00..60.00 rows=1 width=10) + Index Cond: ((b = foo.b) AND ((a)::text = (foo.a)::text)) + -> Bitmap Heap Scan on zoo (cost=0.00..431.61 rows=1 width=10) + Recheck Cond: (((a)::text = (foo.a)::text) AND (b = foo.b)) -> Bitmap Index Scan on zoo_idx_ab (cost=0.00..0.00 rows=0 width=0) - Index Cond: zoo.b = foo.b AND zoo.a::text = foo.a::text - Settings: enable_nestloop=on; optimizer=on - Optimizer status: PQO version 2.53.11 -(14 rows) + Index Cond: ((b = foo.b) AND ((a)::text = (foo.a)::text)) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) --> @@ -36,14 +44,16 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + - - + + - + + + @@ -59,6 +69,8 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left + + @@ -73,7 +85,9 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + + + @@ -88,7 +102,65 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -97,13 +169,15 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - - + + - + + + @@ -118,11 +192,8 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - - - - - + + @@ -137,7 +208,8 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + + @@ -152,10 +224,62 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -167,18 +291,6 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - - - - - - - - - - - - @@ -186,14 +298,56 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + + + + + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -224,23 +378,18 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - - - + + + + + - - - - - - - - - + + - + @@ -252,6 +401,18 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left + + + + + + + + + + + + @@ -260,48 +421,54 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -319,9 +486,9 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + - + @@ -335,9 +502,9 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + - + @@ -366,9 +533,9 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + - + @@ -396,7 +563,7 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + @@ -429,9 +596,9 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + - + @@ -466,9 +633,9 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + - + @@ -496,7 +663,7 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + @@ -510,9 +677,9 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + - + @@ -527,7 +694,7 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + @@ -555,10 +722,10 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - - + + - + @@ -571,10 +738,14 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left + + + + - + @@ -619,11 +790,11 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left - + - + - + @@ -632,6 +803,10 @@ explain select * from foo left join bar on foo.a = bar.a and foo.b = bar.b left + + + + diff --git a/src/backend/gporca/data/dxl/minidump/LOJ-IsNullPred.mdp b/src/backend/gporca/data/dxl/minidump/LOJ-IsNullPred.mdp index 1c671ec6f9aa..1a9a6dd34eb3 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJ-IsNullPred.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJ-IsNullPred.mdp @@ -12162,7 +12162,7 @@ - + @@ -12299,7 +12299,7 @@ - + @@ -12440,7 +12440,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJ-PushDown.mdp b/src/backend/gporca/data/dxl/minidump/LOJ-PushDown.mdp index 9c77ae8d5e98..4b8c1849a641 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJ-PushDown.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJ-PushDown.mdp @@ -382,7 +382,7 @@ explain select 1 from push_t3 where exists ( - + @@ -393,7 +393,7 @@ explain select 1 from push_t3 where exists ( - + @@ -408,7 +408,7 @@ explain select 1 from push_t3 where exists ( - + @@ -424,7 +424,7 @@ explain select 1 from push_t3 where exists ( - + @@ -434,7 +434,7 @@ explain select 1 from push_t3 where exists ( - + @@ -445,7 +445,7 @@ explain select 1 from push_t3 where exists ( - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJ-With-Agg.mdp b/src/backend/gporca/data/dxl/minidump/LOJ-With-Agg.mdp index ee9548a2608b..c08259ef2892 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJ-With-Agg.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJ-With-Agg.mdp @@ -298,7 +298,7 @@ - + @@ -312,7 +312,7 @@ - + @@ -335,7 +335,7 @@ - + @@ -353,7 +353,7 @@ - + @@ -372,7 +372,7 @@ - + @@ -386,7 +386,7 @@ - + @@ -407,7 +407,7 @@ - + @@ -422,7 +422,7 @@ - + @@ -433,7 +433,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJNonNullRejectingPredicates.mdp b/src/backend/gporca/data/dxl/minidump/LOJNonNullRejectingPredicates.mdp index 8f5a31a942e7..9af5b9e38b43 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJNonNullRejectingPredicates.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJNonNullRejectingPredicates.mdp @@ -434,7 +434,7 @@ - + @@ -490,7 +490,7 @@ - + @@ -550,7 +550,7 @@ - + @@ -612,7 +612,7 @@ - + @@ -662,7 +662,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJNullRejectingPredicates.mdp b/src/backend/gporca/data/dxl/minidump/LOJNullRejectingPredicates.mdp index 4641e26a63c0..228395db2039 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJNullRejectingPredicates.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJNullRejectingPredicates.mdp @@ -432,7 +432,7 @@ explain select * from t1 left join t2 on t1.a=t2.a left join t3 on t2.a=t3.a lef - + @@ -488,7 +488,7 @@ explain select * from t1 left join t2 on t1.a=t2.a left join t3 on t2.a=t3.a lef - + @@ -550,7 +550,7 @@ explain select * from t1 left join t2 on t1.a=t2.a left join t3 on t2.a=t3.a lef - + @@ -664,7 +664,7 @@ explain select * from t1 left join t2 on t1.a=t2.a left join t3 on t2.a=t3.a lef - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJNullRejectingZeroPlacePredicates.mdp b/src/backend/gporca/data/dxl/minidump/LOJNullRejectingZeroPlacePredicates.mdp index e3bfcd7b8ecb..882cccea5574 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJNullRejectingZeroPlacePredicates.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJNullRejectingZeroPlacePredicates.mdp @@ -415,158 +415,158 @@ - - - - - - - - - - - - - - - - - - - - - - - + - + - - + + - - - + - + - - - - - - - - - - - - - + - + + - + - - - - - - - + - + + + + - + - + + + + + - - + + + + + + + + + + + + + - + - + + + + + + + + + + + - - - - - - - - + - + - - - - - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/LOJReorderComplexNestedLOJs.mdp b/src/backend/gporca/data/dxl/minidump/LOJReorderComplexNestedLOJs.mdp index 49a29fcc4b04..6033b4ab674f 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJReorderComplexNestedLOJs.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJReorderComplexNestedLOJs.mdp @@ -1622,7 +1622,7 @@ - + @@ -1678,7 +1678,7 @@ - + @@ -1707,7 +1707,7 @@ - + @@ -1769,7 +1769,7 @@ - + @@ -1877,7 +1877,7 @@ - + @@ -1906,7 +1906,7 @@ - + @@ -1945,7 +1945,7 @@ - + @@ -2007,7 +2007,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJReorderWithComplexPredicate.mdp b/src/backend/gporca/data/dxl/minidump/LOJReorderWithComplexPredicate.mdp index e088da97620b..f2d51707fddb 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJReorderWithComplexPredicate.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJReorderWithComplexPredicate.mdp @@ -1960,7 +1960,7 @@ - + @@ -1995,7 +1995,7 @@ - + @@ -2040,7 +2040,7 @@ - + @@ -2112,7 +2112,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJReorderWithIDF.mdp b/src/backend/gporca/data/dxl/minidump/LOJReorderWithIDF.mdp index 233ceac3ba98..1f6f334d4614 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJReorderWithIDF.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJReorderWithIDF.mdp @@ -1543,7 +1543,7 @@ - + @@ -1578,7 +1578,7 @@ - + @@ -1618,7 +1618,7 @@ - + @@ -1690,7 +1690,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJReorderWithNestedLOJAndFilter.mdp b/src/backend/gporca/data/dxl/minidump/LOJReorderWithNestedLOJAndFilter.mdp index 70aa3e633bfc..e887bbfba3f6 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJReorderWithNestedLOJAndFilter.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJReorderWithNestedLOJAndFilter.mdp @@ -1543,7 +1543,7 @@ - + @@ -1578,7 +1578,7 @@ - + @@ -1623,7 +1623,7 @@ - + @@ -1695,7 +1695,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJReorderWithOneSidedFilter.mdp b/src/backend/gporca/data/dxl/minidump/LOJReorderWithOneSidedFilter.mdp index cb728e0b1e2d..6f1e7cfae370 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJReorderWithOneSidedFilter.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJReorderWithOneSidedFilter.mdp @@ -1957,7 +1957,7 @@ - + @@ -1992,7 +1992,7 @@ - + @@ -2037,7 +2037,7 @@ - + @@ -2074,7 +2074,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJReorderWithSimplePredicate.mdp b/src/backend/gporca/data/dxl/minidump/LOJReorderWithSimplePredicate.mdp index 4165d5e01acb..eac2d7dc0046 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJReorderWithSimplePredicate.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJReorderWithSimplePredicate.mdp @@ -1540,10 +1540,10 @@ - + - + @@ -1578,7 +1578,7 @@ - + @@ -1654,7 +1654,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJ_IDF_no_convert_outer_ref_predicate_with_NULL.mdp b/src/backend/gporca/data/dxl/minidump/LOJ_IDF_no_convert_outer_ref_predicate_with_NULL.mdp index 9179f4f41a33..f34891644fc2 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJ_IDF_no_convert_outer_ref_predicate_with_NULL.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJ_IDF_no_convert_outer_ref_predicate_with_NULL.mdp @@ -283,7 +283,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t1.b IS DISTINC - + @@ -303,7 +303,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t1.b IS DISTINC - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJ_IDF_no_convert_outer_ref_predicate_with_inner_ref.mdp b/src/backend/gporca/data/dxl/minidump/LOJ_IDF_no_convert_outer_ref_predicate_with_inner_ref.mdp index e4816e858858..bec90eb2f614 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJ_IDF_no_convert_outer_ref_predicate_with_inner_ref.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJ_IDF_no_convert_outer_ref_predicate_with_inner_ref.mdp @@ -285,7 +285,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t1.b IS DISTINC - + @@ -305,7 +305,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t1.b IS DISTINC - + @@ -330,7 +330,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t1.b IS DISTINC - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJ_bb_mpph.mdp b/src/backend/gporca/data/dxl/minidump/LOJ_bb_mpph.mdp index fd3de7990fe8..1b675094d8e9 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJ_bb_mpph.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJ_bb_mpph.mdp @@ -5776,7 +5776,7 @@ - + @@ -5791,7 +5791,7 @@ - + @@ -5811,7 +5811,7 @@ - + @@ -5828,7 +5828,7 @@ - + @@ -5847,7 +5847,7 @@ - + @@ -5870,7 +5870,7 @@ - + @@ -5887,7 +5887,7 @@ - + @@ -5906,7 +5906,7 @@ - + @@ -5925,7 +5925,7 @@ - + @@ -5942,7 +5942,7 @@ - + @@ -5961,7 +5961,7 @@ - + @@ -5982,7 +5982,7 @@ - + @@ -6005,7 +6005,7 @@ - + @@ -6098,7 +6098,7 @@ - + @@ -6115,7 +6115,7 @@ - + @@ -6167,7 +6167,7 @@ - + @@ -6228,7 +6228,7 @@ - + @@ -6249,7 +6249,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJ_convert_to_inner_with_inner_predicate_IDF.mdp b/src/backend/gporca/data/dxl/minidump/LOJ_convert_to_inner_with_inner_predicate_IDF.mdp index 96d3c72ff9fe..871c8276286b 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJ_convert_to_inner_with_inner_predicate_IDF.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJ_convert_to_inner_with_inner_predicate_IDF.mdp @@ -276,7 +276,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t2.b IS DISTINC - + @@ -296,7 +296,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t2.b IS DISTINC - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJ_dont_convert_to_inner_with_inner_predicate_IDF_const.mdp b/src/backend/gporca/data/dxl/minidump/LOJ_dont_convert_to_inner_with_inner_predicate_IDF_const.mdp index bc2e327012ec..b49c5accd86e 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJ_dont_convert_to_inner_with_inner_predicate_IDF_const.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJ_dont_convert_to_inner_with_inner_predicate_IDF_const.mdp @@ -277,7 +277,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t2.b IS DISTINC - + @@ -297,7 +297,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t2.b IS DISTINC - + @@ -322,7 +322,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t2.b IS DISTINC - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJ_dont_convert_to_inner_with_outer_predicate_INDF.mdp b/src/backend/gporca/data/dxl/minidump/LOJ_dont_convert_to_inner_with_outer_predicate_INDF.mdp index 3fbe99331fbc..b222e031d0ae 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJ_dont_convert_to_inner_with_outer_predicate_INDF.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJ_dont_convert_to_inner_with_outer_predicate_INDF.mdp @@ -279,7 +279,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t2.b IS NOT DIS - + @@ -299,7 +299,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t2.b IS NOT DIS - + @@ -326,7 +326,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t2.b IS NOT DIS - + diff --git a/src/backend/gporca/data/dxl/minidump/LOJ_dont_convert_to_inner_with_outer_predicate_INDF_const.mdp b/src/backend/gporca/data/dxl/minidump/LOJ_dont_convert_to_inner_with_outer_predicate_INDF_const.mdp index f7ddcb30933d..b5fa09852b71 100644 --- a/src/backend/gporca/data/dxl/minidump/LOJ_dont_convert_to_inner_with_outer_predicate_INDF_const.mdp +++ b/src/backend/gporca/data/dxl/minidump/LOJ_dont_convert_to_inner_with_outer_predicate_INDF_const.mdp @@ -279,7 +279,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t2.b IS NOT DIS - + @@ -299,7 +299,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t2.b IS NOT DIS - + @@ -326,7 +326,7 @@ EXPLAIN SELECT * FROM t1 LEFT OUTER JOIN t2 ON t1.a = t2.a WHERE t2.b IS NOT DIS - + diff --git a/src/backend/gporca/data/dxl/minidump/LeftJoin-DPv2-With-Select.mdp b/src/backend/gporca/data/dxl/minidump/LeftJoin-DPv2-With-Select.mdp index 1502ce209483..6a7038128997 100644 --- a/src/backend/gporca/data/dxl/minidump/LeftJoin-DPv2-With-Select.mdp +++ b/src/backend/gporca/data/dxl/minidump/LeftJoin-DPv2-With-Select.mdp @@ -351,7 +351,7 @@ - + @@ -377,7 +377,7 @@ - + @@ -405,7 +405,7 @@ - + @@ -433,7 +433,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LeftJoin-UnsupportedFilter-Cardinality.mdp b/src/backend/gporca/data/dxl/minidump/LeftJoin-UnsupportedFilter-Cardinality.mdp index 2bb7cde6d4af..0bf69393e50b 100644 --- a/src/backend/gporca/data/dxl/minidump/LeftJoin-UnsupportedFilter-Cardinality.mdp +++ b/src/backend/gporca/data/dxl/minidump/LeftJoin-UnsupportedFilter-Cardinality.mdp @@ -790,7 +790,7 @@ explain select * from foo left join bar on foo.a=bar.a left join zoo on foo.a::i - + @@ -816,7 +816,7 @@ explain select * from foo left join bar on foo.a=bar.a left join zoo on foo.a::i - + @@ -852,7 +852,7 @@ explain select * from foo left join bar on foo.a=bar.a left join zoo on foo.a::i - + diff --git a/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Coalesce.mdp b/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Coalesce.mdp index b231b765bcff..94cbf8977553 100644 --- a/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Coalesce.mdp +++ b/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Coalesce.mdp @@ -704,7 +704,7 @@ where coalesce(t2.fname, t3.fname) is not null; - + @@ -715,7 +715,7 @@ where coalesce(t2.fname, t3.fname) is not null; - + @@ -728,7 +728,7 @@ where coalesce(t2.fname, t3.fname) is not null; - + @@ -743,7 +743,7 @@ where coalesce(t2.fname, t3.fname) is not null; - + @@ -759,7 +759,7 @@ where coalesce(t2.fname, t3.fname) is not null; - + @@ -772,7 +772,7 @@ where coalesce(t2.fname, t3.fname) is not null; - + @@ -786,7 +786,7 @@ where coalesce(t2.fname, t3.fname) is not null; - + @@ -809,7 +809,7 @@ where coalesce(t2.fname, t3.fname) is not null; - + @@ -829,7 +829,7 @@ where coalesce(t2.fname, t3.fname) is not null; - + diff --git a/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Col-Const-Pred.mdp b/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Col-Const-Pred.mdp index a1b8fd6c45d1..af18f1846dad 100644 --- a/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Col-Const-Pred.mdp +++ b/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Col-Const-Pred.mdp @@ -2113,7 +2113,7 @@ - + @@ -2276,7 +2276,7 @@ - + @@ -2342,7 +2342,7 @@ - + @@ -2475,7 +2475,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Pred-On-Inner.mdp b/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Pred-On-Inner.mdp index 6573be81d041..a0c36d0bd9e4 100644 --- a/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Pred-On-Inner.mdp +++ b/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Pred-On-Inner.mdp @@ -257,7 +257,7 @@ - + @@ -277,7 +277,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Pred-On-Inner2.mdp b/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Pred-On-Inner2.mdp index 5c6543898e8b..4b0c693f77c8 100644 --- a/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Pred-On-Inner2.mdp +++ b/src/backend/gporca/data/dxl/minidump/LeftJoin-With-Pred-On-Inner2.mdp @@ -397,7 +397,7 @@ - + @@ -411,7 +411,7 @@ - + @@ -435,7 +435,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LeftJoinBroadcastTableHashSpec.mdp b/src/backend/gporca/data/dxl/minidump/LeftJoinBroadcastTableHashSpec.mdp index 79f1ef6df562..383a13ae84a4 100644 --- a/src/backend/gporca/data/dxl/minidump/LeftJoinBroadcastTableHashSpec.mdp +++ b/src/backend/gporca/data/dxl/minidump/LeftJoinBroadcastTableHashSpec.mdp @@ -369,7 +369,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1 LEFT JOIN t2 ON a1 = b2 GROUP BY b2 ORDER BY - + @@ -385,7 +385,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1 LEFT JOIN t2 ON a1 = b2 GROUP BY b2 ORDER BY - + @@ -403,7 +403,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1 LEFT JOIN t2 ON a1 = b2 GROUP BY b2 ORDER BY - + @@ -426,7 +426,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1 LEFT JOIN t2 ON a1 = b2 GROUP BY b2 ORDER BY - + @@ -444,7 +444,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1 LEFT JOIN t2 ON a1 = b2 GROUP BY b2 ORDER BY - + @@ -463,7 +463,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1 LEFT JOIN t2 ON a1 = b2 GROUP BY b2 ORDER BY - + @@ -477,7 +477,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1 LEFT JOIN t2 ON a1 = b2 GROUP BY b2 ORDER BY - + @@ -500,7 +500,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1 LEFT JOIN t2 ON a1 = b2 GROUP BY b2 ORDER BY - + @@ -518,7 +518,7 @@ EXPLAIN SELECT b2, sum(c1) FROM t1 LEFT JOIN t2 ON a1 = b2 GROUP BY b2 ORDER BY - + diff --git a/src/backend/gporca/data/dxl/minidump/LeftJoinDPv2JoinOrder.mdp b/src/backend/gporca/data/dxl/minidump/LeftJoinDPv2JoinOrder.mdp index e5bce5f42cb8..72371a3fffc1 100644 --- a/src/backend/gporca/data/dxl/minidump/LeftJoinDPv2JoinOrder.mdp +++ b/src/backend/gporca/data/dxl/minidump/LeftJoinDPv2JoinOrder.mdp @@ -1445,7 +1445,7 @@ - + @@ -1483,7 +1483,7 @@ - + @@ -1509,7 +1509,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/LeftJoinNullsNotColocated.mdp b/src/backend/gporca/data/dxl/minidump/LeftJoinNullsNotColocated.mdp index 40ec6519daf9..199aedd223bd 100644 --- a/src/backend/gporca/data/dxl/minidump/LeftJoinNullsNotColocated.mdp +++ b/src/backend/gporca/data/dxl/minidump/LeftJoinNullsNotColocated.mdp @@ -421,7 +421,7 @@ on id2 = id3 distributed by (id1); - + @@ -445,7 +445,7 @@ on id2 = id3 distributed by (id1); - + @@ -465,7 +465,7 @@ on id2 = id3 distributed by (id1); - + @@ -488,7 +488,7 @@ on id2 = id3 distributed by (id1); - + diff --git a/src/backend/gporca/data/dxl/minidump/LeftOuter2InnerUnionAllAntiSemiJoin-Tpcds.mdp b/src/backend/gporca/data/dxl/minidump/LeftOuter2InnerUnionAllAntiSemiJoin-Tpcds.mdp index 393407dcb73f..b5adfcbe07a8 100644 --- a/src/backend/gporca/data/dxl/minidump/LeftOuter2InnerUnionAllAntiSemiJoin-Tpcds.mdp +++ b/src/backend/gporca/data/dxl/minidump/LeftOuter2InnerUnionAllAntiSemiJoin-Tpcds.mdp @@ -11634,7 +11634,7 @@ select * from v2 left outer join v1 on v2.i_item_sk = v1.ss_item_sk limit 5; - + @@ -11646,7 +11646,7 @@ select * from v2 left outer join v1 on v2.i_item_sk = v1.ss_item_sk limit 5; - + @@ -11660,7 +11660,7 @@ select * from v2 left outer join v1 on v2.i_item_sk = v1.ss_item_sk limit 5; - + @@ -11672,7 +11672,7 @@ select * from v2 left outer join v1 on v2.i_item_sk = v1.ss_item_sk limit 5; - + diff --git a/src/backend/gporca/data/dxl/minidump/LeftOuter2InnerUnionAllAntiSemiJoin.mdp b/src/backend/gporca/data/dxl/minidump/LeftOuter2InnerUnionAllAntiSemiJoin.mdp index 3c309e470c7f..9f76ab7af80e 100644 --- a/src/backend/gporca/data/dxl/minidump/LeftOuter2InnerUnionAllAntiSemiJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/LeftOuter2InnerUnionAllAntiSemiJoin.mdp @@ -304,7 +304,7 @@ and ei.entity_id = i.ad_id; - + @@ -321,7 +321,7 @@ and ei.entity_id = i.ad_id; - + @@ -425,7 +425,7 @@ and ei.entity_id = i.ad_id; - + @@ -440,7 +440,7 @@ and ei.entity_id = i.ad_id; - + @@ -503,7 +503,7 @@ and ei.entity_id = i.ad_id; - + @@ -665,7 +665,7 @@ and ei.entity_id = i.ad_id; - + @@ -763,7 +763,7 @@ and ei.entity_id = i.ad_id; - + @@ -780,7 +780,7 @@ and ei.entity_id = i.ad_id; - + diff --git a/src/backend/gporca/data/dxl/minidump/MDQAs-Grouping-OrderBy.mdp b/src/backend/gporca/data/dxl/minidump/MDQAs-Grouping-OrderBy.mdp index a6f968911ad2..c8455302b782 100644 --- a/src/backend/gporca/data/dxl/minidump/MDQAs-Grouping-OrderBy.mdp +++ b/src/backend/gporca/data/dxl/minidump/MDQAs-Grouping-OrderBy.mdp @@ -467,7 +467,7 @@ SQL: - + @@ -482,7 +482,7 @@ SQL: - + @@ -501,7 +501,7 @@ SQL: - + @@ -516,7 +516,7 @@ SQL: - + @@ -537,7 +537,7 @@ SQL: - + @@ -634,7 +634,7 @@ SQL: - + diff --git a/src/backend/gporca/data/dxl/minidump/MDQAs-Grouping.mdp b/src/backend/gporca/data/dxl/minidump/MDQAs-Grouping.mdp index 0b835973964e..66cc35b325ce 100644 --- a/src/backend/gporca/data/dxl/minidump/MDQAs-Grouping.mdp +++ b/src/backend/gporca/data/dxl/minidump/MDQAs-Grouping.mdp @@ -458,7 +458,7 @@ SQL: - + @@ -475,7 +475,7 @@ SQL: - + @@ -572,7 +572,7 @@ SQL: - + diff --git a/src/backend/gporca/data/dxl/minidump/MDQAs-Union.mdp b/src/backend/gporca/data/dxl/minidump/MDQAs-Union.mdp index 05061ae272fc..217517a60c5f 100644 --- a/src/backend/gporca/data/dxl/minidump/MDQAs-Union.mdp +++ b/src/backend/gporca/data/dxl/minidump/MDQAs-Union.mdp @@ -511,7 +511,7 @@ select a,count(distinct a), count(distinct b) from t1 group by a - + @@ -528,7 +528,7 @@ select a,count(distinct a), count(distinct b) from t1 group by a - + @@ -549,7 +549,7 @@ select a,count(distinct a), count(distinct b) from t1 group by a - + @@ -565,7 +565,7 @@ select a,count(distinct a), count(distinct b) from t1 group by a - + @@ -662,7 +662,7 @@ select a,count(distinct a), count(distinct b) from t1 group by a - + @@ -918,7 +918,7 @@ select a,count(distinct a), count(distinct b) from t1 group by a - + @@ -1015,7 +1015,7 @@ select a,count(distinct a), count(distinct b) from t1 group by a - + diff --git a/src/backend/gporca/data/dxl/minidump/ManyTextUnionsInSubquery.mdp b/src/backend/gporca/data/dxl/minidump/ManyTextUnionsInSubquery.mdp index afffc29aff83..7236684a62f1 100644 --- a/src/backend/gporca/data/dxl/minidump/ManyTextUnionsInSubquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/ManyTextUnionsInSubquery.mdp @@ -591,7 +591,7 @@ - + @@ -602,14 +602,14 @@ - + - + @@ -955,7 +955,7 @@ - + @@ -971,7 +971,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/MissingColStatsWithLOJ.mdp b/src/backend/gporca/data/dxl/minidump/MissingColStatsWithLOJ.mdp index 4267f663ed87..149c44ef1f60 100644 --- a/src/backend/gporca/data/dxl/minidump/MissingColStatsWithLOJ.mdp +++ b/src/backend/gporca/data/dxl/minidump/MissingColStatsWithLOJ.mdp @@ -200,7 +200,7 @@ - + @@ -214,7 +214,7 @@ - + @@ -232,7 +232,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/MotionHazard-MaterializeUnderResult.mdp b/src/backend/gporca/data/dxl/minidump/MotionHazard-MaterializeUnderResult.mdp index 23e8ecccf57f..8fb4e781cad9 100644 --- a/src/backend/gporca/data/dxl/minidump/MotionHazard-MaterializeUnderResult.mdp +++ b/src/backend/gporca/data/dxl/minidump/MotionHazard-MaterializeUnderResult.mdp @@ -415,7 +415,7 @@ Optimizer status: PQO version 2.67.0 - + @@ -523,7 +523,7 @@ Optimizer status: PQO version 2.67.0 - + diff --git a/src/backend/gporca/data/dxl/minidump/MotionHazard-NoMaterializeGatherUnderResult.mdp b/src/backend/gporca/data/dxl/minidump/MotionHazard-NoMaterializeGatherUnderResult.mdp index 758aeaac9a76..4db5c9847307 100644 --- a/src/backend/gporca/data/dxl/minidump/MotionHazard-NoMaterializeGatherUnderResult.mdp +++ b/src/backend/gporca/data/dxl/minidump/MotionHazard-NoMaterializeGatherUnderResult.mdp @@ -411,7 +411,7 @@ explain select tab3.k, (select tab2.k from tab2 where tab2.i = tab1.i limit 1) a - + @@ -519,7 +519,7 @@ explain select tab3.k, (select tab2.k from tab2 where tab2.i = tab1.i limit 1) a - + diff --git a/src/backend/gporca/data/dxl/minidump/MotionHazard-NoMaterializeHashAggUnderResult.mdp b/src/backend/gporca/data/dxl/minidump/MotionHazard-NoMaterializeHashAggUnderResult.mdp index 94511c3ff438..82883e3c74d6 100644 --- a/src/backend/gporca/data/dxl/minidump/MotionHazard-NoMaterializeHashAggUnderResult.mdp +++ b/src/backend/gporca/data/dxl/minidump/MotionHazard-NoMaterializeHashAggUnderResult.mdp @@ -450,7 +450,7 @@ explain select f.k, f.subq from (select tab3.k, (select tab2.k from tab2 where t - + @@ -464,7 +464,7 @@ explain select f.k, f.subq from (select tab3.k, (select tab2.k from tab2 where t - + @@ -480,7 +480,7 @@ explain select f.k, f.subq from (select tab3.k, (select tab2.k from tab2 where t - + @@ -494,7 +494,7 @@ explain select f.k, f.subq from (select tab3.k, (select tab2.k from tab2 where t - + @@ -508,7 +508,7 @@ explain select f.k, f.subq from (select tab3.k, (select tab2.k from tab2 where t - + @@ -616,7 +616,7 @@ explain select f.k, f.subq from (select tab3.k, (select tab2.k from tab2 where t - + @@ -633,7 +633,7 @@ explain select f.k, f.subq from (select tab3.k, (select tab2.k from tab2 where t - + @@ -655,7 +655,7 @@ explain select f.k, f.subq from (select tab3.k, (select tab2.k from tab2 where t - + @@ -672,7 +672,7 @@ explain select f.k, f.subq from (select tab3.k, (select tab2.k from tab2 where t - + @@ -686,7 +686,7 @@ explain select f.k, f.subq from (select tab3.k, (select tab2.k from tab2 where t - + diff --git a/src/backend/gporca/data/dxl/minidump/MotionHazard-NoMaterializeSortUnderResult.mdp b/src/backend/gporca/data/dxl/minidump/MotionHazard-NoMaterializeSortUnderResult.mdp index feb344eb43bf..a9a4a6123ffa 100644 --- a/src/backend/gporca/data/dxl/minidump/MotionHazard-NoMaterializeSortUnderResult.mdp +++ b/src/backend/gporca/data/dxl/minidump/MotionHazard-NoMaterializeSortUnderResult.mdp @@ -436,7 +436,7 @@ explain select tab3.k, (select tab2.k from tab2 where tab2.i = tab1.i limit 1) a - + @@ -544,7 +544,7 @@ explain select tab3.k, (select tab2.k from tab2 where tab2.i = tab1.i limit 1) a - + @@ -562,7 +562,7 @@ explain select tab3.k, (select tab2.k from tab2 where tab2.i = tab1.i limit 1) a - + diff --git a/src/backend/gporca/data/dxl/minidump/MultiColumnDQA-InnerJoin-GroupBy-HashAggregate.mdp b/src/backend/gporca/data/dxl/minidump/MultiColumnDQA-InnerJoin-GroupBy-HashAggregate.mdp index 6d4c26560c98..6970ff0f3316 100644 --- a/src/backend/gporca/data/dxl/minidump/MultiColumnDQA-InnerJoin-GroupBy-HashAggregate.mdp +++ b/src/backend/gporca/data/dxl/minidump/MultiColumnDQA-InnerJoin-GroupBy-HashAggregate.mdp @@ -450,7 +450,7 @@ - + @@ -461,7 +461,7 @@ - + @@ -472,7 +472,7 @@ - + @@ -509,7 +509,7 @@ - + @@ -538,7 +538,7 @@ - + @@ -564,7 +564,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/MultiDistKeyJoinCardinality.mdp b/src/backend/gporca/data/dxl/minidump/MultiDistKeyJoinCardinality.mdp index 3f8b11b92ab5..75daf035296b 100644 --- a/src/backend/gporca/data/dxl/minidump/MultiDistKeyJoinCardinality.mdp +++ b/src/backend/gporca/data/dxl/minidump/MultiDistKeyJoinCardinality.mdp @@ -1182,7 +1182,7 @@ - + @@ -1202,7 +1202,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/MultiDistKeyWithOtherPredsJoinCardinality.mdp b/src/backend/gporca/data/dxl/minidump/MultiDistKeyWithOtherPredsJoinCardinality.mdp index 52e9275c99b6..66cc0b39c190 100644 --- a/src/backend/gporca/data/dxl/minidump/MultiDistKeyWithOtherPredsJoinCardinality.mdp +++ b/src/backend/gporca/data/dxl/minidump/MultiDistKeyWithOtherPredsJoinCardinality.mdp @@ -687,10 +687,10 @@ - + - + @@ -722,7 +722,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/MultiLevel-IN-Subquery.mdp b/src/backend/gporca/data/dxl/minidump/MultiLevel-IN-Subquery.mdp index 3e6e9edc18c6..78393bf3dda8 100644 --- a/src/backend/gporca/data/dxl/minidump/MultiLevel-IN-Subquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/MultiLevel-IN-Subquery.mdp @@ -689,7 +689,7 @@ - + @@ -703,7 +703,7 @@ - + @@ -750,7 +750,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/MultiLevelDecorrelationWithSemiJoins.mdp b/src/backend/gporca/data/dxl/minidump/MultiLevelDecorrelationWithSemiJoins.mdp index 0a3adb5be46e..71fda49641cf 100644 --- a/src/backend/gporca/data/dxl/minidump/MultiLevelDecorrelationWithSemiJoins.mdp +++ b/src/backend/gporca/data/dxl/minidump/MultiLevelDecorrelationWithSemiJoins.mdp @@ -410,7 +410,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/MultipleDampedPredJoinCardinality.mdp b/src/backend/gporca/data/dxl/minidump/MultipleDampedPredJoinCardinality.mdp index 0ed1f2dd1673..366aeefcea67 100644 --- a/src/backend/gporca/data/dxl/minidump/MultipleDampedPredJoinCardinality.mdp +++ b/src/backend/gporca/data/dxl/minidump/MultipleDampedPredJoinCardinality.mdp @@ -1975,7 +1975,7 @@ - + @@ -1995,7 +1995,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/MultipleIndependentPredJoinCardinality.mdp b/src/backend/gporca/data/dxl/minidump/MultipleIndependentPredJoinCardinality.mdp index 28119b57e566..53a370706fa2 100644 --- a/src/backend/gporca/data/dxl/minidump/MultipleIndependentPredJoinCardinality.mdp +++ b/src/backend/gporca/data/dxl/minidump/MultipleIndependentPredJoinCardinality.mdp @@ -5757,7 +5757,7 @@ explain select * from t1, t2, t3 where t1.a = t2.a and t2.a = t3.a and t1.b = t3 - + @@ -5783,7 +5783,7 @@ explain select * from t1, t2, t3 where t1.a = t2.a and t2.a = t3.a and t1.b = t3 - + @@ -5819,7 +5819,7 @@ explain select * from t1, t2, t3 where t1.a = t2.a and t2.a = t3.a and t1.b = t3 - + diff --git a/src/backend/gporca/data/dxl/minidump/MultipleUpdateWithJoinOnDistCol.mdp b/src/backend/gporca/data/dxl/minidump/MultipleUpdateWithJoinOnDistCol.mdp index 39cb5652be1e..0f11dcd8f792 100644 --- a/src/backend/gporca/data/dxl/minidump/MultipleUpdateWithJoinOnDistCol.mdp +++ b/src/backend/gporca/data/dxl/minidump/MultipleUpdateWithJoinOnDistCol.mdp @@ -304,7 +304,7 @@ - + @@ -330,7 +330,7 @@ - + @@ -358,7 +358,7 @@ - + @@ -379,7 +379,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/NOT-IN-ArrayCmp.mdp b/src/backend/gporca/data/dxl/minidump/NOT-IN-ArrayCmp.mdp index 1bd9ed06a630..a9a50fbeb578 100644 --- a/src/backend/gporca/data/dxl/minidump/NOT-IN-ArrayCmp.mdp +++ b/src/backend/gporca/data/dxl/minidump/NOT-IN-ArrayCmp.mdp @@ -278,7 +278,7 @@ - + @@ -298,7 +298,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/NOT-IN-NotNullBoth.mdp b/src/backend/gporca/data/dxl/minidump/NOT-IN-NotNullBoth.mdp index ffa732b7cc31..bff652f88e12 100644 --- a/src/backend/gporca/data/dxl/minidump/NOT-IN-NotNullBoth.mdp +++ b/src/backend/gporca/data/dxl/minidump/NOT-IN-NotNullBoth.mdp @@ -255,7 +255,7 @@ - + @@ -269,7 +269,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/NOT-IN-NullInner.mdp b/src/backend/gporca/data/dxl/minidump/NOT-IN-NullInner.mdp index 17b91238d3dc..7450ed6ac6ac 100644 --- a/src/backend/gporca/data/dxl/minidump/NOT-IN-NullInner.mdp +++ b/src/backend/gporca/data/dxl/minidump/NOT-IN-NullInner.mdp @@ -299,7 +299,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/NOT-IN-NullOuter.mdp b/src/backend/gporca/data/dxl/minidump/NOT-IN-NullOuter.mdp index c5f04180bdb3..25e3faf6c151 100644 --- a/src/backend/gporca/data/dxl/minidump/NOT-IN-NullOuter.mdp +++ b/src/backend/gporca/data/dxl/minidump/NOT-IN-NullOuter.mdp @@ -299,7 +299,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/NaryWithLojAndNonLojChilds.mdp b/src/backend/gporca/data/dxl/minidump/NaryWithLojAndNonLojChilds.mdp index 39fb3a7861d8..28222aa13c3b 100644 --- a/src/backend/gporca/data/dxl/minidump/NaryWithLojAndNonLojChilds.mdp +++ b/src/backend/gporca/data/dxl/minidump/NaryWithLojAndNonLojChilds.mdp @@ -1732,7 +1732,7 @@ - + @@ -1758,7 +1758,7 @@ - + @@ -1790,7 +1790,7 @@ - + @@ -1819,7 +1819,7 @@ - + @@ -1868,7 +1868,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Nested-Setops-2.mdp b/src/backend/gporca/data/dxl/minidump/Nested-Setops-2.mdp index 667635c48d14..8882432bbfa8 100644 --- a/src/backend/gporca/data/dxl/minidump/Nested-Setops-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/Nested-Setops-2.mdp @@ -600,7 +600,7 @@ - + @@ -614,7 +614,7 @@ - + @@ -631,7 +631,7 @@ - + @@ -650,7 +650,7 @@ - + @@ -682,7 +682,7 @@ - + @@ -695,7 +695,7 @@ - + @@ -709,7 +709,7 @@ - + @@ -722,7 +722,7 @@ - + @@ -737,7 +737,7 @@ - + @@ -753,7 +753,7 @@ - + @@ -766,7 +766,7 @@ - + @@ -777,85 +777,83 @@ - + - + - - - - - + + - - - - - - - - - + + - - - - - - - - - + + + + + + + + + - + - + - - + + + + + - - - - - - + - - + + + + + - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - + @@ -864,7 +862,7 @@ - + @@ -878,7 +876,7 @@ - + @@ -891,7 +889,7 @@ - + @@ -906,7 +904,7 @@ - + @@ -922,7 +920,7 @@ - + @@ -935,7 +933,7 @@ - + @@ -946,85 +944,83 @@ - + - + - - - - - + + - - - - - - - - - + + - - - - - - - - - + + + + + + + + + - + - + - - + + + + + - - - - - - + - - + + + + + - - + + + + + + + + + - - - - - - - - - + + + + + + + + + - + @@ -1034,7 +1030,7 @@ - + @@ -1048,7 +1044,7 @@ - + @@ -1061,7 +1057,7 @@ - + @@ -1076,7 +1072,7 @@ - + @@ -1092,7 +1088,7 @@ - + @@ -1105,7 +1101,7 @@ - + @@ -1116,78 +1112,76 @@ - + - + - - - - - + + - + - - - - - - - - - + + + + + + + + + - + - + - - + + + + + - - - - - - + - - + + + + + - + - - - - - - - - - + + + + + + + + + - + diff --git a/src/backend/gporca/data/dxl/minidump/NestedJoinWithCastedColumn.mdp b/src/backend/gporca/data/dxl/minidump/NestedJoinWithCastedColumn.mdp index 972e80b8d468..92ce295de050 100644 --- a/src/backend/gporca/data/dxl/minidump/NestedJoinWithCastedColumn.mdp +++ b/src/backend/gporca/data/dxl/minidump/NestedJoinWithCastedColumn.mdp @@ -585,7 +585,7 @@ - + @@ -601,7 +601,7 @@ - + @@ -612,7 +612,7 @@ - + @@ -694,7 +694,7 @@ - + @@ -715,7 +715,7 @@ - + @@ -732,7 +732,7 @@ - + @@ -751,7 +751,7 @@ - + @@ -773,7 +773,7 @@ - + @@ -786,7 +786,7 @@ - + @@ -800,7 +800,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/NestedSubqLimitBindings.mdp b/src/backend/gporca/data/dxl/minidump/NestedSubqLimitBindings.mdp index 09170e7d7fd0..3ac5d9473ac2 100644 --- a/src/backend/gporca/data/dxl/minidump/NestedSubqLimitBindings.mdp +++ b/src/backend/gporca/data/dxl/minidump/NestedSubqLimitBindings.mdp @@ -484,7 +484,7 @@ select a from t as t1 where a in ( - + @@ -498,7 +498,7 @@ select a from t as t1 where a in ( - + @@ -509,7 +509,7 @@ select a from t as t1 where a in ( - + @@ -523,7 +523,7 @@ select a from t as t1 where a in ( - + @@ -533,7 +533,7 @@ select a from t as t1 where a in ( - + @@ -551,7 +551,7 @@ select a from t as t1 where a in ( - + @@ -561,7 +561,7 @@ select a from t as t1 where a in ( - + @@ -579,7 +579,7 @@ select a from t as t1 where a in ( - + @@ -589,7 +589,7 @@ select a from t as t1 where a in ( - + @@ -600,7 +600,7 @@ select a from t as t1 where a in ( - + @@ -640,7 +640,7 @@ select a from t as t1 where a in ( - + @@ -653,7 +653,7 @@ select a from t as t1 where a in ( - + @@ -668,7 +668,7 @@ select a from t as t1 where a in ( - + @@ -678,7 +678,7 @@ select a from t as t1 where a in ( - + @@ -691,7 +691,7 @@ select a from t as t1 where a in ( - + @@ -706,7 +706,7 @@ select a from t as t1 where a in ( - + @@ -772,7 +772,7 @@ select a from t as t1 where a in ( - + @@ -785,7 +785,7 @@ select a from t as t1 where a in ( - + @@ -800,7 +800,7 @@ select a from t as t1 where a in ( - + @@ -866,7 +866,7 @@ select a from t as t1 where a in ( - + @@ -879,7 +879,7 @@ select a from t as t1 where a in ( - + @@ -894,7 +894,7 @@ select a from t as t1 where a in ( - + diff --git a/src/backend/gporca/data/dxl/minidump/NoBroadcastUnderGatherForWindowFunction.mdp b/src/backend/gporca/data/dxl/minidump/NoBroadcastUnderGatherForWindowFunction.mdp index 337cb723f57e..87c0171cb14b 100644 --- a/src/backend/gporca/data/dxl/minidump/NoBroadcastUnderGatherForWindowFunction.mdp +++ b/src/backend/gporca/data/dxl/minidump/NoBroadcastUnderGatherForWindowFunction.mdp @@ -436,7 +436,7 @@ WHERE buyer_name = 'ABC' - + @@ -457,7 +457,7 @@ WHERE buyer_name = 'ABC' - + @@ -472,7 +472,7 @@ WHERE buyer_name = 'ABC' - + diff --git a/src/backend/gporca/data/dxl/minidump/NoDistKeyMultiPredJoinCardinality.mdp b/src/backend/gporca/data/dxl/minidump/NoDistKeyMultiPredJoinCardinality.mdp index d9b6d9382ee7..fb2f27dc7fd6 100644 --- a/src/backend/gporca/data/dxl/minidump/NoDistKeyMultiPredJoinCardinality.mdp +++ b/src/backend/gporca/data/dxl/minidump/NoDistKeyMultiPredJoinCardinality.mdp @@ -1587,7 +1587,7 @@ - + @@ -1613,7 +1613,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/NoPushdownPredicateWithCTEAnchor.mdp b/src/backend/gporca/data/dxl/minidump/NoPushdownPredicateWithCTEAnchor.mdp index 49f6af3e14f9..29cc995064c2 100644 --- a/src/backend/gporca/data/dxl/minidump/NoPushdownPredicateWithCTEAnchor.mdp +++ b/src/backend/gporca/data/dxl/minidump/NoPushdownPredicateWithCTEAnchor.mdp @@ -461,7 +461,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/NoRedistributeOnAppend.mdp b/src/backend/gporca/data/dxl/minidump/NoRedistributeOnAppend.mdp index a6fddc528273..8ff25f27b912 100644 --- a/src/backend/gporca/data/dxl/minidump/NoRedistributeOnAppend.mdp +++ b/src/backend/gporca/data/dxl/minidump/NoRedistributeOnAppend.mdp @@ -428,7 +428,7 @@ GROUP BY b; - + @@ -442,7 +442,7 @@ GROUP BY b; - + @@ -456,7 +456,7 @@ GROUP BY b; - + @@ -469,7 +469,7 @@ GROUP BY b; - + @@ -484,7 +484,7 @@ GROUP BY b; - + @@ -607,7 +607,7 @@ GROUP BY b; - + @@ -618,7 +618,7 @@ GROUP BY b; - + @@ -631,7 +631,7 @@ GROUP BY b; - + @@ -646,7 +646,7 @@ GROUP BY b; - + @@ -662,7 +662,7 @@ GROUP BY b; - + @@ -675,7 +675,7 @@ GROUP BY b; - + @@ -690,7 +690,7 @@ GROUP BY b; - + @@ -774,7 +774,7 @@ GROUP BY b; - + @@ -785,7 +785,7 @@ GROUP BY b; - + @@ -798,7 +798,7 @@ GROUP BY b; - + @@ -813,7 +813,7 @@ GROUP BY b; - + @@ -829,7 +829,7 @@ GROUP BY b; - + @@ -842,7 +842,7 @@ GROUP BY b; - + @@ -857,7 +857,7 @@ GROUP BY b; - + diff --git a/src/backend/gporca/data/dxl/minidump/Non-Hashjoinable-Pred-2.mdp b/src/backend/gporca/data/dxl/minidump/Non-Hashjoinable-Pred-2.mdp index 5ecb79b68f40..090416286dc1 100644 --- a/src/backend/gporca/data/dxl/minidump/Non-Hashjoinable-Pred-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/Non-Hashjoinable-Pred-2.mdp @@ -259,7 +259,7 @@ - + @@ -279,7 +279,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/NonSingleton.mdp b/src/backend/gporca/data/dxl/minidump/NonSingleton.mdp index 0bdff2c31047..0be37a5e18cf 100644 --- a/src/backend/gporca/data/dxl/minidump/NonSingleton.mdp +++ b/src/backend/gporca/data/dxl/minidump/NonSingleton.mdp @@ -285,7 +285,7 @@ EXPLAIN SELECT a FROM snackbox JOIN (SELECT c FROM hottoast LIMIT 3) hottoast ON - + @@ -296,7 +296,7 @@ EXPLAIN SELECT a FROM snackbox JOIN (SELECT c FROM hottoast LIMIT 3) hottoast ON - + diff --git a/src/backend/gporca/data/dxl/minidump/NotExists-SuperflousOuterRefWithGbAgg.mdp b/src/backend/gporca/data/dxl/minidump/NotExists-SuperflousOuterRefWithGbAgg.mdp index c8744233c4cf..24f8eb5a8a0e 100644 --- a/src/backend/gporca/data/dxl/minidump/NotExists-SuperflousOuterRefWithGbAgg.mdp +++ b/src/backend/gporca/data/dxl/minidump/NotExists-SuperflousOuterRefWithGbAgg.mdp @@ -377,7 +377,7 @@ explain select * from A where not exists (select sum(C.i) from C where C.i = A.i - + @@ -391,7 +391,7 @@ explain select * from A where not exists (select sum(C.i) from C where C.i = A.i - + diff --git a/src/backend/gporca/data/dxl/minidump/NotInToLASJ.mdp b/src/backend/gporca/data/dxl/minidump/NotInToLASJ.mdp index 98d8fcfe62f8..d5a013aed2b4 100644 --- a/src/backend/gporca/data/dxl/minidump/NotInToLASJ.mdp +++ b/src/backend/gporca/data/dxl/minidump/NotInToLASJ.mdp @@ -333,7 +333,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/OneDistKeyMultiPredJoinCardinality.mdp b/src/backend/gporca/data/dxl/minidump/OneDistKeyMultiPredJoinCardinality.mdp index 790a62dd7c90..a2af75d1ccb6 100644 --- a/src/backend/gporca/data/dxl/minidump/OneDistKeyMultiPredJoinCardinality.mdp +++ b/src/backend/gporca/data/dxl/minidump/OneDistKeyMultiPredJoinCardinality.mdp @@ -1223,7 +1223,7 @@ - + @@ -1249,7 +1249,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/OuterJoinOnViewWithCastedColumn.mdp b/src/backend/gporca/data/dxl/minidump/OuterJoinOnViewWithCastedColumn.mdp index e747979d2b5e..387bda782035 100644 --- a/src/backend/gporca/data/dxl/minidump/OuterJoinOnViewWithCastedColumn.mdp +++ b/src/backend/gporca/data/dxl/minidump/OuterJoinOnViewWithCastedColumn.mdp @@ -348,7 +348,7 @@ - + @@ -368,7 +368,7 @@ - + @@ -394,7 +394,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartSelectorOnJoinSide.mdp b/src/backend/gporca/data/dxl/minidump/PartSelectorOnJoinSide.mdp index f026aedf08b6..ad49fbbbb653 100644 --- a/src/backend/gporca/data/dxl/minidump/PartSelectorOnJoinSide.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartSelectorOnJoinSide.mdp @@ -1618,10 +1618,10 @@ - + - + @@ -1653,7 +1653,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartSelectorOnJoinSide2.mdp b/src/backend/gporca/data/dxl/minidump/PartSelectorOnJoinSide2.mdp index 4d083e86961c..c3775aa40065 100644 --- a/src/backend/gporca/data/dxl/minidump/PartSelectorOnJoinSide2.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartSelectorOnJoinSide2.mdp @@ -1621,7 +1621,7 @@ - + @@ -1635,7 +1635,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-AggWithExistentialSubquery.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-AggWithExistentialSubquery.mdp index fea5bd0a8a61..eb6e838500c5 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-AggWithExistentialSubquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-AggWithExistentialSubquery.mdp @@ -436,7 +436,7 @@ - + @@ -454,7 +454,7 @@ - + @@ -465,7 +465,7 @@ - + @@ -495,7 +495,7 @@ - + @@ -532,7 +532,7 @@ - + @@ -571,7 +571,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-AvoidRangePred-DPE.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-AvoidRangePred-DPE.mdp index c362f2d9c709..1dc7ea529136 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-AvoidRangePred-DPE.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-AvoidRangePred-DPE.mdp @@ -828,7 +828,7 @@ FROM abuela JOIN bar ON a = c AND b BETWEEN d - 1 AND d + 4 - + @@ -839,7 +839,7 @@ FROM abuela JOIN bar ON a = c AND b BETWEEN d - 1 AND d + 4 - + @@ -860,7 +860,7 @@ FROM abuela JOIN bar ON a = c AND b BETWEEN d - 1 AND d + 4 - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-GroupBy.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-GroupBy.mdp index 36be4570d0ef..1906e5c43fb8 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-GroupBy.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-GroupBy.mdp @@ -536,7 +536,7 @@ - + @@ -559,7 +559,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-Limit.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-Limit.mdp index fc00b62c6311..1ae8e2969a7b 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-Limit.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-Limit.mdp @@ -490,7 +490,7 @@ - + @@ -525,7 +525,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-PartitionSelectorRewindability.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-PartitionSelectorRewindability.mdp index 7a7f70eb4448..703acb5e3fdf 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-PartitionSelectorRewindability.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-PartitionSelectorRewindability.mdp @@ -422,7 +422,7 @@ - + @@ -433,14 +433,14 @@ - + - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-WindowFunction.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-WindowFunction.mdp index 3d21fc998224..3a358e166466 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-WindowFunction.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-DPE-WindowFunction.mdp @@ -686,7 +686,7 @@ - + @@ -706,7 +706,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-DisablePartSelectionJoin.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-DisablePartSelectionJoin.mdp index e6f118392992..787ebad097df 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-DisablePartSelectionJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-DisablePartSelectionJoin.mdp @@ -596,7 +596,7 @@ - + @@ -616,7 +616,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-HJ3.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-HJ3.mdp index 77791e4bca32..fc54bea2ff33 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-HJ3.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-HJ3.mdp @@ -219,7 +219,7 @@ - + @@ -239,7 +239,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-HJ4.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-HJ4.mdp index 0790e1108f71..d7ab0e27b884 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-HJ4.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-HJ4.mdp @@ -273,7 +273,7 @@ - + @@ -287,7 +287,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-HJ5.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-HJ5.mdp index fd4e4b61cf8e..b6294768d849 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-HJ5.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-HJ5.mdp @@ -294,7 +294,7 @@ select * from s,t where s.b=t.a and t.b=35; - + @@ -314,7 +314,7 @@ select * from s,t where s.b=t.a and t.b=35; - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverExcept.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverExcept.mdp index 3d9b69fc2f59..191d9ac57444 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverExcept.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverExcept.mdp @@ -1284,10 +1284,10 @@ select * from (select * from p1 except select * from p2) as p, tt where p.b=tt.b - + - + @@ -1307,7 +1307,7 @@ select * from (select * from p1 except select * from p2) as p, tt where p.b=tt.b - + @@ -1333,7 +1333,7 @@ select * from (select * from p1 except select * from p2) as p, tt where p.b=tt.b - + @@ -1350,7 +1350,7 @@ select * from (select * from p1 except select * from p2) as p, tt where p.b=tt.b - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverGbAgg-2.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverGbAgg-2.mdp index ed0ba9e21a57..68d28872178b 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverGbAgg-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverGbAgg-2.mdp @@ -1237,7 +1237,7 @@ - + @@ -1260,7 +1260,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverGbAgg.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverGbAgg.mdp index 2ef4d47f8bea..1d817faa8121 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverGbAgg.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverGbAgg.mdp @@ -298,7 +298,7 @@ - + @@ -318,7 +318,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverIntersect.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverIntersect.mdp index 0f645f52d258..a77c9f00dca0 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverIntersect.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverIntersect.mdp @@ -1284,10 +1284,10 @@ select * from (select * from p1 intersect select * from p2) as p, tt where p.b=t - + - + @@ -1307,7 +1307,7 @@ select * from (select * from p1 intersect select * from p2) as p, tt where p.b=t - + @@ -1333,7 +1333,7 @@ select * from (select * from p1 intersect select * from p2) as p, tt where p.b=t - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverUnion-1.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverUnion-1.mdp index c51138edb6dc..36508f599c19 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverUnion-1.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverUnion-1.mdp @@ -1287,7 +1287,7 @@ select * from (select * from p1 union all select * from p2) as p, tt where p.b=t - + @@ -1307,7 +1307,7 @@ select * from (select * from p1 union all select * from p2) as p, tt where p.b=t - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverUnion-2.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverUnion-2.mdp index 6fb3eebdb2a3..33a7a6e03025 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverUnion-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-JoinOverUnion-2.mdp @@ -888,7 +888,7 @@ select * from (select * from tt union all select * from p2) as p, tt where p.b=t - + @@ -908,7 +908,7 @@ select * from (select * from tt union all select * from p2) as p, tt where p.b=t - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-LASJ.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-LASJ.mdp index 6a957bfd50ba..45e36dae5f43 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-LASJ.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-LASJ.mdp @@ -642,7 +642,7 @@ - + @@ -660,7 +660,7 @@ - + @@ -671,7 +671,7 @@ - + @@ -687,7 +687,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-LeftOuterHashJoin-DPE-IsNull.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-LeftOuterHashJoin-DPE-IsNull.mdp index de06e964bd33..d9189725b7b6 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-LeftOuterHashJoin-DPE-IsNull.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-LeftOuterHashJoin-DPE-IsNull.mdp @@ -269,7 +269,7 @@ select * from t2 left outer join t1 on t1.b = t2.d where t1.b is null; - + @@ -289,7 +289,7 @@ select * from t2 left outer join t1 on t1.b = t2.d where t1.b is null; - + @@ -313,7 +313,7 @@ select * from t2 left outer join t1 on t1.b = t2.d where t1.b is null; - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-MultiWayJoin.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-MultiWayJoin.mdp index 6810bf1806ba..5eb2cf50016b 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-MultiWayJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-MultiWayJoin.mdp @@ -415,7 +415,7 @@ explain select count(*) from r_p, s c, s d, s e where r_p.a = c.c and r_p.a = d. - + @@ -433,7 +433,7 @@ explain select count(*) from r_p, s c, s d, s e where r_p.a = c.c and r_p.a = d. - + @@ -444,7 +444,7 @@ explain select count(*) from r_p, s c, s d, s e where r_p.a = c.c and r_p.a = d. - + @@ -460,7 +460,7 @@ explain select count(*) from r_p, s c, s d, s e where r_p.a = c.c and r_p.a = d. - + @@ -473,7 +473,7 @@ explain select count(*) from r_p, s c, s d, s e where r_p.a = c.c and r_p.a = d. - + @@ -571,7 +571,7 @@ explain select count(*) from r_p, s c, s d, s e where r_p.a = c.c and r_p.a = d. - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-MultiWayJoinWithDPE-2.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-MultiWayJoinWithDPE-2.mdp index 780036b48b2a..339ba3ddedde 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-MultiWayJoinWithDPE-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-MultiWayJoinWithDPE-2.mdp @@ -1352,7 +1352,7 @@ - + @@ -1513,7 +1513,7 @@ - + @@ -1901,7 +1901,7 @@ - + @@ -1993,7 +1993,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-MultiWayJoinWithDPE.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-MultiWayJoinWithDPE.mdp index be0129d522a9..45c551109ac9 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-MultiWayJoinWithDPE.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-MultiWayJoinWithDPE.mdp @@ -3258,7 +3258,7 @@ - + @@ -3484,13 +3484,109 @@ - + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -3699,7 +3795,7 @@ - + @@ -3914,7 +4010,7 @@ - + @@ -4726,102 +4822,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-RangeJoinPred.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-RangeJoinPred.mdp index 6230a79b3db4..762a0e2967ab 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-RangeJoinPred.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-RangeJoinPred.mdp @@ -5170,7 +5170,7 @@ where d.msisdn=f.subscriberaddress and f.sessioncreationtimestamp >= d.start_dtm - + @@ -5241,7 +5241,7 @@ where d.msisdn=f.subscriberaddress and f.sessioncreationtimestamp >= d.start_dtm - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-RightOuterHashJoin-DPE-IsNull.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-RightOuterHashJoin-DPE-IsNull.mdp index 1d2a5cc5c746..67c2d97984a7 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-RightOuterHashJoin-DPE-IsNull.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-RightOuterHashJoin-DPE-IsNull.mdp @@ -306,7 +306,7 @@ - + @@ -330,7 +330,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-SQAny.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-SQAny.mdp index 139efeadd84e..c6f5d1a415b0 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-SQAny.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-SQAny.mdp @@ -359,7 +359,7 @@ - + @@ -373,7 +373,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-SQExists.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-SQExists.mdp index cda1040b510b..6f0f5934888c 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-SQExists.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-SQExists.mdp @@ -312,7 +312,7 @@ - + @@ -326,7 +326,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-SQNotExists.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-SQNotExists.mdp index 01cea25438b0..5f397c7c0269 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-SQNotExists.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-SQNotExists.mdp @@ -306,7 +306,7 @@ - + @@ -320,7 +320,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-SQScalar.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-SQScalar.mdp index 84a51c16443e..fb221318e064 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-SQScalar.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-SQScalar.mdp @@ -319,10 +319,10 @@ - + - + @@ -336,7 +336,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PartTbl-WindowFunction.mdp b/src/backend/gporca/data/dxl/minidump/PartTbl-WindowFunction.mdp index 5fc1411387df..75df46c91448 100644 --- a/src/backend/gporca/data/dxl/minidump/PartTbl-WindowFunction.mdp +++ b/src/backend/gporca/data/dxl/minidump/PartTbl-WindowFunction.mdp @@ -686,7 +686,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-11.mdp b/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-11.mdp index 3c44d6e4a231..7d521933ed13 100644 --- a/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-11.mdp +++ b/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-11.mdp @@ -323,7 +323,7 @@ - + @@ -337,7 +337,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-12.mdp b/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-12.mdp index 627f4dfa7f90..32f8a7466e73 100644 --- a/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-12.mdp +++ b/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-12.mdp @@ -297,7 +297,7 @@ - + @@ -311,7 +311,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-13.mdp b/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-13.mdp index 1b37997ebfd8..d6193d48b723 100644 --- a/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-13.mdp +++ b/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-13.mdp @@ -10,19 +10,18 @@ CREATE TABLE t2 (id smallint); EXPLAIN (costs off) SELECT * FROM t1 a JOIN t2 fa ON a.id = fa.id WHERE a.id = 1; - QUERY PLAN - ------------------------------------------------------------------ + QUERY PLAN + ---------------------------------------------- Gather Motion 3:1 (slice1; segments: 3) -> Hash Join - Hash Cond: (t1.id = (t2.id)::integer) - -> Seq Scan on t1 + Hash Cond: (a.id = (fa.id)::integer) + -> Seq Scan on t1 a Filter: (id = 1) -> Hash - -> Redistribute Motion 3:3 (slice2; segments: 3) - Hash Key: (t2.id)::integer - -> Seq Scan on t2 - Filter: (id = 1) + -> Seq Scan on t2 fa + Filter: (id = 1) Optimizer: Pivotal Optimizer (GPORCA) + (9 rows) ]]> @@ -331,10 +330,10 @@ - + - + @@ -348,7 +347,7 @@ - + @@ -396,53 +395,34 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-14.mdp b/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-14.mdp index 96529708fe88..6932b5eaaa7b 100644 --- a/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-14.mdp +++ b/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-14.mdp @@ -8,19 +8,18 @@ CREATE TABLE t2 (id smallint); EXPLAIN (costs off) SELECT * FROM t1 a JOIN t2 fa ON a.id = fa.id WHERE a.id > 1; - QUERY PLAN - ------------------------------------------------------------------ + QUERY PLAN + ---------------------------------------------- Gather Motion 3:1 (slice1; segments: 3) -> Hash Join - Hash Cond: (t1.id = (t2.id)::integer) - -> Seq Scan on t1 + Hash Cond: (a.id = (fa.id)::integer) + -> Seq Scan on t1 a Filter: (id > 1) -> Hash - -> Redistribute Motion 3:3 (slice2; segments: 3) - Hash Key: (t2.id)::integer - -> Seq Scan on t2 - Filter: (id > 1) + -> Seq Scan on t2 fa + Filter: (id > 1) Optimizer: Pivotal Optimizer (GPORCA) + (9 rows) ]]> @@ -378,10 +377,10 @@ - + - + @@ -395,7 +394,7 @@ - + @@ -443,53 +442,34 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-15.mdp b/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-15.mdp index 7f06a97a9184..37ffaf8f8582 100644 --- a/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-15.mdp +++ b/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-15.mdp @@ -8,19 +8,18 @@ CREATE TABLE t2 (id smallint); EXPLAIN (costs off) SELECT * FROM t1 a JOIN t2 fa ON a.id = fa.id WHERE a.id <= 1; - QUERY PLAN - ------------------------------------------------------------------ + QUERY PLAN + ---------------------------------------------- Gather Motion 3:1 (slice1; segments: 3) -> Hash Join - Hash Cond: (t1.id = (t2.id)::integer) - -> Seq Scan on t1 + Hash Cond: (a.id = (fa.id)::integer) + -> Seq Scan on t1 a Filter: (id <= 1) -> Hash - -> Redistribute Motion 3:3 (slice2; segments: 3) - Hash Key: (t2.id)::integer - -> Seq Scan on t2 - Filter: (id <= 1) + -> Seq Scan on t2 fa + Filter: (id <= 1) Optimizer: Pivotal Optimizer (GPORCA) + (9 rows) ]]> @@ -378,10 +377,10 @@ - + - + @@ -395,7 +394,7 @@ - + @@ -443,53 +442,34 @@ - + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-2.mdp b/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-2.mdp index 08ae782e28e3..0ceb241f222c 100644 --- a/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/PushConstantSelectPredicateThruJoin-2.mdp @@ -418,7 +418,7 @@ - + @@ -434,14 +434,14 @@ - + - + diff --git a/src/backend/gporca/data/dxl/minidump/PushFilterToSemiJoinLeftChild.mdp b/src/backend/gporca/data/dxl/minidump/PushFilterToSemiJoinLeftChild.mdp index 210e626f630c..d4343715a1d5 100644 --- a/src/backend/gporca/data/dxl/minidump/PushFilterToSemiJoinLeftChild.mdp +++ b/src/backend/gporca/data/dxl/minidump/PushFilterToSemiJoinLeftChild.mdp @@ -311,7 +311,7 @@ - + @@ -322,7 +322,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PushGbBelowJoin-NegativeCase.mdp b/src/backend/gporca/data/dxl/minidump/PushGbBelowJoin-NegativeCase.mdp index 98c079805bfe..b75f3662435d 100644 --- a/src/backend/gporca/data/dxl/minidump/PushGbBelowJoin-NegativeCase.mdp +++ b/src/backend/gporca/data/dxl/minidump/PushGbBelowJoin-NegativeCase.mdp @@ -409,7 +409,7 @@ - + @@ -420,7 +420,7 @@ - + @@ -437,7 +437,7 @@ - + @@ -456,7 +456,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/PushSelectDownUnionAllOfCTG.mdp b/src/backend/gporca/data/dxl/minidump/PushSelectDownUnionAllOfCTG.mdp index 86e78954ee23..5ebc48e7d0b1 100644 --- a/src/backend/gporca/data/dxl/minidump/PushSelectDownUnionAllOfCTG.mdp +++ b/src/backend/gporca/data/dxl/minidump/PushSelectDownUnionAllOfCTG.mdp @@ -217,7 +217,7 @@ - + @@ -235,7 +235,7 @@ - + @@ -245,7 +245,7 @@ - + @@ -400,7 +400,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Remove-Distinct-From-Subquery.mdp b/src/backend/gporca/data/dxl/minidump/Remove-Distinct-From-Subquery.mdp index 2d4d8603d2b0..6c167a2fea41 100644 --- a/src/backend/gporca/data/dxl/minidump/Remove-Distinct-From-Subquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/Remove-Distinct-From-Subquery.mdp @@ -524,7 +524,7 @@ select * from bar where c not in (select distinct a from foo); - + @@ -538,7 +538,7 @@ select * from bar where c not in (select distinct a from foo); - + @@ -649,7 +649,7 @@ select * from bar where c not in (select distinct a from foo); - + @@ -828,7 +828,7 @@ select * from bar where c not in (select distinct a from foo); - + @@ -842,7 +842,7 @@ select * from bar where c not in (select distinct a from foo); - + diff --git a/src/backend/gporca/data/dxl/minidump/RemoveImpliedPredOnBCCPredicates.mdp b/src/backend/gporca/data/dxl/minidump/RemoveImpliedPredOnBCCPredicates.mdp index 4451ac16e8b2..7a9002c18df0 100644 --- a/src/backend/gporca/data/dxl/minidump/RemoveImpliedPredOnBCCPredicates.mdp +++ b/src/backend/gporca/data/dxl/minidump/RemoveImpliedPredOnBCCPredicates.mdp @@ -278,7 +278,7 @@ - + @@ -304,7 +304,7 @@ - + @@ -368,7 +368,7 @@ - + @@ -404,7 +404,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedHashJoinReplicated.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedHashJoinReplicated.mdp index 121d74dd666d..e56d0d69112a 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedHashJoinReplicated.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedHashJoinReplicated.mdp @@ -1046,7 +1046,7 @@ - + @@ -1066,7 +1066,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedJoinHashDistributedTable.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedJoinHashDistributedTable.mdp index a609fadbb521..16926488e209 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedJoinHashDistributedTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedJoinHashDistributedTable.mdp @@ -1440,7 +1440,7 @@ - + @@ -1460,7 +1460,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedJoinPartitionedTable.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedJoinPartitionedTable.mdp index dbc4893bec8e..539f55d74f53 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedJoinPartitionedTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedJoinPartitionedTable.mdp @@ -652,7 +652,7 @@ - + @@ -672,7 +672,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedJoinRandomDistributedTable.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedJoinRandomDistributedTable.mdp index 48f7d8883ada..dffb62bcae8b 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedJoinRandomDistributedTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedJoinRandomDistributedTable.mdp @@ -1042,7 +1042,7 @@ - + @@ -1062,7 +1062,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedLOJHashDistributedTable.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedLOJHashDistributedTable.mdp index 6448db1a7257..8e5f26a585f1 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedLOJHashDistributedTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedLOJHashDistributedTable.mdp @@ -1440,7 +1440,7 @@ - + @@ -1460,7 +1460,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedLOJRandomDistributedTable.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedLOJRandomDistributedTable.mdp index 5e35b86a516b..cd7e26e78e84 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedLOJRandomDistributedTable.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedLOJRandomDistributedTable.mdp @@ -1042,7 +1042,7 @@ - + @@ -1062,7 +1062,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedLOJReplicated.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedLOJReplicated.mdp index e38e97961353..e9e5ae1ee503 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedLOJReplicated.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedLOJReplicated.mdp @@ -1046,7 +1046,7 @@ - + @@ -1066,7 +1066,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedTableCTE.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedTableCTE.mdp index 11f568fac780..ed134c981484 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedTableCTE.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedTableCTE.mdp @@ -1446,7 +1446,7 @@ - + @@ -1466,7 +1466,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/ReplicatedTableInClause.mdp b/src/backend/gporca/data/dxl/minidump/ReplicatedTableInClause.mdp index 05d82731ca16..5f724ae1ab3f 100644 --- a/src/backend/gporca/data/dxl/minidump/ReplicatedTableInClause.mdp +++ b/src/backend/gporca/data/dxl/minidump/ReplicatedTableInClause.mdp @@ -1108,7 +1108,7 @@ - + @@ -1122,7 +1122,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/RightJoinBothReplicated.mdp b/src/backend/gporca/data/dxl/minidump/RightJoinBothReplicated.mdp index d38955682580..f2b8a47c450e 100644 --- a/src/backend/gporca/data/dxl/minidump/RightJoinBothReplicated.mdp +++ b/src/backend/gporca/data/dxl/minidump/RightJoinBothReplicated.mdp @@ -715,7 +715,7 @@ - + @@ -735,7 +735,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/RightJoinDPS.mdp b/src/backend/gporca/data/dxl/minidump/RightJoinDPS.mdp index e411f82d9092..535db0a37767 100644 --- a/src/backend/gporca/data/dxl/minidump/RightJoinDPS.mdp +++ b/src/backend/gporca/data/dxl/minidump/RightJoinDPS.mdp @@ -357,7 +357,7 @@ - + @@ -377,7 +377,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/RightJoinHashed.mdp b/src/backend/gporca/data/dxl/minidump/RightJoinHashed.mdp index c59ebdf7b3d9..95f00be781d2 100644 --- a/src/backend/gporca/data/dxl/minidump/RightJoinHashed.mdp +++ b/src/backend/gporca/data/dxl/minidump/RightJoinHashed.mdp @@ -719,7 +719,7 @@ - + @@ -739,7 +739,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/RightJoinNoDPSNonDistKey.mdp b/src/backend/gporca/data/dxl/minidump/RightJoinNoDPSNonDistKey.mdp index 0c966d659373..17ead5e060f8 100644 --- a/src/backend/gporca/data/dxl/minidump/RightJoinNoDPSNonDistKey.mdp +++ b/src/backend/gporca/data/dxl/minidump/RightJoinNoDPSNonDistKey.mdp @@ -762,7 +762,7 @@ - + @@ -782,7 +782,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/RightJoinRedistribute.mdp b/src/backend/gporca/data/dxl/minidump/RightJoinRedistribute.mdp index 74f9dd565031..1d650259a91a 100644 --- a/src/backend/gporca/data/dxl/minidump/RightJoinRedistribute.mdp +++ b/src/backend/gporca/data/dxl/minidump/RightJoinRedistribute.mdp @@ -763,7 +763,7 @@ - + @@ -783,7 +783,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/RightJoinReplicated.mdp b/src/backend/gporca/data/dxl/minidump/RightJoinReplicated.mdp index 69b37f154a0a..964aff6d630a 100644 --- a/src/backend/gporca/data/dxl/minidump/RightJoinReplicated.mdp +++ b/src/backend/gporca/data/dxl/minidump/RightJoinReplicated.mdp @@ -1076,7 +1076,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/RightJoinTVF.mdp b/src/backend/gporca/data/dxl/minidump/RightJoinTVF.mdp index c30375a2e185..bfb7af1717f2 100644 --- a/src/backend/gporca/data/dxl/minidump/RightJoinTVF.mdp +++ b/src/backend/gporca/data/dxl/minidump/RightJoinTVF.mdp @@ -320,7 +320,7 @@ - + @@ -331,7 +331,7 @@ - + @@ -344,7 +344,7 @@ - + @@ -359,7 +359,7 @@ - + @@ -375,7 +375,7 @@ - + @@ -388,7 +388,7 @@ - + @@ -399,7 +399,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Select-Over-CTEAnchor.mdp b/src/backend/gporca/data/dxl/minidump/Select-Over-CTEAnchor.mdp index 46e73e658944..625ae11670dd 100644 --- a/src/backend/gporca/data/dxl/minidump/Select-Over-CTEAnchor.mdp +++ b/src/backend/gporca/data/dxl/minidump/Select-Over-CTEAnchor.mdp @@ -463,7 +463,7 @@ - + @@ -489,7 +489,7 @@ - + @@ -520,7 +520,7 @@ - + @@ -540,7 +540,7 @@ - + @@ -558,7 +558,7 @@ - + @@ -576,7 +576,7 @@ - + @@ -663,7 +663,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Select-Proj-OuterJoin.mdp b/src/backend/gporca/data/dxl/minidump/Select-Proj-OuterJoin.mdp index bd679820b58e..8c1b163b2004 100644 --- a/src/backend/gporca/data/dxl/minidump/Select-Proj-OuterJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/Select-Proj-OuterJoin.mdp @@ -892,7 +892,7 @@ - + @@ -905,7 +905,7 @@ - + @@ -920,7 +920,7 @@ - + @@ -937,7 +937,7 @@ - + @@ -951,7 +951,7 @@ - + @@ -999,7 +999,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/SemiJoin2InnerJoin.mdp b/src/backend/gporca/data/dxl/minidump/SemiJoin2InnerJoin.mdp index 7c84a45fcaf3..349689a49e0d 100644 --- a/src/backend/gporca/data/dxl/minidump/SemiJoin2InnerJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/SemiJoin2InnerJoin.mdp @@ -531,7 +531,7 @@ - + @@ -542,7 +542,7 @@ - + @@ -553,7 +553,7 @@ - + @@ -574,7 +574,7 @@ - + @@ -596,7 +596,7 @@ - + @@ -621,7 +621,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/SixWayDPv2.mdp b/src/backend/gporca/data/dxl/minidump/SixWayDPv2.mdp index aa39255a2117..32f24260e28f 100644 --- a/src/backend/gporca/data/dxl/minidump/SixWayDPv2.mdp +++ b/src/backend/gporca/data/dxl/minidump/SixWayDPv2.mdp @@ -495,7 +495,7 @@ - + @@ -539,7 +539,7 @@ - + @@ -589,7 +589,7 @@ - + @@ -633,7 +633,7 @@ - + @@ -670,7 +670,7 @@ - + @@ -708,7 +708,7 @@ - + @@ -739,7 +739,7 @@ - + @@ -771,7 +771,7 @@ - + @@ -796,7 +796,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/SpoolShouldInvalidateUnresolvedDynamicScans.mdp b/src/backend/gporca/data/dxl/minidump/SpoolShouldInvalidateUnresolvedDynamicScans.mdp index 1857ddef1ea9..e5b65ca47d34 100644 --- a/src/backend/gporca/data/dxl/minidump/SpoolShouldInvalidateUnresolvedDynamicScans.mdp +++ b/src/backend/gporca/data/dxl/minidump/SpoolShouldInvalidateUnresolvedDynamicScans.mdp @@ -608,7 +608,7 @@ And instead have a plan like - + @@ -634,7 +634,7 @@ And instead have a plan like - + @@ -707,7 +707,7 @@ And instead have a plan like - + @@ -726,7 +726,7 @@ And instead have a plan like - + diff --git a/src/backend/gporca/data/dxl/minidump/SqlFuncNullReject.mdp b/src/backend/gporca/data/dxl/minidump/SqlFuncNullReject.mdp index 2bd402640de5..5f9d2a174c87 100644 --- a/src/backend/gporca/data/dxl/minidump/SqlFuncNullReject.mdp +++ b/src/backend/gporca/data/dxl/minidump/SqlFuncNullReject.mdp @@ -287,14 +287,14 @@ yolo(c) = 16 - + - + diff --git a/src/backend/gporca/data/dxl/minidump/SqlFuncPredFactorize.mdp b/src/backend/gporca/data/dxl/minidump/SqlFuncPredFactorize.mdp index d3d9c870237c..b24a3be6b9e9 100644 --- a/src/backend/gporca/data/dxl/minidump/SqlFuncPredFactorize.mdp +++ b/src/backend/gporca/data/dxl/minidump/SqlFuncPredFactorize.mdp @@ -322,14 +322,14 @@ WHERE a = c AND - + - + diff --git a/src/backend/gporca/data/dxl/minidump/Stat-Derivation-Leaf-Pattern.mdp b/src/backend/gporca/data/dxl/minidump/Stat-Derivation-Leaf-Pattern.mdp index 422c085befc2..012cec4c418b 100644 --- a/src/backend/gporca/data/dxl/minidump/Stat-Derivation-Leaf-Pattern.mdp +++ b/src/backend/gporca/data/dxl/minidump/Stat-Derivation-Leaf-Pattern.mdp @@ -830,7 +830,7 @@ AND - + diff --git a/src/backend/gporca/data/dxl/minidump/Subq-JoinWithOuterRef.mdp b/src/backend/gporca/data/dxl/minidump/Subq-JoinWithOuterRef.mdp index 2fadb34797dc..4d0b495edefe 100644 --- a/src/backend/gporca/data/dxl/minidump/Subq-JoinWithOuterRef.mdp +++ b/src/backend/gporca/data/dxl/minidump/Subq-JoinWithOuterRef.mdp @@ -420,7 +420,7 @@ - + @@ -431,7 +431,7 @@ - + @@ -442,7 +442,7 @@ - + @@ -462,7 +462,7 @@ - + @@ -478,7 +478,7 @@ - + @@ -488,7 +488,7 @@ - + @@ -499,7 +499,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Subq-On-OuterRef.mdp b/src/backend/gporca/data/dxl/minidump/Subq-On-OuterRef.mdp index 73b8dce74337..f32125b252aa 100644 --- a/src/backend/gporca/data/dxl/minidump/Subq-On-OuterRef.mdp +++ b/src/backend/gporca/data/dxl/minidump/Subq-On-OuterRef.mdp @@ -265,7 +265,7 @@ - + @@ -279,7 +279,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Subq-With-OuterRefCol.mdp b/src/backend/gporca/data/dxl/minidump/Subq-With-OuterRefCol.mdp index c4439f83c4a8..5513a712a259 100644 --- a/src/backend/gporca/data/dxl/minidump/Subq-With-OuterRefCol.mdp +++ b/src/backend/gporca/data/dxl/minidump/Subq-With-OuterRefCol.mdp @@ -535,7 +535,7 @@ pivotal=# explain select a, c from r, s where a in (select c from r) order by a, - + @@ -547,7 +547,7 @@ pivotal=# explain select a, c from r, s where a in (select c from r) order by a, - + @@ -564,7 +564,7 @@ pivotal=# explain select a, c from r, s where a in (select c from r) order by a, - + @@ -576,7 +576,7 @@ pivotal=# explain select a, c from r, s where a in (select c from r) order by a, - + @@ -595,7 +595,7 @@ pivotal=# explain select a, c from r, s where a in (select c from r) order by a, - + diff --git a/src/backend/gporca/data/dxl/minidump/Subq2CorrSQInLOJOn.mdp b/src/backend/gporca/data/dxl/minidump/Subq2CorrSQInLOJOn.mdp index 6b1a44d50399..4fcaefa3ba6e 100644 --- a/src/backend/gporca/data/dxl/minidump/Subq2CorrSQInLOJOn.mdp +++ b/src/backend/gporca/data/dxl/minidump/Subq2CorrSQInLOJOn.mdp @@ -2433,7 +2433,7 @@ - + @@ -2447,7 +2447,7 @@ - + @@ -2470,7 +2470,7 @@ - + @@ -2489,7 +2489,7 @@ - + @@ -2502,7 +2502,7 @@ - + @@ -2516,7 +2516,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Subq2NotInWhereLOJ.mdp b/src/backend/gporca/data/dxl/minidump/Subq2NotInWhereLOJ.mdp index 49f4e8c49f56..b06040459638 100644 --- a/src/backend/gporca/data/dxl/minidump/Subq2NotInWhereLOJ.mdp +++ b/src/backend/gporca/data/dxl/minidump/Subq2NotInWhereLOJ.mdp @@ -739,7 +739,7 @@ - + @@ -756,7 +756,7 @@ - + @@ -777,7 +777,7 @@ - + @@ -800,7 +800,7 @@ - + @@ -828,7 +828,7 @@ - + @@ -849,7 +849,7 @@ - + @@ -872,7 +872,7 @@ - + @@ -892,7 +892,7 @@ - + @@ -909,7 +909,7 @@ - + @@ -936,7 +936,7 @@ - + @@ -984,7 +984,7 @@ - + @@ -1011,7 +1011,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/SubqEnforceSubplan.mdp b/src/backend/gporca/data/dxl/minidump/SubqEnforceSubplan.mdp index af568b0cbc4e..933815a1763a 100644 --- a/src/backend/gporca/data/dxl/minidump/SubqEnforceSubplan.mdp +++ b/src/backend/gporca/data/dxl/minidump/SubqEnforceSubplan.mdp @@ -276,7 +276,7 @@ explain select * from foo,bar where b = (select min(b) from bar where a = b); - + diff --git a/src/backend/gporca/data/dxl/minidump/SubqExists-With-External-Corrs.mdp b/src/backend/gporca/data/dxl/minidump/SubqExists-With-External-Corrs.mdp index c102ea887f9d..32c1eedbc1e3 100644 --- a/src/backend/gporca/data/dxl/minidump/SubqExists-With-External-Corrs.mdp +++ b/src/backend/gporca/data/dxl/minidump/SubqExists-With-External-Corrs.mdp @@ -459,7 +459,7 @@ - + @@ -521,7 +521,7 @@ - + @@ -534,7 +534,7 @@ - + @@ -549,7 +549,7 @@ - + @@ -613,7 +613,7 @@ - + @@ -624,7 +624,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/SubqExists-Without-External-Corrs.mdp b/src/backend/gporca/data/dxl/minidump/SubqExists-Without-External-Corrs.mdp index 4b3514f9ba7b..bffbb71ccf27 100644 --- a/src/backend/gporca/data/dxl/minidump/SubqExists-Without-External-Corrs.mdp +++ b/src/backend/gporca/data/dxl/minidump/SubqExists-Without-External-Corrs.mdp @@ -434,7 +434,7 @@ - + @@ -448,7 +448,7 @@ - + @@ -491,32 +491,32 @@ - + - + - + - + - + @@ -553,7 +553,7 @@ - + @@ -564,7 +564,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/SubqInIndexPred.mdp b/src/backend/gporca/data/dxl/minidump/SubqInIndexPred.mdp index e1121b3b0d47..95760bbe246f 100644 --- a/src/backend/gporca/data/dxl/minidump/SubqInIndexPred.mdp +++ b/src/backend/gporca/data/dxl/minidump/SubqInIndexPred.mdp @@ -523,7 +523,7 @@ ON a = c - + @@ -534,7 +534,7 @@ ON a = c - + @@ -548,7 +548,7 @@ ON a = c - + @@ -561,7 +561,7 @@ ON a = c - + @@ -574,7 +574,7 @@ ON a = c - + diff --git a/src/backend/gporca/data/dxl/minidump/Switch-With-Subquery.mdp b/src/backend/gporca/data/dxl/minidump/Switch-With-Subquery.mdp index 3bf60d6d2251..ddd1e0447020 100644 --- a/src/backend/gporca/data/dxl/minidump/Switch-With-Subquery.mdp +++ b/src/backend/gporca/data/dxl/minidump/Switch-With-Subquery.mdp @@ -409,7 +409,7 @@ - + @@ -422,7 +422,7 @@ - + @@ -437,7 +437,7 @@ - + @@ -458,7 +458,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/TPCDS-39-InnerJoin-JoinEstimate.mdp b/src/backend/gporca/data/dxl/minidump/TPCDS-39-InnerJoin-JoinEstimate.mdp index 474b732b0ccb..5e8a7a137050 100644 --- a/src/backend/gporca/data/dxl/minidump/TPCDS-39-InnerJoin-JoinEstimate.mdp +++ b/src/backend/gporca/data/dxl/minidump/TPCDS-39-InnerJoin-JoinEstimate.mdp @@ -2651,7 +2651,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/TPCH-Partitioned-256GB.mdp b/src/backend/gporca/data/dxl/minidump/TPCH-Partitioned-256GB.mdp index edaf7061cd5a..0679fff9ff46 100644 --- a/src/backend/gporca/data/dxl/minidump/TPCH-Partitioned-256GB.mdp +++ b/src/backend/gporca/data/dxl/minidump/TPCH-Partitioned-256GB.mdp @@ -3673,10 +3673,10 @@ - + - + @@ -3795,7 +3795,7 @@ - + @@ -3920,7 +3920,7 @@ - + @@ -4023,7 +4023,7 @@ - + @@ -4127,7 +4127,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/TPCH-Q5.mdp b/src/backend/gporca/data/dxl/minidump/TPCH-Q5.mdp index f1db9db09c80..81419e9f8e9e 100644 --- a/src/backend/gporca/data/dxl/minidump/TPCH-Q5.mdp +++ b/src/backend/gporca/data/dxl/minidump/TPCH-Q5.mdp @@ -6505,7 +6505,7 @@ - + @@ -6521,7 +6521,7 @@ - + @@ -6539,7 +6539,7 @@ - + @@ -6562,7 +6562,7 @@ - + @@ -6581,7 +6581,7 @@ - + @@ -6595,7 +6595,7 @@ - + @@ -6604,13 +6604,13 @@ - - - - - + + + + + + - @@ -6624,7 +6624,7 @@ - + @@ -6641,21 +6641,24 @@ - - + + - + - + - - + + + + + @@ -6663,9 +6666,6 @@ - - - @@ -6674,8 +6674,8 @@ - - + + @@ -6713,16 +6713,16 @@ - + - + - - + + - - + + @@ -6730,16 +6730,21 @@ + + + + + - + - - + + - - + + @@ -6749,54 +6754,122 @@ - - + + - + - + - - + + - - + + - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - - + + + + + - - + + + + + + + + - + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -6807,16 +6880,10 @@ - - - - - - - - + + - + @@ -6825,199 +6892,135 @@ - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - + + - + - - + + + + + + + + - - - - - - - + + - - - - - - - - - + + + + + + + + + + - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + - + - + - - + + - - + + - - - - - - + - + - - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedTablesCTE.mdp b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedTablesCTE.mdp index e0f7c2267eda..804792b594db 100644 --- a/src/backend/gporca/data/dxl/minidump/TaintedReplicatedTablesCTE.mdp +++ b/src/backend/gporca/data/dxl/minidump/TaintedReplicatedTablesCTE.mdp @@ -417,7 +417,7 @@ - + @@ -522,7 +522,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/TimeStamp-Date-HashJoin.mdp b/src/backend/gporca/data/dxl/minidump/TimeStamp-Date-HashJoin.mdp index 299cd050713c..64b58ff6d337 100644 --- a/src/backend/gporca/data/dxl/minidump/TimeStamp-Date-HashJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/TimeStamp-Date-HashJoin.mdp @@ -294,7 +294,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Tpcds-NonPart-Q70a.mdp b/src/backend/gporca/data/dxl/minidump/Tpcds-NonPart-Q70a.mdp index 11e441c38170..5b996a03a46c 100644 --- a/src/backend/gporca/data/dxl/minidump/Tpcds-NonPart-Q70a.mdp +++ b/src/backend/gporca/data/dxl/minidump/Tpcds-NonPart-Q70a.mdp @@ -14890,7 +14890,7 @@ with results as - + @@ -14913,7 +14913,7 @@ with results as - + @@ -14943,7 +14943,7 @@ with results as - + @@ -14975,7 +14975,7 @@ with results as - + @@ -14999,7 +14999,7 @@ with results as - + @@ -15020,7 +15020,7 @@ with results as - + @@ -15043,7 +15043,7 @@ with results as - + @@ -15070,7 +15070,7 @@ with results as - + @@ -15092,7 +15092,7 @@ with results as - + @@ -15117,7 +15117,7 @@ with results as - + @@ -15134,7 +15134,7 @@ with results as - + @@ -15161,7 +15161,7 @@ with results as - + @@ -15184,7 +15184,7 @@ with results as - + @@ -15279,7 +15279,7 @@ with results as - + @@ -15296,7 +15296,7 @@ with results as - + @@ -15350,7 +15350,7 @@ with results as - + @@ -15361,7 +15361,7 @@ with results as - + @@ -15377,7 +15377,7 @@ with results as - + @@ -15393,7 +15393,7 @@ with results as - + @@ -15412,7 +15412,7 @@ with results as - + @@ -15435,7 +15435,7 @@ with results as - + @@ -15453,7 +15453,7 @@ with results as - + @@ -15472,7 +15472,7 @@ with results as - + @@ -15486,7 +15486,7 @@ with results as - + @@ -15509,7 +15509,7 @@ with results as - + @@ -15529,7 +15529,7 @@ with results as - + diff --git a/src/backend/gporca/data/dxl/minidump/TranslateFilterDisjunctQuals.mdp b/src/backend/gporca/data/dxl/minidump/TranslateFilterDisjunctQuals.mdp index 0e7897bc0f07..d58d5e3a1bda 100644 --- a/src/backend/gporca/data/dxl/minidump/TranslateFilterDisjunctQuals.mdp +++ b/src/backend/gporca/data/dxl/minidump/TranslateFilterDisjunctQuals.mdp @@ -387,7 +387,7 @@ - + @@ -398,7 +398,7 @@ - + @@ -500,7 +500,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/TranslateFilterWithCTEAndTableScanIntoFilterAndOneTimeFilter.mdp b/src/backend/gporca/data/dxl/minidump/TranslateFilterWithCTEAndTableScanIntoFilterAndOneTimeFilter.mdp index 1540265f8878..dcdeec33935d 100644 --- a/src/backend/gporca/data/dxl/minidump/TranslateFilterWithCTEAndTableScanIntoFilterAndOneTimeFilter.mdp +++ b/src/backend/gporca/data/dxl/minidump/TranslateFilterWithCTEAndTableScanIntoFilterAndOneTimeFilter.mdp @@ -615,7 +615,7 @@ - + @@ -632,7 +632,7 @@ - + @@ -647,7 +647,7 @@ - + @@ -659,7 +659,7 @@ - + @@ -731,7 +731,7 @@ - + @@ -973,7 +973,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/TranslateOneTimeFilterConjunctQuals.mdp b/src/backend/gporca/data/dxl/minidump/TranslateOneTimeFilterConjunctQuals.mdp index 7889c3640fae..2c6163cd74f0 100644 --- a/src/backend/gporca/data/dxl/minidump/TranslateOneTimeFilterConjunctQuals.mdp +++ b/src/backend/gporca/data/dxl/minidump/TranslateOneTimeFilterConjunctQuals.mdp @@ -390,7 +390,7 @@ - + @@ -401,7 +401,7 @@ - + @@ -504,7 +504,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/Union-NOT-Plus-OR-Constraint.mdp b/src/backend/gporca/data/dxl/minidump/Union-NOT-Plus-OR-Constraint.mdp index 24817bc032ea..3ff44bfb751f 100644 --- a/src/backend/gporca/data/dxl/minidump/Union-NOT-Plus-OR-Constraint.mdp +++ b/src/backend/gporca/data/dxl/minidump/Union-NOT-Plus-OR-Constraint.mdp @@ -291,7 +291,7 @@ explain SELECT a.f3 FROM tb a JOIN tb b ON a.f1 = b.f1 AND NOT ( a.f2 = 0 OR a.f - + @@ -302,7 +302,7 @@ explain SELECT a.f3 FROM tb a JOIN tb b ON a.f1 = b.f1 AND NOT ( a.f2 = 0 OR a.f - + @@ -315,7 +315,7 @@ explain SELECT a.f3 FROM tb a JOIN tb b ON a.f1 = b.f1 AND NOT ( a.f2 = 0 OR a.f - + @@ -330,7 +330,7 @@ explain SELECT a.f3 FROM tb a JOIN tb b ON a.f1 = b.f1 AND NOT ( a.f2 = 0 OR a.f - + @@ -346,7 +346,7 @@ explain SELECT a.f3 FROM tb a JOIN tb b ON a.f1 = b.f1 AND NOT ( a.f2 = 0 OR a.f - + @@ -359,7 +359,7 @@ explain SELECT a.f3 FROM tb a JOIN tb b ON a.f1 = b.f1 AND NOT ( a.f2 = 0 OR a.f - + @@ -374,7 +374,7 @@ explain SELECT a.f3 FROM tb a JOIN tb b ON a.f1 = b.f1 AND NOT ( a.f2 = 0 OR a.f - + @@ -384,7 +384,7 @@ explain SELECT a.f3 FROM tb a JOIN tb b ON a.f1 = b.f1 AND NOT ( a.f2 = 0 OR a.f - + @@ -395,10 +395,50 @@ explain SELECT a.f3 FROM tb a JOIN tb b ON a.f1 = b.f1 AND NOT ( a.f2 = 0 OR a.f - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -462,46 +502,6 @@ explain SELECT a.f3 FROM tb a JOIN tb b ON a.f1 = b.f1 AND NOT ( a.f2 = 0 OR a.f - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/backend/gporca/data/dxl/minidump/Union-On-HJNs.mdp b/src/backend/gporca/data/dxl/minidump/Union-On-HJNs.mdp index 3feb59b90d8b..24241b780632 100644 --- a/src/backend/gporca/data/dxl/minidump/Union-On-HJNs.mdp +++ b/src/backend/gporca/data/dxl/minidump/Union-On-HJNs.mdp @@ -509,7 +509,7 @@ - + @@ -529,7 +529,7 @@ - + @@ -548,7 +548,7 @@ - + @@ -566,7 +566,7 @@ - + @@ -677,7 +677,7 @@ - + @@ -796,7 +796,7 @@ - + @@ -891,7 +891,7 @@ - + @@ -1382,7 +1382,7 @@ - + @@ -1936,7 +1936,7 @@ - + @@ -1956,7 +1956,7 @@ - + @@ -1971,7 +1971,7 @@ - + @@ -2079,7 +2079,7 @@ - + @@ -2195,7 +2195,7 @@ - + @@ -2287,7 +2287,7 @@ - + @@ -2766,7 +2766,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UnionAll.mdp b/src/backend/gporca/data/dxl/minidump/UnionAll.mdp index d26397d44094..cd4e29002c88 100644 --- a/src/backend/gporca/data/dxl/minidump/UnionAll.mdp +++ b/src/backend/gporca/data/dxl/minidump/UnionAll.mdp @@ -8893,7 +8893,7 @@ - + @@ -8907,7 +8907,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UnionAllWithTruncatedOutput.mdp b/src/backend/gporca/data/dxl/minidump/UnionAllWithTruncatedOutput.mdp index fd03037061ab..33a2b0c8f11c 100644 --- a/src/backend/gporca/data/dxl/minidump/UnionAllWithTruncatedOutput.mdp +++ b/src/backend/gporca/data/dxl/minidump/UnionAllWithTruncatedOutput.mdp @@ -324,7 +324,7 @@ - + @@ -338,7 +338,7 @@ - + @@ -445,7 +445,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UnionWithOuterRefs.mdp b/src/backend/gporca/data/dxl/minidump/UnionWithOuterRefs.mdp index 5438cacc0e89..290e6cfd12de 100644 --- a/src/backend/gporca/data/dxl/minidump/UnionWithOuterRefs.mdp +++ b/src/backend/gporca/data/dxl/minidump/UnionWithOuterRefs.mdp @@ -732,7 +732,7 @@ - + @@ -746,7 +746,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UnnestSQJoins.mdp b/src/backend/gporca/data/dxl/minidump/UnnestSQJoins.mdp index 351f735db8b5..59fab2b2328d 100644 --- a/src/backend/gporca/data/dxl/minidump/UnnestSQJoins.mdp +++ b/src/backend/gporca/data/dxl/minidump/UnnestSQJoins.mdp @@ -1283,148 +1283,91 @@ WHERE - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - + + + + - - - - - + + - - + + - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -1436,99 +1379,156 @@ WHERE - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + - + + - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/backend/gporca/data/dxl/minidump/UnsupportedStatsPredicate.mdp b/src/backend/gporca/data/dxl/minidump/UnsupportedStatsPredicate.mdp index e8545825f354..83a25ab00768 100644 --- a/src/backend/gporca/data/dxl/minidump/UnsupportedStatsPredicate.mdp +++ b/src/backend/gporca/data/dxl/minidump/UnsupportedStatsPredicate.mdp @@ -1019,7 +1019,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateCardinalityAssert.mdp b/src/backend/gporca/data/dxl/minidump/UpdateCardinalityAssert.mdp index cb3219098caf..7cf544591e2f 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateCardinalityAssert.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateCardinalityAssert.mdp @@ -277,7 +277,7 @@ - + @@ -303,7 +303,7 @@ - + @@ -331,7 +331,7 @@ - + @@ -352,7 +352,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateDistKeyWithNestedJoin.mdp b/src/backend/gporca/data/dxl/minidump/UpdateDistKeyWithNestedJoin.mdp index 026db05d722c..ec10764b0c1c 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateDistKeyWithNestedJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateDistKeyWithNestedJoin.mdp @@ -682,7 +682,7 @@ WHERE t1.id1 = t2.id1; - + @@ -708,7 +708,7 @@ WHERE t1.id1 = t2.id1; - + @@ -736,7 +736,7 @@ WHERE t1.id1 = t2.id1; - + @@ -757,7 +757,7 @@ WHERE t1.id1 = t2.id1; - + @@ -819,7 +819,7 @@ WHERE t1.id1 = t2.id1; - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateDistrKey.mdp b/src/backend/gporca/data/dxl/minidump/UpdateDistrKey.mdp index f6b2e0d6a62d..29e2934bb0b9 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateDistrKey.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateDistrKey.mdp @@ -272,7 +272,7 @@ - + @@ -298,7 +298,7 @@ - + @@ -326,7 +326,7 @@ - + @@ -347,7 +347,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateNotNullCols.mdp b/src/backend/gporca/data/dxl/minidump/UpdateNotNullCols.mdp index 67c9f0767bed..7ea50dcfbd0a 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateNotNullCols.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateNotNullCols.mdp @@ -330,7 +330,7 @@ - + @@ -356,7 +356,7 @@ - + @@ -384,7 +384,7 @@ - + @@ -414,7 +414,7 @@ - + @@ -438,7 +438,7 @@ - + @@ -464,7 +464,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint-2.mdp b/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint-2.mdp index cdf0f5eba8e0..90961adb3ce4 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateUniqueConstraint-2.mdp @@ -767,7 +767,7 @@ - + @@ -793,7 +793,7 @@ - + @@ -823,7 +823,7 @@ - + @@ -844,7 +844,7 @@ - + @@ -870,7 +870,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateWindowGatherMerge.mdp b/src/backend/gporca/data/dxl/minidump/UpdateWindowGatherMerge.mdp index 5d9fd884460d..07c38bc704fe 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateWindowGatherMerge.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateWindowGatherMerge.mdp @@ -711,7 +711,7 @@ - + @@ -737,7 +737,7 @@ - + @@ -760,7 +760,7 @@ - + @@ -781,7 +781,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UpdateWithHashJoin.mdp b/src/backend/gporca/data/dxl/minidump/UpdateWithHashJoin.mdp index 281d1beda1c1..417eb593cfef 100644 --- a/src/backend/gporca/data/dxl/minidump/UpdateWithHashJoin.mdp +++ b/src/backend/gporca/data/dxl/minidump/UpdateWithHashJoin.mdp @@ -303,7 +303,7 @@ - + @@ -329,7 +329,7 @@ - + @@ -350,7 +350,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/UseDistributionSatisfactionForUniversalInnerChild.mdp b/src/backend/gporca/data/dxl/minidump/UseDistributionSatisfactionForUniversalInnerChild.mdp index d9c86bfe6277..e8512f5ddd3f 100644 --- a/src/backend/gporca/data/dxl/minidump/UseDistributionSatisfactionForUniversalInnerChild.mdp +++ b/src/backend/gporca/data/dxl/minidump/UseDistributionSatisfactionForUniversalInnerChild.mdp @@ -107,7 +107,7 @@ - + @@ -120,7 +120,7 @@ - + @@ -135,7 +135,7 @@ - + diff --git a/src/backend/gporca/data/dxl/minidump/cte-duplicate-columns-2.mdp b/src/backend/gporca/data/dxl/minidump/cte-duplicate-columns-2.mdp index 4e173637adde..09eb7d08a398 100644 --- a/src/backend/gporca/data/dxl/minidump/cte-duplicate-columns-2.mdp +++ b/src/backend/gporca/data/dxl/minidump/cte-duplicate-columns-2.mdp @@ -248,7 +248,7 @@ where x1.b = x2.b; - + @@ -403,7 +403,7 @@ where x1.b = x2.b; - + diff --git a/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-JoinPred-AllLevels.mdp b/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-JoinPred-AllLevels.mdp index 1f9bb4d217de..eaae220b32fd 100644 --- a/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-JoinPred-AllLevels.mdp +++ b/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-JoinPred-AllLevels.mdp @@ -340,7 +340,7 @@ select * from pt, t where pt.j = t.t1 and pt.k = t.t2; - + @@ -363,7 +363,7 @@ select * from pt, t where pt.j = t.t1 and pt.k = t.t2; - + diff --git a/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-JoinPred-Level1.mdp b/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-JoinPred-Level1.mdp index 1691735a66d3..ab1a5f68ac25 100644 --- a/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-JoinPred-Level1.mdp +++ b/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-JoinPred-Level1.mdp @@ -358,7 +358,7 @@ select * from pt, t where pt.k = t.t1; - + @@ -381,7 +381,7 @@ select * from pt, t where pt.k = t.t1; - + diff --git a/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-JoinPred-Level2.mdp b/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-JoinPred-Level2.mdp index 177980adfcdc..513297baebbf 100644 --- a/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-JoinPred-Level2.mdp +++ b/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-JoinPred-Level2.mdp @@ -358,7 +358,7 @@ select * from pt, t where pt.j = t.t1; - + @@ -381,7 +381,7 @@ select * from pt, t where pt.j = t.t1; - + diff --git a/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-Nary-Join.mdp b/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-Nary-Join.mdp index 9327f1f8c1de..e6623ed9b908 100644 --- a/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-Nary-Join.mdp +++ b/src/backend/gporca/data/dxl/multilevel-partitioning/Multilevel-Nary-Join.mdp @@ -1429,7 +1429,7 @@ select * from pt, foo, bar where pt.k=foo.a and pt.j = bar.a; - + @@ -1458,7 +1458,7 @@ select * from pt, foo, bar where pt.k=foo.a and pt.j = bar.a; - + @@ -1493,7 +1493,7 @@ select * from pt, foo, bar where pt.k=foo.a and pt.j = bar.a; - + diff --git a/src/backend/gporca/libgpdbcost/src/CCostModelParamsGPDB.cpp b/src/backend/gporca/libgpdbcost/src/CCostModelParamsGPDB.cpp index 673f8f87af95..32ddac576cdf 100644 --- a/src/backend/gporca/libgpdbcost/src/CCostModelParamsGPDB.cpp +++ b/src/backend/gporca/libgpdbcost/src/CCostModelParamsGPDB.cpp @@ -95,7 +95,7 @@ const CDouble CCostModelParamsGPDB::DHJSpillingMemThresholdVal = const CDouble CCostModelParamsGPDB::DHJHashTableInitCostFactorVal = 500.0; // building hash table cost per tuple per column -const CDouble CCostModelParamsGPDB::DHJHashTableColumnCostUnitVal = 5.0e-05; +const CDouble CCostModelParamsGPDB::DHJHashTableColumnCostUnitVal = 1.0e-04; // the unit cost to process each tuple with unit width when building a hash table const CDouble CCostModelParamsGPDB::DHJHashTableWidthCostUnitVal = 3.0e-06; @@ -105,7 +105,7 @@ const CDouble CCostModelParamsGPDB::DHJHashingTupWidthCostUnitVal = 1.97e-05; // feeding cost per tuple per column in hash join if spilling const CDouble CCostModelParamsGPDB::DHJFeedingTupColumnSpillingCostUnitVal = - 1.97e-04; + 8.69e-05; // feeding cost per tuple with unit width in hash join if spilling const CDouble CCostModelParamsGPDB::DHJFeedingTupWidthSpillingCostUnitVal = diff --git a/src/backend/gporca/libgpopt/include/gpopt/base/CDistributionSpecHashed.h b/src/backend/gporca/libgpopt/include/gpopt/base/CDistributionSpecHashed.h index 3aa48cc1e532..5f25006d9d55 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/base/CDistributionSpecHashed.h +++ b/src/backend/gporca/libgpopt/include/gpopt/base/CDistributionSpecHashed.h @@ -74,12 +74,12 @@ class CDistributionSpecHashed : public CDistributionSpecRandom public: // ctor CDistributionSpecHashed(CExpressionArray *pdrgpexpr, BOOL fNullsColocated, - IMdIdArray *opfamilies = NULL); + IMdIdArray *opfamilies = NULL, BOOL noOp = false); // ctor CDistributionSpecHashed(CExpressionArray *pdrgpexpr, BOOL fNullsColocated, CDistributionSpecHashed *pdshashedEquiv, - IMdIdArray *opfamilies = NULL); + IMdIdArray *opfamilies = NULL, BOOL noOp = false); static CDistributionSpecHashed *MakeHashedDistrSpec( CMemoryPool *mp, CExpressionArray *pdrgpexpr, BOOL fNullsColocated, diff --git a/src/backend/gporca/libgpopt/include/gpopt/base/CDistributionSpecHashedNoOp.h b/src/backend/gporca/libgpopt/include/gpopt/base/CDistributionSpecHashedNoOp.h index 476c681235ca..a9883ef1f7d4 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/base/CDistributionSpecHashedNoOp.h +++ b/src/backend/gporca/libgpopt/include/gpopt/base/CDistributionSpecHashedNoOp.h @@ -12,7 +12,10 @@ namespace gpopt class CDistributionSpecHashedNoOp : public CDistributionSpecHashed { public: - CDistributionSpecHashedNoOp(CExpressionArray *pdrgpexr); + // explicitly pass opfamilies or NULL, since the default ones are not + // populated by parent ctor for NoOp cases. + CDistributionSpecHashedNoOp(CExpressionArray *pdrgpexr, + IMdIdArray *opfamilies); virtual EDistributionType Edt() const; diff --git a/src/backend/gporca/libgpopt/include/gpopt/base/CReqdPropPlan.h b/src/backend/gporca/libgpopt/include/gpopt/base/CReqdPropPlan.h index 66f67be0d2e3..7d0031802cd1 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/base/CReqdPropPlan.h +++ b/src/backend/gporca/libgpopt/include/gpopt/base/CReqdPropPlan.h @@ -16,6 +16,8 @@ #include "gpopt/base/CColRef.h" #include "gpopt/base/CReqdProp.h" +#define GPOPT_INVALID_OPT_REQUEST gpos::ulong_max + namespace gpopt { using namespace gpos; diff --git a/src/backend/gporca/libgpopt/include/gpopt/base/CUtils.h b/src/backend/gporca/libgpopt/include/gpopt/base/CUtils.h index 5eb78fcd551c..05b3ea709725 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/base/CUtils.h +++ b/src/backend/gporca/libgpopt/include/gpopt/base/CUtils.h @@ -445,13 +445,22 @@ class CUtils static CExpressionArray *PdrgpexprDedup(CMemoryPool *mp, CExpressionArray *pdrgpexpr); + // common handler for direct expression comparison CUtils::Equals + // and distribution matching CUtils::EqualDistributions. + static BOOL Equals(const CExpression *pexprLeft, + const CExpression *pexprRight, bool fMatchDistribution); + // deep equality of expression trees static BOOL Equals(const CExpression *pexprLeft, const CExpression *pexprRight); + static BOOL EqualDistributions(const CExpression *pexprLeft, + const CExpression *pexprRight); + // compare expression against an array of expressions static BOOL FEqualAny(const CExpression *pexpr, - const CExpressionArray *pdrgpexpr); + const CExpressionArray *pdrgpexpr, + BOOL fMatchDistribution); // deep equality of expression arrays static BOOL Equals(const CExpressionArray *pdrgpexprLeft, @@ -459,7 +468,11 @@ class CUtils // check if first expression array contains all expressions in second array static BOOL Contains(const CExpressionArray *pdrgpexprFst, - const CExpressionArray *pdrgpexprSnd); + const CExpressionArray *pdrgpexprSnd, + bool fMatchDistribution); + + static BOOL ContainsDistributions(const CExpressionArray *pdrgpexprFst, + const CExpressionArray *pdrgpexprSnd); // return the number of occurrences of the given expression in the given // array of expressions @@ -1002,7 +1015,10 @@ class CUtils CExpression *join_expr); static BOOL Contains(const CExpressionArray *exprs, - CExpression *expr_to_match); + CExpression *expr_to_match, BOOL fMatchDistribution); + + static BOOL ContainsDistribution(const CExpressionArray *exprs, + CExpression *expr_to_match); static BOOL Equals(const CExpressionArrays *exprs_arr, const CExpressionArrays *other_exprs_arr); diff --git a/src/backend/gporca/libgpopt/include/gpopt/operators/CPhysicalHashJoin.h b/src/backend/gporca/libgpopt/include/gpopt/operators/CPhysicalHashJoin.h index 22a1ec43d8af..54a2a5fcc172 100644 --- a/src/backend/gporca/libgpopt/include/gpopt/operators/CPhysicalHashJoin.h +++ b/src/backend/gporca/libgpopt/include/gpopt/operators/CPhysicalHashJoin.h @@ -56,7 +56,7 @@ class CPhysicalHashJoin : public CPhysicalJoin // compute a distribution matching the distribution delivered by given child CDistributionSpec *PdsMatch(CMemoryPool *mp, CDistributionSpec *pds, - ULONG ulSourceChildIndex) const; + ULONG ulSourceChildIndex, ULONG ulOptReq) const; protected: // compute required hashed distribution from the n-th child @@ -96,7 +96,7 @@ class CPhysicalHashJoin : public CPhysicalJoin // helper for computing a hashed distribution matching the given distribution CDistributionSpecHashed *PdshashedMatching( CMemoryPool *mp, CDistributionSpecHashed *pdshashed, - ULONG ulSourceChild) const; + ULONG ulSourceChild, ULONG ulOptReq) const; // create (singleton, singleton) optimization request CDistributionSpec *PdsRequiredSingleton(CMemoryPool *mp, @@ -220,7 +220,6 @@ class CPhysicalHashJoin : public CPhysicalJoin return dynamic_cast(pop); } - }; // class CPhysicalHashJoin } // namespace gpopt diff --git a/src/backend/gporca/libgpopt/src/base/CDistributionSpecHashed.cpp b/src/backend/gporca/libgpopt/src/base/CDistributionSpecHashed.cpp index de10f60e2f44..dcb4421aef0f 100644 --- a/src/backend/gporca/libgpopt/src/base/CDistributionSpecHashed.cpp +++ b/src/backend/gporca/libgpopt/src/base/CDistributionSpecHashed.cpp @@ -16,6 +16,7 @@ #include "gpopt/base/CColRefSetIter.h" #include "gpopt/base/COptCtxt.h" #include "gpopt/base/CUtils.h" +#include "gpopt/exception.h" #include "gpopt/operators/CExpressionHandle.h" #include "gpopt/operators/CExpressionPreprocessor.h" #include "gpopt/operators/CPhysicalMotionBroadcast.h" @@ -40,7 +41,8 @@ using namespace gpopt; //--------------------------------------------------------------------------- CDistributionSpecHashed::CDistributionSpecHashed(CExpressionArray *pdrgpexpr, BOOL fNullsColocated, - IMdIdArray *opfamilies) + IMdIdArray *opfamilies, + BOOL noOp) : m_pdrgpexpr(pdrgpexpr), m_opfamilies(opfamilies), m_fNullsColocated(fNullsColocated), @@ -50,7 +52,7 @@ CDistributionSpecHashed::CDistributionSpecHashed(CExpressionArray *pdrgpexpr, GPOS_ASSERT(NULL != pdrgpexpr); GPOS_ASSERT(0 < pdrgpexpr->Size()); if (GPOS_FTRACE(EopttraceConsiderOpfamiliesForDistribution) && - NULL == opfamilies) + NULL == opfamilies && !noOp) { PopulateDefaultOpfamilies(); } @@ -68,7 +70,7 @@ CDistributionSpecHashed::CDistributionSpecHashed(CExpressionArray *pdrgpexpr, //--------------------------------------------------------------------------- CDistributionSpecHashed::CDistributionSpecHashed( CExpressionArray *pdrgpexpr, BOOL fNullsColocated, - CDistributionSpecHashed *pdshashedEquiv, IMdIdArray *opfamilies) + CDistributionSpecHashed *pdshashedEquiv, IMdIdArray *opfamilies, BOOL noOp) : m_pdrgpexpr(pdrgpexpr), m_opfamilies(opfamilies), m_fNullsColocated(fNullsColocated), @@ -78,7 +80,7 @@ CDistributionSpecHashed::CDistributionSpecHashed( GPOS_ASSERT(NULL != pdrgpexpr); GPOS_ASSERT(0 < pdrgpexpr->Size()); if (GPOS_FTRACE(EopttraceConsiderOpfamiliesForDistribution) && - NULL == opfamilies) + NULL == opfamilies && !noOp) { PopulateDefaultOpfamilies(); } @@ -119,8 +121,9 @@ CDistributionSpecHashed::PopulateDefaultOpfamilies() // For a data type the retrieved opfamily can be 'InvalidOid'. // Eg - For 'json', the distribution opfamily is 'InvalidOid'. // Using an InvalidOid can lead to crash. - m_opfamilies->Release(); - m_opfamilies = NULL; + GPOS_RAISE( + gpopt::ExmaGPOPT, gpdxl::ExmiUnexpectedOp, + GPOS_WSZ_LIT(": opfamily must exist for each hash expr")); return; } mdid_opfamily->AddRef(); @@ -268,7 +271,7 @@ CDistributionSpecHashed::FMatchSubset( opfamily_other = (*pdsHashed->m_opfamilies)[ulInner]; } - if (CUtils::Equals(pexprOwn, pexprOther) && + if (CUtils::EqualDistributions(pexprOwn, pexprOther) && CUtils::Equals(opfamily_own, opfamily_other)) { fFound = true; @@ -295,7 +298,8 @@ CDistributionSpecHashed::FMatchSubset( GPOS_ASSERT(false == fFound); CExpressionArray *equiv_distribution_exprs = (*equiv_hash_exprs)[ulInner]; - if (CUtils::Contains(equiv_distribution_exprs, pexprOwn)) + if (CUtils::ContainsDistribution(equiv_distribution_exprs, + pexprOwn)) { fFound = true; break; @@ -517,12 +521,13 @@ CDistributionSpecHashed::FMatchHashedDistribution( equiv_distribution_exprs = (*all_equiv_exprs)[ul]; CExpression *pexprLeft = (*(pdshashed->m_pdrgpexpr))[ul]; CExpression *pexprRight = (*m_pdrgpexpr)[ul]; - BOOL fSuccess = CUtils::Equals(pexprLeft, pexprRight); + BOOL fSuccess = CUtils::EqualDistributions(pexprLeft, pexprRight); if (!fSuccess) { // if failed to find a equal match in the source distribution expr // array, check the equivalent exprs to find a match - fSuccess = CUtils::Contains(equiv_distribution_exprs, pexprRight); + fSuccess = CUtils::ContainsDistribution(equiv_distribution_exprs, + pexprRight); } if (!fSuccess) { @@ -616,6 +621,17 @@ CDistributionSpecHashed::Equals(const CDistributionSpec *input_spec) const CExpressionArrays *other_spec_equiv_exprs = other_spec->HashSpecEquivExprs(); + // The equality below should probably be strict, without need + // for calling CUtils::EqualDistributions, + // because the callers of this functions usually require + // direct expression matching. + // + // For example, one of the call chains leads to + // CCostContext::Equals and then to СGroupExpression::PccInsert + // + // But there are a lot of calls to this function, and given how + // nuanced ORCA can be, it is not strightforward to confirm this + // with certainty. return CUtils::Equals(spec_equiv_exprs, other_spec_equiv_exprs); } @@ -662,7 +678,8 @@ CDistributionSpecHashed::IsCoveredBy( const CDistributionSpecHashed *pds = this; while (pds && !covers) { - covers = CUtils::Contains(dist_cols_expr_array, pds->Pdrgpexpr()); + covers = CUtils::ContainsDistributions(dist_cols_expr_array, + pds->Pdrgpexpr()); pds = pds->PdshashedEquiv(); } return covers; @@ -753,13 +770,13 @@ CDistributionSpecHashed::ComputeEquivHashExprs( // if the predicate is a = b, and a is the current distribution expr, // then the equivalent expr is b CExpression *equiv_distribution_expr = NULL; - if (CUtils::Equals(left_distribution_expr, - distribution_expr)) + if (CUtils::EqualDistributions(left_distribution_expr, + distribution_expr)) { equiv_distribution_expr = right_distribution_expr; } - else if (CUtils::Equals(right_distribution_expr, - distribution_expr)) + else if (CUtils::EqualDistributions(right_distribution_expr, + distribution_expr)) { equiv_distribution_expr = left_distribution_expr; } diff --git a/src/backend/gporca/libgpopt/src/base/CDistributionSpecHashedNoOp.cpp b/src/backend/gporca/libgpopt/src/base/CDistributionSpecHashedNoOp.cpp index dbcebfedc118..8da365c67c6f 100644 --- a/src/backend/gporca/libgpopt/src/base/CDistributionSpecHashedNoOp.cpp +++ b/src/backend/gporca/libgpopt/src/base/CDistributionSpecHashedNoOp.cpp @@ -3,14 +3,15 @@ #include "gpopt/base/CDistributionSpecHashedNoOp.h" +#include "gpopt/exception.h" #include "gpopt/operators/CExpressionHandle.h" #include "gpopt/operators/CPhysicalMotionHashDistribute.h" using namespace gpopt; CDistributionSpecHashedNoOp::CDistributionSpecHashedNoOp( - CExpressionArray *pdrgpexpr) - : CDistributionSpecHashed(pdrgpexpr, true) + CExpressionArray *pdrgpexpr, IMdIdArray *opfamilies) + : CDistributionSpecHashed(pdrgpexpr, true, opfamilies, true) { } @@ -46,8 +47,21 @@ CDistributionSpecHashedNoOp::AppendEnforcers(CMemoryPool *mp, CExpressionArray *pdrgpexprNoOpRedistributionColumns = pdsChildHashed->Pdrgpexpr(); pdrgpexprNoOpRedistributionColumns->AddRef(); - CDistributionSpecHashedNoOp *pdsNoOp = GPOS_NEW(mp) - CDistributionSpecHashedNoOp(pdrgpexprNoOpRedistributionColumns); + + IMdIdArray *opfamilies = pdsChildHashed->Opfamilies(); + + if (GPOS_FTRACE(EopttraceConsiderOpfamiliesForDistribution)) + { + if (NULL == opfamilies) + GPOS_RAISE( + gpopt::ExmaGPOPT, gpdxl::ExmiUnexpectedOp, + GPOS_WSZ_LIT(": opfamily must exist for each hash expr")); + opfamilies->AddRef(); + } + + CDistributionSpecHashedNoOp *pdsNoOp = + GPOS_NEW(mp) CDistributionSpecHashedNoOp( + pdrgpexprNoOpRedistributionColumns, opfamilies); pexpr->AddRef(); CExpression *pexprMotion = GPOS_NEW(mp) CExpression( mp, GPOS_NEW(mp) CPhysicalMotionHashDistribute(mp, pdsNoOp), pexpr); diff --git a/src/backend/gporca/libgpopt/src/base/CUtils.cpp b/src/backend/gporca/libgpopt/src/base/CUtils.cpp index cc5fe5c4e319..bc115b60d8fb 100644 --- a/src/backend/gporca/libgpopt/src/base/CUtils.cpp +++ b/src/backend/gporca/libgpopt/src/base/CUtils.cpp @@ -1474,9 +1474,40 @@ CUtils::Equals(const CExpressionArray *pdrgpexprLeft, return fEqual; } -// deep equality of expression trees +// helper for CUtils::Equals, practically useless on its own +static const CExpression * +SkipCastWithinOpfamilyIfPossible(const CExpression *pexpr) +{ + if (pexpr->Pop()->Eopid() != COperator::EopScalarCast) + { + return pexpr; + } + + const CExpression *pexprChild = (*pexpr)[0]; + CScalar *popChild = CScalar::PopConvert(pexprChild->Pop()); + CScalarCast *popCast = CScalarCast::PopConvert(pexpr->Pop()); + IMDId *mdidSource = popChild->MdidType(); + IMDId *mdidDest = popCast->MdidType(); + + CMDAccessor *mda = COptCtxt::PoctxtFromTLS()->Pmda(); + const IMDType *mdtSourceType = mda->RetrieveType(mdidSource); + const IMDType *mdtDestType = mda->RetrieveType(mdidDest); + + IMDId *mdidSourceOpfamily = mdtSourceType->GetDistrOpfamilyMdid(); + IMDId *mdidTargetOpfamily = mdtDestType->GetDistrOpfamilyMdid(); + if (!CUtils::Equals(mdidSourceOpfamily, mdidTargetOpfamily)) + { + return pexpr; + } + + return pexprChild; +} + +// common handler for direct expression comparation CUtils::Equals +// and distribution matching CUtils::EqualDistributions BOOL -CUtils::Equals(const CExpression *pexprLeft, const CExpression *pexprRight) +CUtils::Equals(const CExpression *pexprLeft, const CExpression *pexprRight, + bool fMatchDistribution) { GPOS_CHECK_STACK_SIZE; @@ -1491,6 +1522,34 @@ CUtils::Equals(const CExpression *pexprLeft, const CExpression *pexprRight) { return true; } + // Allow an expression and the same expression + // casted to a different type within the same distribution opfamily + // be considered equal. + // E.g., let's suppose we have a table with a column of a type + // int2 named int2_column, then it would be considered equal + // to int2_column::int4 or int2_column::int8. + // This logic applies even if both expressions are converted + // to different types, e.g., int2_column::int4 = int2_column::int8 + // + // In this case, presence of the cast doesn't change how the value is + // distributed, meaning that redistribution motion is not required. + // + // Note that this check is not quite permissive, because distribution + // might not be changed even if there are multiple casts in a row, + // e.g. int2_column::int4::int8. + // But, as the time of writing this, the first cast will be turned into + // hard-to-detect coercion function anyway, so there is no need + // to perform this check recursively. + // + // Also, when using legacy hashfamilies, it is not guaranteed that + // different types within the same opfamily have the same hashfunction, + // so the logic above is not applicable. + if (GPOS_FTRACE(EopttraceConsiderOpfamiliesForDistribution) && + fMatchDistribution) + { + pexprLeft = SkipCastWithinOpfamilyIfPossible(pexprLeft); + pexprRight = SkipCastWithinOpfamilyIfPossible(pexprRight); + } // compare number of children and root operators if (pexprLeft->Arity() != pexprRight->Arity() || @@ -1507,6 +1566,20 @@ CUtils::Equals(const CExpression *pexprLeft, const CExpression *pexprRight) return FMatchChildrenUnordered(pexprLeft, pexprRight); } +// deep equality of expression trees +BOOL +CUtils::Equals(const CExpression *pexprLeft, const CExpression *pexprRight) +{ + return Equals(pexprLeft, pexprRight, false); +} + +BOOL +CUtils::EqualDistributions(const CExpression *pexprLeft, + const CExpression *pexprRight) +{ + return Equals(pexprLeft, pexprRight, true); +} + // check if two expressions have the same children in any order BOOL CUtils::FMatchChildrenUnordered(const CExpression *pexprLeft, @@ -1565,7 +1638,8 @@ CUtils::UlOccurrences(const CExpression *pexpr, CExpressionArray *pdrgpexpr) // compare expression against an array of expressions BOOL -CUtils::FEqualAny(const CExpression *pexpr, const CExpressionArray *pdrgpexpr) +CUtils::FEqualAny(const CExpression *pexpr, const CExpressionArray *pdrgpexpr, + BOOL fMatchDistribution) { GPOS_ASSERT(NULL != pexpr); @@ -1573,7 +1647,7 @@ CUtils::FEqualAny(const CExpression *pexpr, const CExpressionArray *pdrgpexpr) BOOL fEqual = false; for (ULONG ul = 0; !fEqual && ul < size; ul++) { - fEqual = Equals(pexpr, (*pdrgpexpr)[ul]); + fEqual = Equals(pexpr, (*pdrgpexpr)[ul], fMatchDistribution); } return fEqual; @@ -1582,7 +1656,7 @@ CUtils::FEqualAny(const CExpression *pexpr, const CExpressionArray *pdrgpexpr) // check if first expression array contains all expressions in second array BOOL CUtils::Contains(const CExpressionArray *pdrgpexprFst, - const CExpressionArray *pdrgpexprSnd) + const CExpressionArray *pdrgpexprSnd, BOOL fMatchDistribution) { GPOS_ASSERT(NULL != pdrgpexprFst); GPOS_ASSERT(NULL != pdrgpexprSnd); @@ -1601,12 +1675,20 @@ CUtils::Contains(const CExpressionArray *pdrgpexprFst, BOOL fContains = true; for (ULONG ul = 0; fContains && ul < size; ul++) { - fContains = FEqualAny((*pdrgpexprSnd)[ul], pdrgpexprFst); + fContains = + FEqualAny((*pdrgpexprSnd)[ul], pdrgpexprFst, fMatchDistribution); } return fContains; } +BOOL +CUtils::ContainsDistributions(const CExpressionArray *pdrgpexprFst, + const CExpressionArray *pdrgpexprSnd) +{ + return CUtils::Contains(pdrgpexprFst, pdrgpexprSnd, true); +} + // generate a Not expression on top of the given expression CExpression * CUtils::PexprNegate(CMemoryPool *mp, CExpression *pexpr) @@ -4907,33 +4989,53 @@ CUtils::PexprMatchEqualityOrINDF( CScalar::PopConvert(pexprPredOuter->Pop())->MdidType(); IMDId *pmdidTypeInner = CScalar::PopConvert(pexprPredInner->Pop())->MdidType(); - if (!pmdidTypeOuter->Equals(pmdidTypeInner)) + + CMDAccessor *mdAccessor = COptCtxt::PoctxtFromTLS()->Pmda(); + + IMDId *mdidOpfamilyInner = + mdAccessor->RetrieveType(pmdidTypeInner)->GetDistrOpfamilyMdid(); + + IMDId *mdidOpfamilyOuter = + mdAccessor->RetrieveType(pmdidTypeOuter)->GetDistrOpfamilyMdid(); + + // Callers of this function expect that they can distribute by the + // expression returned, and there were no guarantees + // about it before this call. + // + // For the time being, just don't return such expressions, + // but it doesn't seem that this logic belongs here. + if (GPOS_FTRACE(EopttraceConsiderOpfamiliesForDistribution) && + (!mdidOpfamilyInner || !mdidOpfamilyOuter)) { - // only consider equality of identical types continue; } + // Note that we need to manually remove binary coercible casts here, + // while for other join types this is done when they are being constructed + // (see CPhysicalJoin::AlignJoinKeyOuterInner). + CExpression *pexprOuterToMatch = + CCastUtils::PexprWithoutBinaryCoercibleCasts(pexprPredOuter); + CExpression *pexprInnerToMatch = + CCastUtils::PexprWithoutBinaryCoercibleCasts(pexprPredInner); pexprToMatch = CCastUtils::PexprWithoutBinaryCoercibleCasts(pexprToMatch); - if (CUtils::Equals( - CCastUtils::PexprWithoutBinaryCoercibleCasts(pexprPredOuter), - pexprToMatch)) + + if (CUtils::EqualDistributions(pexprOuterToMatch, pexprToMatch)) { pexprMatching = pexprPredInner; - break; } - - if (CUtils::Equals( - CCastUtils::PexprWithoutBinaryCoercibleCasts(pexprPredInner), - pexprToMatch)) + if (CUtils::EqualDistributions(pexprInnerToMatch, pexprToMatch)) { pexprMatching = pexprPredOuter; + } + if (pexprMatching) + { + pexprMatching = + CCastUtils::PexprWithoutBinaryCoercibleCasts(pexprMatching); break; } } - if (NULL != pexprMatching) - return CCastUtils::PexprWithoutBinaryCoercibleCasts(pexprMatching); return pexprMatching; } @@ -4966,7 +5068,8 @@ CUtils::MakeJoinWithoutInferredPreds(CMemoryPool *mp, CExpression *join_expr) // check if the input expr array contains the expr BOOL -CUtils::Contains(const CExpressionArray *exprs, CExpression *expr_to_match) +CUtils::Contains(const CExpressionArray *exprs, CExpression *expr_to_match, + BOOL fMatchDistribution) { if (NULL == exprs) { @@ -4977,11 +5080,18 @@ CUtils::Contains(const CExpressionArray *exprs, CExpression *expr_to_match) for (ULONG ul = 0; ul < exprs->Size() && !contains; ul++) { CExpression *expr = (*exprs)[ul]; - contains = CUtils::Equals(expr, expr_to_match); + contains = CUtils::Equals(expr, expr_to_match, fMatchDistribution); } return contains; } +BOOL +CUtils::ContainsDistribution(const CExpressionArray *exprs, + CExpression *expr_to_match) +{ + return Contains(exprs, expr_to_match, true); +} + BOOL CUtils::Equals(const CExpressionArrays *exprs_arr, const CExpressionArrays *other_exprs_arr) diff --git a/src/backend/gporca/libgpopt/src/operators/CPhysicalHashJoin.cpp b/src/backend/gporca/libgpopt/src/operators/CPhysicalHashJoin.cpp index eeeefe147acf..790375d781c6 100644 --- a/src/backend/gporca/libgpopt/src/operators/CPhysicalHashJoin.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CPhysicalHashJoin.cpp @@ -244,7 +244,7 @@ CPhysicalHashJoin::PrsRequired(CMemoryPool *mp, CExpressionHandle &exprhdl, //--------------------------------------------------------------------------- CDistributionSpec * CPhysicalHashJoin::PdsMatch(CMemoryPool *mp, CDistributionSpec *pds, - ULONG ulSourceChildIndex) const + ULONG ulSourceChildIndex, ULONG ulOptReq) const { GPOS_ASSERT(NULL != pds); @@ -267,7 +267,7 @@ CPhysicalHashJoin::PdsMatch(CMemoryPool *mp, CDistributionSpec *pds, // require second child to provide a matching hashed distribution return PdshashedMatching(mp, CDistributionSpecHashed::PdsConvert(pds), - ulSourceChildIndex); + ulSourceChildIndex, ulOptReq); default: GPOS_ASSERT(CDistributionSpec::EdtStrictReplicated == pds->Edt() || @@ -307,9 +307,11 @@ CPhysicalHashJoin::PdsMatch(CMemoryPool *mp, CDistributionSpec *pds, CDistributionSpecHashed * CPhysicalHashJoin::PdshashedMatching( CMemoryPool *mp, CDistributionSpecHashed *pdshashed, - ULONG - ulSourceChild // index of child that delivered the given hashed distribution -) const + // index of child that delivered the given hashed distribution + ULONG ulSourceChild, + // index of the request that created the distribution + // if this value is unknown, GPOPT_INVALID_OPT_REQUEST should be provided instead + ULONG ulOptReq) const { GPOS_ASSERT(2 > ulSourceChild); @@ -340,18 +342,98 @@ CPhysicalHashJoin::PdshashedMatching( CExpression *pexprDlvrd = (*pdrgpexprDist)[ulDlvrdIdx]; CExpressionArray *equiv_distribution_exprs = NULL; if (NULL != all_equiv_exprs && all_equiv_exprs->Size() > 0) + { equiv_distribution_exprs = (*all_equiv_exprs)[ulDlvrdIdx]; + } + + // first, try to match the initial source expression from which this request was derived, when + // 1) we know an optimization request index + // 2) requested distribution is on a single key + // + // if we don't perform this check right away, we might lose a distribution. + // consider the following query, before this logic was introduced: + // + // create table t1 as (select gen::numeric as a from generate_series(1, 20) as gen) distributed by (a); + // create table t2 as (select gen::numeric as a from generate_series(1, 20) as gen) distributed by (a); + // explain (verbose) select t1.a from t1 where t1.a = (select sum(t2.a) from t2 where t1.a = t2.a); + // Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..862.00 rows=1 width=8) + // Output: t1.a + // -> Hash Join (cost=0.00..862.00 rows=1 width=8) + // Output: t1.a + // Hash Cond: (((sum(t2.a)) = t1.a) AND (t2.a = t1.a)) + // -> Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..431.00 rows=1 width=16) + // Output: t2.a, (sum(t2.a)) + // Hash Key: (sum(t2.a)) + // -> GroupAggregate (cost=0.00..431.00 rows=1 width=16) + // Output: t2.a, sum(t2.a) + // Group Key: t2.a + // -> Sort (cost=0.00..431.00 rows=1 width=8) + // Output: t2.a + // Sort Key: t2.a + // -> Seq Scan on public.t2 (cost=0.00..431.00 rows=1 width=8) + // Output: t2.a + // -> Hash (cost=431.00..431.00 rows=1 width=8) + // Output: t1.a + // -> Seq Scan on public.t1 (cost=0.00..431.00 rows=1 width=8) + // Output: t1.a + // + // here, the join condition has two expressions, and all of them have the same + // right-hand side. It means that for every single-key redistribution request we get the same + // pexprDlvrd value (t1.a) + // and, when we go through the source expressions in order, + // the first expression will always be selected as matching for every redistribution request, + // meaning that the second expression has no chance to be matched, and therefore the distribution + // by t2.a is not considered + // + // also, it isn't obvious if the same problem might arise when matching a distribution containing + // multiple keys. theoretically, it can, so it might be worth exploring + + if (GPOPT_INVALID_OPT_REQUEST != ulOptReq && ulSourceSize > ulOptReq) + { + CExpression *source_expr = (*pdrgpexprSource)[ulOptReq]; + BOOL fSuccess = CUtils::EqualDistributions(pexprDlvrd, source_expr); + if (!fSuccess) + { + // if failed to find a equal match in the source distribution expr + // array, check the equivalent exprs to find a match + fSuccess = CUtils::ContainsDistribution( + equiv_distribution_exprs, source_expr); + } + if (fSuccess) + { + CExpression *pexprTarget = (*pdrgpexprTarget)[ulOptReq]; + pexprTarget->AddRef(); + pdrgpexpr->Append(pexprTarget); + + if (nullptr != opfamilies) + { + GPOS_ASSERT(nullptr != m_hash_opfamilies); + IMDId *opfamily = (*m_hash_opfamilies)[ulOptReq]; + opfamily->AddRef(); + opfamilies->Append(opfamily); + } + continue; + } + } + + // then, try the rest of the expressions for (ULONG idx = 0; idx < ulSourceSize; idx++) { + // check if we've already mathed this child above + if (idx == ulOptReq) + { + continue; + } + BOOL fSuccess = false; CExpression *source_expr = (*pdrgpexprSource)[idx]; - fSuccess = CUtils::Equals(pexprDlvrd, source_expr); + fSuccess = CUtils::EqualDistributions(pexprDlvrd, source_expr); if (!fSuccess) { // if failed to find a equal match in the source distribution expr // array, check the equivalent exprs to find a match - fSuccess = - CUtils::Contains(equiv_distribution_exprs, source_expr); + fSuccess = CUtils::ContainsDistribution( + equiv_distribution_exprs, source_expr); } if (fSuccess) { @@ -396,7 +478,7 @@ CPhysicalHashJoin::PdshashedMatching( CRefCount::SafeRelease(opfamilies); // try again using the equivalent hashed distribution return PdshashedMatching(mp, pdshashed->PdshashedEquiv(), - ulSourceChild); + ulSourceChild, ulOptReq); } // it should never happen, but instead of creating wrong spec, raise an exception GPOS_RAISE( @@ -638,6 +720,18 @@ CPhysicalHashJoin::PdsRequiredRedistribute(CMemoryPool *mp, } // find the distribution delivered by first child + // it should be noted that it is not guaranteed that the first child derived CDistributionSpecHashed + // for example, we might get a CDistributionSpecSingleton from it, so even though + // the initial request says (redistribute, redistribute), we would get (singleton, singleton) + // distribution as a result of this function + // + // it means that we don't guarantee that any requested distribution can be actually enforced. + // moreover, even when the first child derives CDistributionSpecHashed, the way we match distribution + // expressions inside PdshashedMatching is not perfect, and might possibly distort distribution + // of the second child + // + // this logic is far from being straightforward, but it is not a trivial problem to fix it + // at least you are warned about it CDistributionSpec *pdsFirst = CDrvdPropPlan::Pdpplan((*pdrgpdpCtxt)[0])->Pds(); GPOS_ASSERT(NULL != pdsFirst); @@ -667,7 +761,8 @@ CPhysicalHashJoin::PdsRequiredRedistribute(CMemoryPool *mp, } // return a matching distribution request for the second child - CDistributionSpec *pdsMatch = PdsMatch(mp, pdsInputForMatch, ulFirstChild); + CDistributionSpec *pdsMatch = + PdsMatch(mp, pdsInputForMatch, ulFirstChild, ulOptReq); if (pdsFirst->Edt() == CDistributionSpec::EdtHashed) { // if the input spec was created as a copy, release it @@ -917,7 +1012,8 @@ CPhysicalHashJoin::CreateOptRequests(CMemoryPool *mp) // to be distributed on single hash join keys separately, as well as the set // of all hash join keys, // the second hash join child is always required to match the distribution returned - // by first child + // by the first child. note, that the returned distribution may have different distribution keys + // compared to the requested one, or even have a different distribution kind altogether // Req(N + 1) (hashed, broadcast) // Req(N + 2) (non-singleton, broadcast) // Req(N + 3) (singleton, singleton) diff --git a/src/backend/gporca/libgpopt/src/operators/CPhysicalInnerHashJoin.cpp b/src/backend/gporca/libgpopt/src/operators/CPhysicalInnerHashJoin.cpp index ae4ce941684d..e9f8b605806a 100644 --- a/src/backend/gporca/libgpopt/src/operators/CPhysicalInnerHashJoin.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CPhysicalInnerHashJoin.cpp @@ -14,6 +14,7 @@ #include "gpos/base.h" #include "gpopt/base/CDistributionSpecHashed.h" +#include "gpopt/base/COptimizationContext.h" #include "gpopt/base/CUtils.h" #include "gpopt/operators/CExpressionHandle.h" @@ -68,8 +69,10 @@ CPhysicalInnerHashJoin::PdshashedCreateMatching( { GPOS_ASSERT(NULL != pdshashed); - CDistributionSpecHashed *pdshashedMatching = - PdshashedMatching(mp, pdshashed, ulSourceChild); + // if we end up here, it is completely unknown how our child derived its distribution + // so tell the function that we don't know how the spec was derived, and hope for the best + CDistributionSpecHashed *pdshashedMatching = PdshashedMatching( + mp, pdshashed, ulSourceChild, GPOPT_INVALID_OPT_REQUEST); // create a new spec with input and the output spec as equivalents, as you don't want to lose // the already existing equivalent specs of pdshashed diff --git a/src/backend/gporca/libgpopt/src/operators/CPhysicalJoin.cpp b/src/backend/gporca/libgpopt/src/operators/CPhysicalJoin.cpp index 00cb7cc4c205..f9d58db0e805 100644 --- a/src/backend/gporca/libgpopt/src/operators/CPhysicalJoin.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CPhysicalJoin.cpp @@ -23,6 +23,7 @@ #include "gpopt/operators/CScalarCmp.h" #include "gpopt/operators/CScalarIsDistinctFrom.h" #include "naucrates/md/IMDScalarOp.h" +#include "naucrates/traceflags/traceflags.h" using namespace gpopt; @@ -401,6 +402,23 @@ CPhysicalJoin::PedInnerHashedFromOuterHashed( mdAccessor->RetrieveType(pmdidTypeOuter) ->GetDistrOpfamilyMdid(); + // We may get here with null hashfamilies if we join on integer types + // (or other 'non-generic' types) + // with EopttraceConsiderOpfamiliesForDistribution is set to off. + // This is not the common case, because this flag is on by default. + // + // If a type has no dedicated subclass (i.e., it is CMDTypeGenericGPDB), + // hashfamilies are non-null most of the time, since they are set + // regardless of the flag. + // But even in such case the distribution can be missing if + // a type doesn't have one in the first place. + // For example, a type can be created this way by a user. + if (!mdidOpfamilyInner || !mdidOpfamilyOuter) + { + fSuccess = false; + continue; + } + if (mdidOpfamilyOuter->Equals(mdidOpfamilyInner) && mdAccessor->RetrieveType(pmdidTypeInner)->IsHashable()) { diff --git a/src/backend/gporca/libgpopt/src/operators/CPhysicalParallelUnionAll.cpp b/src/backend/gporca/libgpopt/src/operators/CPhysicalParallelUnionAll.cpp index 77518ec1c6e5..54d3db6fe15a 100644 --- a/src/backend/gporca/libgpopt/src/operators/CPhysicalParallelUnionAll.cpp +++ b/src/backend/gporca/libgpopt/src/operators/CPhysicalParallelUnionAll.cpp @@ -65,7 +65,7 @@ CPhysicalParallelUnionAll::PdsRequired(CMemoryPool *mp, CExpressionHandle &, pdrgpexprFakeRequestedColumns->Append(pexprScalarIdent); return GPOS_NEW(mp) - CDistributionSpecHashedNoOp(pdrgpexprFakeRequestedColumns); + CDistributionSpecHashedNoOp(pdrgpexprFakeRequestedColumns, NULL); } } diff --git a/src/backend/gporca/libgpopt/src/search/CGroup.cpp b/src/backend/gporca/libgpopt/src/search/CGroup.cpp index ce3853f2e109..3b723bd4d0dd 100644 --- a/src/backend/gporca/libgpopt/src/search/CGroup.cpp +++ b/src/backend/gporca/libgpopt/src/search/CGroup.cpp @@ -862,6 +862,12 @@ CGroup::AppendStats(CMemoryPool *mp, IStatistics *stats) GPOS_ASSERT(NULL != stats); GPOS_ASSERT(NULL != Pstats()); + if (FDuplicateGroup()) + { + PgroupDuplicate()->AppendStats(mp, stats); + return; + } + IStatistics *stats_copy = Pstats()->CopyStats(mp); stats_copy->AppendStats(mp, stats); diff --git a/src/backend/gporca/libgpopt/src/search/CGroupExpression.cpp b/src/backend/gporca/libgpopt/src/search/CGroupExpression.cpp index 34ad3dad91da..96283422d732 100644 --- a/src/backend/gporca/libgpopt/src/search/CGroupExpression.cpp +++ b/src/backend/gporca/libgpopt/src/search/CGroupExpression.cpp @@ -1104,6 +1104,16 @@ CGroupExpression::OsPrintCostContexts(IOstream &os, const CHAR *szPrefix) const // 4: CLogicalInnerJoin [ 6 7 3 ] Origin: (xform: CXformExpandNAryJoinGreedy, Grp: 4, GrpExpr: 3) // // Group 0 (#GExprs: 0, Duplicate Group: 4): +// +// There is also a chance that one of the group's expressions refers to the same group. +// This can happen if one of the groups has a link to another group, which in turn is its duplicate. +// Example: Group 0 is a duplicate of group 12, while it has an expression 1 +// that refers to group 12. After the groups merge, this expression will end up +// in group 12, which will lead to a cyclical relationship. +// Group 0 (#GExprs: 3, Duplicate Group: 12): +// 0: CLogicalCTEConsumer (1), Columns: ["a" (98), "b" (99), "c" (100)] [ ] +// 1: CLogicalSelect [ 12 3 ] +// 2: CLogicalNAryJoin [ 13 14 15 ] BOOL CGroupExpression::ContainsCircularDependencies() { @@ -1122,6 +1132,14 @@ CGroupExpression::ContainsCircularDependencies() CGroup *child_group = (*child_groups)[ul]; if (child_group->FScalar()) continue; + + if (child_group->Id() == m_pgroup->Id()) + { + m_ecirculardependency = CGroupExpression::ecdCircularDependency; + GPOS_ASSERT(Pgroup()->UlGExprs() > 1); + break; + } + CGroup *child_duplicate_group = child_group->PgroupDuplicate(); if (child_duplicate_group != NULL) { diff --git a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp index c80440d31c87..907d34ae3329 100644 --- a/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp +++ b/src/backend/gporca/libgpopt/src/translate/CTranslatorExprToDXL.cpp @@ -3632,10 +3632,18 @@ CTranslatorExprToDXL::PdxlnCorrelatedNLJoin( // If bar is a very small table, ORCA generates a CorrelatedInnerNLJoin with // a Const true join filter and condition 10 > bar.b is added as a filter // to the scan of bar. + // But, we should not create a Boolean subplan, if output columns are needed + // somewhere on upper levels, as filter will block them from projecting. // For the other cases function BuildSubplans generates another sublink type // for correct type of join condition. + CColRefSet *pcrsRequired = + GPOS_NEW(m_mp) CColRefSet(m_mp, *pexpr->Prpp()->PcrsRequired()); + CColRefSet *pcrsOutput = GPOS_NEW(m_mp) + CColRefSet(m_mp, *pexprInnerChild->DeriveOutputColumns()); + pcrsRequired->Intersection(pcrsOutput); if (CUtils::FScalarConstTrue(pexprScalar) && - COperator::EopPhysicalCorrelatedInnerNLJoin == op_id) + COperator::EopPhysicalCorrelatedInnerNLJoin == op_id && + 0 == pcrsRequired->Size()) { // translate relational inner child expression CDXLNode *pdxlnInnerChild = @@ -3656,6 +3664,8 @@ CTranslatorExprToDXL::PdxlnCorrelatedNLJoin( BuildSubplans(pexpr, dxl_colref_array, &pdxlnCond, pdrgpdsBaseTables, pulNonGatherMotions, pfDML); } + pcrsRequired->Release(); + pcrsOutput->Release(); // extract dxl properties from correlated join CDXLPhysicalProperties *dxl_properties = GetProperties(pexpr); diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerDynamicTableScan.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerDynamicTableScan.cpp index d007e52a8104..ea8f217c6dea 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerDynamicTableScan.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerDynamicTableScan.cpp @@ -162,7 +162,7 @@ CParseHandlerDynamicTableScan::EndElement(const XMLCh *const, // element_uri, m_mp, table_descr, m_part_index_id, m_part_index_id_printable); m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); // add constructed children diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerGatherMotion.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerGatherMotion.cpp index 56766a48b21a..9f926ce1da28 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerGatherMotion.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerGatherMotion.cpp @@ -160,7 +160,7 @@ CParseHandlerGatherMotion::EndElement(const XMLCh *const, // element_uri, GPOS_ASSERT(NULL != child_parse_handler); m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, m_dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerHashJoin.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerHashJoin.cpp index 5d40be605b97..1260ae54be84 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerHashJoin.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerHashJoin.cpp @@ -180,7 +180,7 @@ CParseHandlerHashJoin::EndElement(const XMLCh *const, // element_uri, GPOS_ASSERT(NULL != right_child_parse_handler); m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, m_dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); // add children diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerMaterialize.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerMaterialize.cpp index de235cce74ad..4ec5c3c606f6 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerMaterialize.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerMaterialize.cpp @@ -150,7 +150,7 @@ CParseHandlerMaterialize::EndElement(const XMLCh *const, // element_uri, GPOS_ASSERT(NULL != child_parse_handler); m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, m_dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); // add constructed children diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerMergeJoin.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerMergeJoin.cpp index 25a1dfec9f2a..ff5b1b08f0dc 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerMergeJoin.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerMergeJoin.cpp @@ -180,7 +180,7 @@ CParseHandlerMergeJoin::EndElement(const XMLCh *const, // element_uri, GPOS_ASSERT(NULL != right_child_parse_handler); m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, m_dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); // add children diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerNLJoin.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerNLJoin.cpp index ec806fd3e27d..2f30fce70ee8 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerNLJoin.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerNLJoin.cpp @@ -194,7 +194,7 @@ CParseHandlerNLJoin::EndElement(const XMLCh *const, // element_uri, m_dxl_op->SetNestLoopParamsColRefs(nest_params_colrefs); } m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, m_dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); // add constructed children diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalAbstractBitmapScan.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalAbstractBitmapScan.cpp index 90e8ffeb65ab..0011b26980f2 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalAbstractBitmapScan.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerPhysicalAbstractBitmapScan.cpp @@ -162,7 +162,7 @@ CParseHandlerPhysicalAbstractBitmapScan::EndElementHelper( } m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); // add constructed children diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerRandomMotion.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerRandomMotion.cpp index 7ce7235acad5..3fe6a23bd395 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerRandomMotion.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerRandomMotion.cpp @@ -160,7 +160,7 @@ CParseHandlerRandomMotion::EndElement(const XMLCh *const, // element_uri, GPOS_ASSERT(NULL != child_parse_handler); m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, m_dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); // add children diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerRedistributeMotion.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerRedistributeMotion.cpp index 62b5ec7d13e0..97d8d5b182dc 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerRedistributeMotion.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerRedistributeMotion.cpp @@ -176,7 +176,7 @@ CParseHandlerRedistributeMotion::EndElement( GPOS_ASSERT(NULL != child_parse_handler); m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, m_dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); // add children diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerResult.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerResult.cpp index 85fa41b1441a..315303710144 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerResult.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerResult.cpp @@ -178,7 +178,7 @@ CParseHandlerResult::EndElement(const XMLCh *const, // element_uri, GPOS_ASSERT(NULL != one_time_filter_parse_handler); m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, m_dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); // add constructed children diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerRoutedMotion.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerRoutedMotion.cpp index d32abfbb0187..0e3638fa56cd 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerRoutedMotion.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerRoutedMotion.cpp @@ -162,7 +162,7 @@ CParseHandlerRoutedMotion::EndElement(const XMLCh *const, // element_uri, GPOS_ASSERT(NULL != child_parse_handler); m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, m_dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); // add children diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerSort.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerSort.cpp index bed106991b3e..5ba4eb31d9c2 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerSort.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerSort.cpp @@ -181,7 +181,7 @@ CParseHandlerSort::EndElement(const XMLCh *const, // element_uri, GPOS_ASSERT(NULL != child_parse_handler); m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, m_dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); // add children diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerSubqueryScan.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerSubqueryScan.cpp index 604c49b1a3fd..1d285dc0b71c 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerSubqueryScan.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerSubqueryScan.cpp @@ -146,7 +146,7 @@ CParseHandlerSubqueryScan::EndElement(const XMLCh *const, // element_uri, GPOS_ASSERT(NULL != child_parse_handler); m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, m_dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); // add constructed children diff --git a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerTableScan.cpp b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerTableScan.cpp index f6f0c7123fc7..1280d01755f5 100644 --- a/src/backend/gporca/libnaucrates/src/parser/CParseHandlerTableScan.cpp +++ b/src/backend/gporca/libnaucrates/src/parser/CParseHandlerTableScan.cpp @@ -189,7 +189,7 @@ CParseHandlerTableScan::EndElement(const XMLCh *const element_local_name, m_dxl_op->SetTableDescriptor(table_descr); m_dxl_node = GPOS_NEW(m_mp) CDXLNode(m_mp, m_dxl_op); - // set statictics and physical properties + // set statistics and physical properties CParseHandlerUtils::SetProperties(m_dxl_node, prop_parse_handler); // add constructed children diff --git a/src/backend/gporca/libnaucrates/src/statistics/CBucket.cpp b/src/backend/gporca/libnaucrates/src/statistics/CBucket.cpp index 3ddd0c987455..e63d8ad09b2a 100644 --- a/src/backend/gporca/libnaucrates/src/statistics/CBucket.cpp +++ b/src/backend/gporca/libnaucrates/src/statistics/CBucket.cpp @@ -455,7 +455,6 @@ CBucket::MakeBucketCopy(CMemoryPool *mp) BOOL CBucket::Equals(const CBucket *bucket) { - GPOS_ASSERT(this != NULL); GPOS_ASSERT(bucket != NULL); if (this->GetLowerBound()->Equals(bucket->GetLowerBound()) && this->IsLowerClosed() == bucket->IsLowerClosed() && diff --git a/src/backend/gporca/server/CMakeLists.txt b/src/backend/gporca/server/CMakeLists.txt index e2de25e87767..4cb17c128bae 100644 --- a/src/backend/gporca/server/CMakeLists.txt +++ b/src/backend/gporca/server/CMakeLists.txt @@ -71,7 +71,7 @@ OR-WithIsNullPred Int2Predicate IN-Numeric DeduplicatePredicates AddEqualityPredicates EqualityPredicateOverDate AddPredsInSubqueries ExtractPredicateFromDisjWithComputedColumns Join-With-Subq-Preds-1 Non-Hashjoinable-Pred Non-Hashjoinable-Pred-2 Factorized-Preds IN OR AvoidConstraintDerivationForLike NLJ-DistCol-No-Broadcast NLJ-EqAllCol-No-Broadcast NLJ-EqDistCol-InEqNonDistCol-No-Broadcast -NLJ-InEqDistCol-EqNonDistCol-Redistribute CorrelatedNLJWithTrueCondition InferPredicatesInnerOfLOJ +NLJ-InEqDistCol-EqNonDistCol-Redistribute CorrelatedNLJWithTrueCondition CorrelatedNLJWithTrueConditionNeededProjection InferPredicatesInnerOfLOJ InferredPredicatesConstraintSimplification NoPushdownPredicateWithCTEAnchor InferPredicatesForPartSQ InferPredicatesForQuantifiedSQ DoubleNDVCardinalityEquals NotWellDefinedDisjunctConjunctPredicates InferPredicatesIntFromSubquery InferPredicatesFromExistsSubquery diff --git a/src/backend/gporca/server/src/unittest/gpopt/base/CGroupTest.cpp b/src/backend/gporca/server/src/unittest/gpopt/base/CGroupTest.cpp index de06032d3716..cd4ba99944d4 100644 --- a/src/backend/gporca/server/src/unittest/gpopt/base/CGroupTest.cpp +++ b/src/backend/gporca/server/src/unittest/gpopt/base/CGroupTest.cpp @@ -104,6 +104,24 @@ CGroupTest::EresUnittest_FResetStatsOnCGroupWithDuplicateGroup() return GPOS_FAILED; } + CStatistics *stat = + GPOS_NEW(mp) CStatistics(mp, GPOS_NEW(mp) UlongToHistogramMap(mp), + GPOS_NEW(mp) UlongToDoubleMap(mp), 0, false); + + IStatistics *oldStats = pmemo->Pgroup(0)->Pstats(); + pmemo->Pgroup(0)->AppendStats(mp, stat); + + // By appending stats on group (0), we really are appending the stats on + // group (1). group (0) stats is never set in the first place. + if (oldStats == pmemo->Pgroup(1)->Pstats()) + { + stat->Release(); + GPOS_DELETE(pmemo); + pexprGet1->Release(); + pexprGet2->Release(); + return GPOS_FAILED; + } + pmemo->Pgroup(0)->FResetStats(); // By resetting stats on group (0), we really are resetting the stats on @@ -111,12 +129,14 @@ CGroupTest::EresUnittest_FResetStatsOnCGroupWithDuplicateGroup() if (pmemo->Pgroup(0)->Pstats() != NULL || pmemo->Pgroup(1)->Pstats() != NULL) { + stat->Release(); GPOS_DELETE(pmemo); pexprGet1->Release(); pexprGet2->Release(); return GPOS_FAILED; } + stat->Release(); GPOS_DELETE(pmemo); pexprGet1->Release(); pexprGet2->Release(); diff --git a/src/backend/gporca/server/src/unittest/gpopt/minidump/CCTETest.cpp b/src/backend/gporca/server/src/unittest/gpopt/minidump/CCTETest.cpp index 53cabdf2ac5b..7e040abc863b 100644 --- a/src/backend/gporca/server/src/unittest/gpopt/minidump/CCTETest.cpp +++ b/src/backend/gporca/server/src/unittest/gpopt/minidump/CCTETest.cpp @@ -59,6 +59,7 @@ const CHAR *rgszCTEFileNames[] = { "../data/dxl/minidump/CTE-ValuesScan-ProjList.mdp", "../data/dxl/minidump/CTEWithMergedGroup.mdp", "../data/dxl/minidump/CTEMergeGroupsCircularDeriveStats.mdp", + "../data/dxl/minidump/CTEMergeGroupsCircularDeriveStats2.mdp", "../data/dxl/minidump/CTE15Replicated.mdp", "../data/dxl/minidump/CTE2Replicated.mdp", "../data/dxl/minidump/CTE15HAReplicated.mdp", diff --git a/src/backend/libpq/pqcomm.c b/src/backend/libpq/pqcomm.c index 2b0700814491..553aecac2a22 100644 --- a/src/backend/libpq/pqcomm.c +++ b/src/backend/libpq/pqcomm.c @@ -998,6 +998,13 @@ pq_waitForDataUsingSelect(void) errno = 0; numSockets = select(sock+1, &toRead, NULL /* toWrite */, &haveError, NULL ); + /* + * Here numSockets < 0 should be technically checked first for + * proper error handling. However, this function wasn't modified + * since it isn't using in our code. Changing it would be risky + * due to the lack of coverage, and the external extensions might + * still rely on it. + */ if ( errno == EINTR) { return false; diff --git a/src/backend/optimizer/plan/createplan.c b/src/backend/optimizer/plan/createplan.c index 782b43359fe6..e8edcc66aa8d 100644 --- a/src/backend/optimizer/plan/createplan.c +++ b/src/backend/optimizer/plan/createplan.c @@ -5702,6 +5702,13 @@ make_motion(PlannerInfo *root, Plan *lefttree, Oid *sortOperators, Oid *collations, bool *nullsFirst, bool useExecutorVarFormat) { + if (Gp_role != GP_ROLE_DISPATCH) + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot create Motion on QE slice"))); + } + Motion *node = makeNode(Motion); Plan *plan = &node->plan; @@ -7241,7 +7248,13 @@ append_initplan_for_function_scan(PlannerInfo *root, Path *best_path, Plan *plan subroot = (PlannerInfo *) palloc(sizeof(PlannerInfo)); memcpy(subroot, root, sizeof(PlannerInfo)); subroot->query_level++; - subroot->parent_root = root; + /* + * We set parent_root to NULL here in order to isolate the initplan + * from all params ('plan_params') of outer queries. Otherwise, we may + * recognize the parameter of the initplan function, referring to the + * outer query, as an eligible param. + */ + subroot->parent_root = NULL; /* reset subplan-related stuff */ subroot->plan_params = NIL; subroot->init_plans = NIL; diff --git a/src/backend/optimizer/plan/subselect.c b/src/backend/optimizer/plan/subselect.c index d6133e82ae20..55ef62e089dc 100644 --- a/src/backend/optimizer/plan/subselect.c +++ b/src/backend/optimizer/plan/subselect.c @@ -420,7 +420,7 @@ get_first_col_type(Plan *plan, Oid *coltype, int32 *coltypmod, } /** - * Returns true if query refers to a distributed table. + * Returns true if query refers to a distributed or replicated table. */ bool QueryHasDistributedRelation(Query *q, bool recursive) { @@ -435,11 +435,13 @@ bool QueryHasDistributedRelation(Query *q, bool recursive) && QueryHasDistributedRelation(rte->subquery, true)) return true; + /* Really, any kind of distribution policy causes rescan issues */ if (rte->relid != InvalidOid && rte->rtekind == RTE_RELATION) { GpPolicy *policy = GpPolicyFetch(rte->relid); - if (GpPolicyIsPartitioned(policy)) + if (GpPolicyIsPartitioned(policy) || + GpPolicyIsReplicated(policy)) { pfree(policy); return true; @@ -450,6 +452,30 @@ bool QueryHasDistributedRelation(Query *q, bool recursive) return false; } +/** + * Returns true if query refers to an entry table. + */ +bool QueryHasMasterOnlyRelation(Query *q) { + ListCell *rt = NULL; + + foreach(rt, q->rtable) + { + RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt); + + if (rte->relid != InvalidOid + && rte->rtekind == RTE_RELATION) + { + GpPolicy *policy = GpPolicyFetch(rte->relid); + if (GpPolicyIsEntry(policy)) + { + pfree(policy); + return true; + } + } + } + return false; +} + typedef struct CorrelatedVarWalkerContext { int maxLevelsUpVar; @@ -534,9 +560,11 @@ check_multi_subquery_correlated(PlannerInfo *root, Var *var) if (list_length(root->parse->rtable) == 0) return; + PlannerInfo *parent_root = NULL; + PlannerInfo *cur_root = root; for (levelsup = var->varlevelsup; levelsup > 0; levelsup--) { - PlannerInfo *parent_root = root->parent_root; + parent_root = cur_root->parent_root; if (parent_root == NULL) elog(ERROR, "not found parent root when checking skip-level correlations"); @@ -545,16 +573,25 @@ check_multi_subquery_correlated(PlannerInfo *root, Var *var) * Only check sublink not include subquery */ if(parent_root->parse->hasSubLinks && - QueryHasDistributedRelation(root->parse, parent_root->is_correlated_subplan)) + QueryHasDistributedRelation(cur_root->parse, parent_root->is_correlated_subplan)) { ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("correlated subquery with skip-level correlations is not supported"))); } - root = root->parent_root; + cur_root = cur_root->parent_root; } + if (parent_root->parse->hasSubLinks && + QueryHasDistributedRelation(parent_root->parse, false) && + QueryHasMasterOnlyRelation(root->parse)) + { + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("correlated subquery with skip-level correlations is not supported"))); + } + return; } diff --git a/src/backend/postmaster/pgstat.c b/src/backend/postmaster/pgstat.c index 4052a71100a7..f6393ddf6d88 100644 --- a/src/backend/postmaster/pgstat.c +++ b/src/backend/postmaster/pgstat.c @@ -2956,6 +2956,8 @@ pgstat_report_resgroup(TimestampTz queueStart, Oid groupid) beentry->st_rsgid = groupid; beentry->st_changecount++; Assert((beentry->st_changecount & 1) == 0); + + elog(DEBUG1, "Reported resource group ID of %d", groupid); } /* diff --git a/src/backend/postmaster/postmaster.c b/src/backend/postmaster/postmaster.c index 37ead7c8693d..0de0b7da0ced 100644 --- a/src/backend/postmaster/postmaster.c +++ b/src/backend/postmaster/postmaster.c @@ -3738,6 +3738,21 @@ CleanupBackend(int pid, if (!EXIT_STATUS_0(exitstatus) && !EXIT_STATUS_1(exitstatus)) { + +#ifdef FAULT_INJECTOR + if (pmState == PM_RUN) + { + /* + * Code below is for test purposes only. If a fault is set, it + * will formally be completed without doing anything. + * + * Additional note: This check of pmState == PM_RUN is just extra + * safety measurments. If we try to access this code not from + * PM_RUN the behaviour can be unpredictable. + */ + SIMPLE_FAULT_INJECTOR("backend_abort_handling"); + } +#endif HandleChildCrash(pid, exitstatus, _("server process")); return; } diff --git a/src/backend/replication/logical/snapbuild.c b/src/backend/replication/logical/snapbuild.c index 06fbead100c8..0305c3cf82ba 100644 --- a/src/backend/replication/logical/snapbuild.c +++ b/src/backend/replication/logical/snapbuild.c @@ -1684,6 +1684,7 @@ SnapBuildRestore(SnapBuild *builder, XLogRecPtr lsn) /* read statically sized portion of snapshot */ + errno = 0; readBytes = read(fd, &ondisk, SnapBuildOnDiskConstantSize); if (readBytes != SnapBuildOnDiskConstantSize) { diff --git a/src/backend/replication/slot.c b/src/backend/replication/slot.c index 5503ac4e76fe..a8982f7373d6 100644 --- a/src/backend/replication/slot.c +++ b/src/backend/replication/slot.c @@ -1326,6 +1326,7 @@ RestoreSlotFromDisk(const char *name) END_CRIT_SECTION(); /* read part of statefile that's guaranteed to be version independent */ + errno = 0; readBytes = read(fd, &cp, ReplicationSlotOnDiskConstantSize); if (readBytes != ReplicationSlotOnDiskConstantSize) { diff --git a/src/backend/storage/buffer/bufmgr.c b/src/backend/storage/buffer/bufmgr.c index 399649affcab..0c2907f1cedd 100644 --- a/src/backend/storage/buffer/bufmgr.c +++ b/src/backend/storage/buffer/bufmgr.c @@ -361,6 +361,7 @@ ReadBufferWithoutRelcache(RelFileNode rnode, ForkNumber forkNum, bool hit; SMgrRelation smgr = smgropen(rnode, InvalidBackendId); + smgr->smgr_which = 0; Assert(InRecovery); @@ -2121,6 +2122,7 @@ FlushBuffer(volatile BufferDesc *buf, SMgrRelation reln) reln = smgropen(buf->tag.rnode, istemp ? TempRelBackendId : InvalidBackendId); + reln->smgr_which = 0; } TRACE_POSTGRESQL_BUFFER_FLUSH_START(buf->tag.forkNum, diff --git a/src/backend/storage/buffer/localbuf.c b/src/backend/storage/buffer/localbuf.c index 1b77a83c6813..8b0ba5b392a6 100644 --- a/src/backend/storage/buffer/localbuf.c +++ b/src/backend/storage/buffer/localbuf.c @@ -207,6 +207,7 @@ LocalBufferAlloc(SMgrRelation smgr, ForkNumber forkNum, BlockNumber blockNum, /* Find smgr relation for buffer */ oreln = smgropen(bufHdr->tag.rnode, MyBackendId); + oreln->smgr_which = 0; // GPDB_93_MERGE_FIXME: is this TODO comment still relevant? // UNDONE: Unfortunately, I think we write temp relations to the mirror... diff --git a/src/backend/storage/ipc/procarray.c b/src/backend/storage/ipc/procarray.c index 4962759ad21d..957e146f9d56 100644 --- a/src/backend/storage/ipc/procarray.c +++ b/src/backend/storage/ipc/procarray.c @@ -52,6 +52,7 @@ #include "access/xact.h" #include "access/twophase.h" #include "catalog/catalog.h" +#include "cdb/cdbendpoint.h" #include "miscadmin.h" #include "port/atomics.h" #include "storage/proc.h" @@ -4880,7 +4881,7 @@ LocalXidGetDistributedXid(TransactionId xid) { DistributedLog_GetDistributedXid(xid, &tstamp, &gxid); AssertImply(gxid != InvalidDistributedTransactionId, - tstamp == MyTmGxact->distribTimeStamp); + (tstamp == MyTmGxact->distribTimeStamp || MyTmGxact->distribTimeStamp == 0)); } return gxid; @@ -4951,8 +4952,12 @@ ResGroupMoveSignalTarget(int sessionId, void *slot, Oid groupId, { PGPROC *proc = &allProcs[arrayP->pgprocnos[i]]; - if (proc->mppSessionId != sessionId) + /* Retrieve sessions are in utility mode. Grab them too. */ + if (proc->mppSessionId != sessionId && + !sharedEndpointsContain(proc->pid, sessionId)) + { continue; + } /* * Before, we didn't distinguish entrydb processes from main target diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c index 9ec98c84b2f3..87271a33c0e7 100644 --- a/src/backend/storage/smgr/md.c +++ b/src/backend/storage/smgr/md.c @@ -342,6 +342,9 @@ mdcreate(SMgrRelation reln, ForkNumber forkNum, bool isRedo) reln->md_fd[forkNum]->mdfd_vfd = fd; reln->md_fd[forkNum]->mdfd_segno = 0; reln->md_fd[forkNum]->mdfd_chain = NULL; + + if (!SmgrIsTemp(reln) && reln->smgr_which == RELSTORAGE_HEAP) + register_dirty_segment(reln, forkNum, reln->md_fd[forkNum]); } /* @@ -1326,6 +1329,7 @@ mdsync(void) * cases we couldn't safely do that.) */ reln = smgropen(entry->rnode, InvalidBackendId); + reln->smgr_which = 0; if (entry->is_ao_segnos) { @@ -1914,6 +1918,7 @@ DropRelationFiles(RelFileNodePendingDelete *delrels, int ndelrels, bool isRedo) * given relfile since we don't tie temp relations to their backends. */ SMgrRelation srel = smgropen(delrels[i].node, delrels[i].isTempRelation ? TempRelBackendId : InvalidBackendId); + srel->smgr_which = delrels[i].relstorage; if (isRedo) { diff --git a/src/backend/tcop/postgres.c b/src/backend/tcop/postgres.c index 437059ff3d72..0961c6a66851 100644 --- a/src/backend/tcop/postgres.c +++ b/src/backend/tcop/postgres.c @@ -2320,6 +2320,32 @@ exec_bind_message(StringInfo input_message) if (save_log_statement_stats) ResetUsage(); + /* + * If several queries are processed within the same transaction during + * extended protocol communication, and the first of them is a bypassing + * command, the next commands may also bypass resgroup quota assignment. + * In order to prevent that, the best option would be to reassign resgroup + * at the start of normal command until the transaction end. + */ + if (Gp_role == GP_ROLE_DISPATCH && ResGroupIsBypassed() + && IsTransactionState()) + { + MemoryContextSwitchTo(CurTransactionContext); + + List *parsetree_list = list_make1(psrc->raw_parse_tree); + + if (!ShouldBypassQueryFromParseTree(parsetree_list)) + { + elog(DEBUG1, "Upgrading from bypassed resource group at bind time for statement: %s", + psrc->query_string); + + UnassignResGroup(); + AttachResGroupSlot(); + } + + list_free(parsetree_list); + } + /* * Start up a transaction command so we can call functions etc. (Note that * this will normally change current memory context.) Nothing happens if @@ -5400,6 +5426,11 @@ PostgresMain(int argc, char *argv[], elogif(Debug_print_full_dtm, LOG, "Simple query stmt: %s.",query_string); + if (ShouldUseRetrieveResGroup()) + { + SwitchResGroupOnRetrieveSession(); + } + if (am_walsender) exec_replication_command(query_string); else if (am_ftshandler) diff --git a/src/backend/tcop/test/postgres_test.c b/src/backend/tcop/test/postgres_test.c index cc0b0164fdc5..740d91e06b48 100644 --- a/src/backend/tcop/test/postgres_test.c +++ b/src/backend/tcop/test/postgres_test.c @@ -19,6 +19,14 @@ errfinish_impl(int dummy __attribute__((unused)),...) PG_RE_THROW(); } +bool __wrap_in_oom_error_trouble(void); + +bool +__wrap_in_oom_error_trouble(void) +{ + return false; +} + #include "../postgres.c" #define EXPECT_EREPORT(LOG_LEVEL) \ diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c index a3b6efd9ca5d..7a100e9b22ce 100644 --- a/src/backend/tcop/utility.c +++ b/src/backend/tcop/utility.c @@ -1840,19 +1840,23 @@ ExecDropStmt(DropStmt *stmt, bool isTopLevel) case OBJECT_MATVIEW: case OBJECT_FOREIGN_TABLE: case OBJECT_EXTTABLE: - RemoveRelations(stmt); + RemoveRelations(copyStmt); break; default: - RemoveObjects(stmt); + RemoveObjects(copyStmt); break; } + SIMPLE_FAULT_INJECTOR("wait_before_drop_dispatch"); + /* * Dispatch the original, unmodified statement. * * Event triggers are not stored in QE nodes, so skip those. */ - if (Gp_role == GP_ROLE_DISPATCH && stmt->removeType != OBJECT_EVENT_TRIGGER) + if (Gp_role == GP_ROLE_DISPATCH && + stmt->removeType != OBJECT_EVENT_TRIGGER && + list_length(copyStmt->objects) > 0) { int flags; diff --git a/src/backend/utils/adt/jsonb_util.c b/src/backend/utils/adt/jsonb_util.c index e45132229b27..d8aa4d890706 100644 --- a/src/backend/utils/adt/jsonb_util.c +++ b/src/backend/utils/adt/jsonb_util.c @@ -252,9 +252,6 @@ compareJsonbContainers(JsonbContainer *a, JsonbContainer *b) else { /* - * It's safe to assume that the types differed, and that the va - * and vb values passed were set. - * * If the two values were of the same container type, then there'd * have been a chance to observe the variation in the number of * elements/pairs (when processing WJB_BEGIN_OBJECT, say). They're @@ -748,15 +745,20 @@ JsonbIteratorInit(JsonbContainer *container) * It is our job to expand the jbvBinary representation without bothering them * with it. However, clients should not take it upon themselves to touch array * or Object element/pair buffers, since their element/pair pointers are - * garbage. Also, *val will not be set when returning WJB_END_ARRAY or - * WJB_END_OBJECT, on the assumption that it's only useful to access values - * when recursing in. + * garbage. + * + * *val is not meaningful when the result is WJB_DONE, WJB_END_ARRAY or + * WJB_END_OBJECT. However, we set val->type = jbvNull in those cases, + * so that callers may assume that val->type is always well-defined. */ JsonbIteratorToken JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested) { if (*it == NULL) + { + val->type = jbvNull; return WJB_DONE; + } /* * When stepping into a nested container, we jump back here to start @@ -794,6 +796,7 @@ JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested) * nesting). */ *it = freeAndGetParent(*it); + val->type = jbvNull; return WJB_END_ARRAY; } @@ -847,6 +850,7 @@ JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested) * of nesting). */ *it = freeAndGetParent(*it); + val->type = jbvNull; return WJB_END_OBJECT; } else @@ -891,8 +895,10 @@ JsonbIteratorNext(JsonbIterator **it, JsonbValue *val, bool skipNested) return WJB_VALUE; } - elog(ERROR, "invalid iterator state"); - return -1; + elog(ERROR, "invalid jsonb iterator state"); + /* satisfy compilers that don't know that elog(ERROR) doesn't return */ + val->type = jbvNull; + return WJB_DONE; } /* diff --git a/src/backend/utils/cache/relmapper.c b/src/backend/utils/cache/relmapper.c index d6e3ca348190..3e5d77c09ec0 100644 --- a/src/backend/utils/cache/relmapper.c +++ b/src/backend/utils/cache/relmapper.c @@ -656,6 +656,7 @@ load_relmap_file(bool shared) * look, the sinval signaling mechanism will make us re-read it before we * are able to access any relation that's affected by the change. */ + errno = 0; if (read(fd, map, sizeof(RelMapFile)) != sizeof(RelMapFile)) ereport(FATAL, (errcode_for_file_access(), diff --git a/src/backend/utils/error/elog.c b/src/backend/utils/error/elog.c index a447b00b7964..920559a8f8d5 100644 --- a/src/backend/utils/error/elog.c +++ b/src/backend/utils/error/elog.c @@ -174,6 +174,15 @@ static bool openlog_done = false; static char *syslog_ident = NULL; static int syslog_facility = LOG_LOCAL0; +/* + * GPDB: + * Workaround for dispatcher cleanup routines to know whether we should take a + * shortcut and avoid allocations. + * + * Set when OOM error is encountered, reset at the end of AbortTransaction(). + */ +static bool in_oom_error = false; + static void write_syslog(int level, const char *line); #endif @@ -265,6 +274,22 @@ in_error_recursion_trouble(void) return (recursion_depth > 2); } +/* + * GPDB: + * Are we currently handling an OOM error? See in_oom_error comments. + */ +bool +in_oom_error_trouble(void) +{ + return in_oom_error; +} + +void +reset_oom_flag(void) +{ + in_oom_error = false; +} + /* * One of those fallback steps is to stop trying to localize the error * message, since there's a significant probability that that's exactly @@ -626,6 +651,12 @@ errfinish(int dummy __attribute__((unused)),...) CritSectionCount = 0; /* should be unnecessary, but... */ + if (edata->sqlerrcode == ERRCODE_GP_MEMPROT_KILL || + edata->sqlerrcode == ERRCODE_OUT_OF_MEMORY) + { + in_oom_error = true; + } + /* * Note that we leave CurrentMemoryContext set to ErrorContext. The * handler should reset it to something else soon. diff --git a/src/backend/utils/fmgr/test/dfmgr_test.c b/src/backend/utils/fmgr/test/dfmgr_test.c index abd529e695bb..cc5c927bdd50 100755 --- a/src/backend/utils/fmgr/test/dfmgr_test.c +++ b/src/backend/utils/fmgr/test/dfmgr_test.c @@ -68,6 +68,14 @@ errdetail_internal_impl(const char* fmt, ...) return 0; } +bool __wrap_in_oom_error_trouble(void); + +bool +__wrap_in_oom_error_trouble(void) +{ + return false; +} + #include "../dfmgr.c" #define EXPECT_EREPORT(LOG_LEVEL) \ diff --git a/src/backend/utils/gpmon/gpmon.c b/src/backend/utils/gpmon/gpmon.c index 96217a09a098..776f8c5756b4 100644 --- a/src/backend/utils/gpmon/gpmon.c +++ b/src/backend/utils/gpmon/gpmon.c @@ -16,6 +16,7 @@ #include "utils/guc.h" #include "utils/memutils.h" +#include "utils/builtins.h" #include "cdb/cdbtm.h" #include "cdb/cdbvars.h" @@ -222,6 +223,7 @@ void gpmon_qlog_packet_init(gpmon_packet_t *gpmonPacket) { const char *username = NULL; char *dbname = NULL; + const char *escaped_dbname = NULL; Assert(gp_enable_gpperfmon && Gp_role == GP_ROLE_DISPATCH); Assert(gpmonPacket); @@ -241,7 +243,15 @@ void gpmon_qlog_packet_init(gpmon_packet_t *gpmonPacket) /* DB Id */ dbname = get_database_name(MyDatabaseId); /* needs to be freed */ - snprintf(gpmonPacket->u.qlog.db, sizeof(gpmonPacket->u.qlog.db), "%s", dbname ? dbname : ""); + if (dbname) + escaped_dbname = quote_identifier(dbname); + snprintf(gpmonPacket->u.qlog.db, sizeof(gpmonPacket->u.qlog.db), "%s", + escaped_dbname ? escaped_dbname : ""); + if (escaped_dbname != dbname) + { + pfree((void *) escaped_dbname); + escaped_dbname = NULL; + } if(dbname) { pfree(dbname); diff --git a/src/backend/utils/init/postinit.c b/src/backend/utils/init/postinit.c index dc9610e818a0..06fc48ab9e22 100644 --- a/src/backend/utils/init/postinit.c +++ b/src/backend/utils/init/postinit.c @@ -1154,6 +1154,19 @@ InitPostgres(const char *in_dbname, Oid dboid, const char *username, (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE), errmsg("retrieve connection was not authenticated for unknown reason"))); InitRetrieveCtl(); + + if (IsResGroupEnabled()) + { + /* + * Initialize now-empty SessionState and apply resource group + * limits. + */ + + gp_session_id = RetrieveSessionId(); + + SessionState_Init(); + GPMemoryProtect_Init(); + } } /* diff --git a/src/backend/utils/misc/guc_gp.c b/src/backend/utils/misc/guc_gp.c index 5cbeea560258..cd3e218a7a27 100644 --- a/src/backend/utils/misc/guc_gp.c +++ b/src/backend/utils/misc/guc_gp.c @@ -233,6 +233,7 @@ bool gp_resource_group_cpu_ceiling_enforcement; double gp_resource_group_memory_limit; bool gp_resource_group_bypass; bool gp_resource_group_enable_recalculate_query_mem; +bool gp_resource_group_retrieve; /* Perfmon segment GUCs */ int gp_perfmon_segment_interval; @@ -482,6 +483,8 @@ bool gp_allow_date_field_width_5digits = false; bool gp_track_pending_delete = true; +bool gp_dispatch_drop_always = false; + /* GUC to set interval for streaming archival status */ int wal_sender_archiving_status_interval; @@ -1499,7 +1502,7 @@ struct config_bool ConfigureNamesBool_gp[] = }, { - {"test_AppendOnlyHash_eviction_vs_just_marking_not_inuse", PGC_SUSET, DEVELOPER_OPTIONS, + {"test_AppendOnlyHash_eviction_vs_just_marking_not_inuse", PGC_SUSET, DEPRECATED_OPTIONS, gettext_noop("Helps to test evicting the entry for AppendOnlyHash as soon as its usage is done instead of just marking it not inuse."), NULL, GUC_SUPERUSER_ONLY | GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE @@ -3434,6 +3437,28 @@ struct config_bool ConfigureNamesBool_gp[] = NULL, NULL, NULL }, + { + {"gp_dispatch_drop_always", PGC_USERSET, DEVELOPER_OPTIONS, + gettext_noop("Dispatch DROP if object doesn't exist on coordinator"), + NULL, + GUC_DISALLOW_IN_FILE | GUC_NO_SHOW_ALL | GUC_NOT_IN_SAMPLE + }, + &gp_dispatch_drop_always, + false, + NULL, NULL, NULL + }, + + { + {"gp_resource_group_retrieve", PGC_SIGHUP, RESOURCES, + gettext_noop("Activate resource groups for parallel retrieve cursor sessions."), + gettext_noop("When enabled, retrieve sessions use the same resource group as the " + "session that declared the parallel retrieve cursor, sharing slots and " + "enforcing resource limits.") + }, + &gp_resource_group_retrieve, + false, NULL, NULL, NULL + }, + /* End-of-list marker */ { {NULL, 0, 0, NULL, NULL}, NULL, false, NULL, NULL @@ -5546,7 +5571,11 @@ assign_pljava_classpath_insecure(bool newval, void *extra) static bool check_gp_resource_group_bypass(bool *newval, void **extra, GucSource source) { - if (!ResGroupIsAssigned()) + /* + * RETRIEVE cursor sessions exist only during a transaction. That means we + * can't really change the GUC while handler is alive. + */ + if (!ResGroupIsAssigned() && !am_cursor_retrieve_handler) return true; GUC_check_errmsg("SET gp_resource_group_bypass cannot run inside a transaction block"); diff --git a/src/backend/utils/mmgr/aset.c b/src/backend/utils/mmgr/aset.c index 8bfab3c5942e..e5add5855b0c 100644 --- a/src/backend/utils/mmgr/aset.c +++ b/src/backend/utils/mmgr/aset.c @@ -89,6 +89,7 @@ #include #include "postgres.h" +#include "utils/faultinjector.h" #include "utils/memdebug.h" #include "utils/memutils.h" #include "utils/memaccounting.h" @@ -1164,6 +1165,16 @@ AllocSetAllocImpl(MemoryContext context, Size size, bool isHeader) Size chunk_size; Size blksize; +#ifdef FAULT_INJECTOR + if (in_oom_error_trouble() && + CurrentMemoryContext != ErrorContext && + SIMPLE_FAULT_INJECTOR("fatal_on_palloc_oom") == FaultInjectorTypeSkip) + { + ereport(FATAL, (errmsg("memory allocated while handling an OOM error"), + errprintstack(true))); + } +#endif + AssertArg(AllocSetIsValid(set)); #ifdef USE_ASSERT_CHECKING if (IsUnderPostmaster && context != ErrorContext && mainthread() != 0 && !pthread_equal(main_tid, pthread_self())) @@ -1617,6 +1628,16 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size) AllocChunk chunk = AllocPointerGetChunk(pointer); Size oldsize = chunk->size; +#ifdef FAULT_INJECTOR + if (in_oom_error_trouble() && + CurrentMemoryContext != ErrorContext && + SIMPLE_FAULT_INJECTOR("fatal_on_palloc_oom") == FaultInjectorTypeSkip) + { + ereport(FATAL, + (errmsg("memory reallocated while handling an OOM error"), + errprintstack(true))); + } +#endif #ifdef USE_ASSERT_CHECKING if (IsUnderPostmaster && context != ErrorContext && mainthread() != 0 && !pthread_equal(main_tid, pthread_self())) { diff --git a/src/backend/utils/mmgr/runaway_cleaner.c b/src/backend/utils/mmgr/runaway_cleaner.c index 61b304332ce3..ca02e39ae19c 100644 --- a/src/backend/utils/mmgr/runaway_cleaner.c +++ b/src/backend/utils/mmgr/runaway_cleaner.c @@ -194,12 +194,23 @@ RunawayCleaner_StartCleanup() LWLockAcquire(ResGroupLock, LW_SHARED); ResGroupGetMemoryRunawayInfo(&str); LWLockRelease(ResGroupLock); - ereport(ERROR, (errmsg("Canceling query because of high VMEM usage. %s", str.data))); + ereport( + ERROR, + (errcode(ERRCODE_GP_MEMPROT_KILL), + errmsg("Canceling query because of high VMEM usage. %s", + str.data))); } else - ereport(ERROR, (errmsg("Canceling query because of high VMEM usage. Used: %dMB, available %dMB, red zone: %dMB", - VmemTracker_ConvertVmemChunksToMB(MySessionState->sessionVmem), VmemTracker_GetAvailableVmemMB(), - RedZoneHandler_GetRedZoneLimitMB()), errprintstack(true))); + ereport( + ERROR, + (errcode(ERRCODE_GP_MEMPROT_KILL), + errmsg( + "Canceling query because of high VMEM usage. Used: %dMB, available %dMB, red zone: %dMB", + VmemTracker_ConvertVmemChunksToMB( + MySessionState->sessionVmem), + VmemTracker_GetAvailableVmemMB(), + RedZoneHandler_GetRedZoneLimitMB()), + errprintstack(true))); } /* diff --git a/src/backend/utils/mmgr/test/memaccounting_test.c b/src/backend/utils/mmgr/test/memaccounting_test.c index ab5f4b7f7ceb..122913b8b9fe 100755 --- a/src/backend/utils/mmgr/test/memaccounting_test.c +++ b/src/backend/utils/mmgr/test/memaccounting_test.c @@ -50,6 +50,14 @@ int fwrite_mock(const char *data, Size size, Size count, FILE *file); void write_stderr_mock(const char *fmt,...); +bool __wrap_in_oom_error_trouble(void); + +bool +__wrap_in_oom_error_trouble(void) +{ + return false; +} + #include "../memaccounting.c" #include "utils/memaccounting_private.h" diff --git a/src/backend/utils/resgroup/resgroup.c b/src/backend/utils/resgroup/resgroup.c index 11210c214cd2..eeae85fa6d70 100644 --- a/src/backend/utils/resgroup/resgroup.c +++ b/src/backend/utils/resgroup/resgroup.c @@ -46,6 +46,7 @@ #include "cdb/cdbvars.h" #include "cdb/cdbdispatchresult.h" #include "cdb/cdbdisp_query.h" +#include "cdb/cdbendpoint.h" #include "cdb/memquota.h" #include "commands/resgroupcmds.h" #include "funcapi.h" @@ -977,6 +978,12 @@ ResGroupIsAssigned(void) return selfIsAssigned(); } +bool +ResGroupIsBypassed(void) +{ + return bypassedGroup != NULL; +} + /* * Get resource group id of my proc. * @@ -2626,10 +2633,8 @@ ShouldAssignResGroupOnMaster(void) bool ShouldUnassignResGroup(void) { - return IsResGroupActivated() && - IsNormalProcessingMode() && - (Gp_role == GP_ROLE_DISPATCH || Gp_role == GP_ROLE_EXECUTE) && - !AmIInSIGUSR1Handler(); + return IsResGroupActivated() && IsNormalProcessingMode() && + IsResGroupRoleAllowed() && !AmIInSIGUSR1Handler(); } /* @@ -2641,9 +2646,6 @@ ShouldUnassignResGroup(void) void AssignResGroupOnMaster(void) { - ResGroupSlotData *slot; - ResGroupInfo groupInfo; - Assert(Gp_role == GP_ROLE_DISPATCH); /* @@ -2652,6 +2654,8 @@ AssignResGroupOnMaster(void) */ if (shouldBypassQuery(debug_query_string)) { + ResGroupInfo groupInfo; + /* * Although we decide to bypass this query we should load the * memory_spill_ratio setting from the resgroup, otherwise a @@ -2680,6 +2684,9 @@ AssignResGroupOnMaster(void) bypassedSlot.memQuota = 0; bypassedSlot.memUsage = 0; + /* Share bypassed group id for RETRIEVE connections. */ + MySessionState->bypassResGroupId = groupInfo.groupId; + /* Attach self memory usage to resgroup */ groupIncMemUsage(bypassedGroup, &bypassedSlot, self->memUsage); @@ -2695,6 +2702,20 @@ AssignResGroupOnMaster(void) return; } + AttachResGroupSlot(); +} + +/* + * Acquire a slot from the resource group and attach the process to them. + */ +void +AttachResGroupSlot(void) +{ + ResGroupSlotData *slot; + ResGroupInfo groupInfo; + + Assert(Gp_role == GP_ROLE_DISPATCH); + PG_TRY(); { do { @@ -2753,6 +2774,12 @@ UnassignResGroup(void) bypassedSlot.groupId = InvalidOid; bypassedGroup = NULL; + /* Clear shared bypass group ID. */ + if (!am_cursor_retrieve_handler) + { + MySessionState->bypassResGroupId = InvalidOid; + } + /* Update pg_stat_activity statistics */ pgstat_report_resgroup(0, InvalidOid); return; @@ -2796,21 +2823,12 @@ UnassignResGroup(void) pgstat_report_resgroup(0, InvalidOid); } -/* - * QEs are not assigned/unassigned to a resource group on segments for each - * transaction, instead, they switch resource group when a new resource group - * id or slot id is dispatched. - */ -void -SwitchResGroupOnSegment(const char *buf, int len) +static void +SwitchResGroupImpl(ResGroupCaps caps, Oid newGroupId) { - Oid newGroupId; - ResGroupCaps caps; ResGroupData *group; ResGroupSlotData *slot; - DeserializeResGroupInfo(&caps, &newGroupId, buf, len); - /* * QD will dispatch the resgroup id via bypassedSlot.groupId * in bypass mode. @@ -2831,6 +2849,11 @@ SwitchResGroupOnSegment(const char *buf, int len) Assert(bypassedGroup != NULL); + if (!am_cursor_retrieve_handler) + { + MySessionState->bypassResGroupId = bypassedSlot.groupId; + } + /* Initialize the fake slot */ bypassedSlot.memQuota = 0; bypassedSlot.memUsage = 0; @@ -2840,6 +2863,9 @@ SwitchResGroupOnSegment(const char *buf, int len) /* Record the bypass memory limit of current query */ self->bypassMemoryLimit = self->memUsage + RESGROUP_BYPASS_MODE_MEMORY_LIMIT_ON_QE; + + pgstat_report_resgroup(0, bypassedSlot.groupId); + return; } @@ -2879,7 +2905,7 @@ SwitchResGroupOnSegment(const char *buf, int len) Assert(group != NULL); /* Init self */ - Assert(host_segments > 0); + Assert(host_segments > 0 || am_cursor_retrieve_handler); Assert(caps.concurrency > 0); self->caps = caps; @@ -2913,6 +2939,82 @@ SwitchResGroupOnSegment(const char *buf, int len) /* Add into cgroup */ ResGroupOps_AssignGroup(self->groupId, &(self->caps), MyProcPid); + + pgstat_report_resgroup(0, group->groupId); +} + +/* + * QEs are not assigned/unassigned to a resource group on segments for each + * transaction, instead, they switch resource group when a new resource group + * id or slot id is dispatched. + */ +void +SwitchResGroupOnSegment(const char *buf, int len) +{ + Oid newGroupId; + ResGroupCaps caps; + + DeserializeResGroupInfo(&caps, &newGroupId, buf, len); + + SwitchResGroupImpl(caps, newGroupId); +} + +/* + * Special path to activate resource group caps for RETRIEVE sessions. + */ +void +SwitchResGroupOnRetrieveSession(void) +{ + /* Both of these are not used when a group is to be bypassed. */ + ResGroupCaps caps = {0}; + Oid groupId = InvalidOid; + + const ResGroupSlotData *slot = MySessionState->resGroupSlot; + + Assert(am_cursor_retrieve_handler); + + if (MySessionState->bypassResGroupId != InvalidOid) + { + bypassedSlot.groupId = MySessionState->bypassResGroupId; + + SIMPLE_FAULT_INJECTOR("switch_resgroup_ppc_bypass"); + + LWLockAcquire(ResGroupLock, LW_EXCLUSIVE); + bypassedSlot.group = groupHashFind(bypassedSlot.groupId, true); + LWLockRelease(ResGroupLock); + } + else if (slot == NULL) + { + if (bypassedGroup != NULL) + { + /* Already in bypass mode. */ + Assert(bypassedGroup->groupId == bypassedSlot.groupId); + } + else + { + /* Cursor was closed while in bypass mode. */ + } + + return; + } + + if (slot != NULL) + { +#ifdef USE_ASSERT_CHECKING + /* + * We reach here even if cursor was closed on coordinator, to fail + * later. + */ + slotValidate(slot); +#endif + + SIMPLE_FAULT_INJECTOR("switch_resgroup_ppc"); + + caps = slot->caps; + groupId = slot->groupId; + } + + SwitchResGroupImpl(caps, groupId); } /* @@ -3789,8 +3891,6 @@ shouldBypassQuery(const char *query_string) MemoryContext oldcontext = NULL; MemoryContext tmpcontext = NULL; List *parsetree_list; - ListCell *parsetree_item; - Node *parsetree; bool bypass; if (gp_resource_group_bypass) @@ -3832,7 +3932,27 @@ shouldBypassQuery(const char *query_string) /* Only bypass SET/RESET/SHOW command and SELECT with only catalog tables * for now */ - bypass = true; + bypass = ShouldBypassQueryFromParseTree(parsetree_list); + + list_free_deep(parsetree_list); + + if (tmpcontext) + MemoryContextDelete(tmpcontext); + + return bypass; +} + +/* + * Should the query bypass the resgroup assignment? + * Basically SET/SHOW and SELECT from catalog tables + * are allowed to bypass. + */ +bool +ShouldBypassQueryFromParseTree(List *parsetree_list) +{ + ListCell *parsetree_item; + Node *parsetree; + foreach(parsetree_item, parsetree_list) { parsetree = (Node *) lfirst(parsetree_item); @@ -3840,25 +3960,15 @@ shouldBypassQuery(const char *query_string) if (IsA(parsetree, SelectStmt)) { if (!shouldBypassSelectQuery(parsetree)) - { - bypass = false; - break; - } + return false; } else if (nodeTag(parsetree) != T_VariableSetStmt && nodeTag(parsetree) != T_VariableShowStmt) { - bypass = false; - break; + return false; } } - - list_free_deep(parsetree_list); - - if (tmpcontext) - MemoryContextDelete(tmpcontext); - - return bypass; + return true; } /* @@ -4735,10 +4845,10 @@ HandleMoveResourceGroup(void) ResGroupSlotData *slot; ResGroupData *group; ResGroupData *oldGroup; - Oid groupId; + Oid groupId = InvalidOid; pid_t callerPid; - Assert(Gp_role == GP_ROLE_DISPATCH || Gp_role == GP_ROLE_EXECUTE); + Assert(IsResGroupRoleAllowed()); /* transaction has finished */ if (!IsTransactionState() || !selfIsAssigned()) @@ -4827,8 +4937,6 @@ HandleMoveResourceGroup(void) * transaction. */ ResGroupOps_AssignGroup(self->groupId, &(self->caps), MyProcPid); - - pgstat_report_resgroup(0, self->groupId); } /* @@ -4873,8 +4981,10 @@ HandleMoveResourceGroup(void) /* * Move segment's executor. Use simple manual counters manipulation. We * can't call same complex designed for coordinator functions like above. + * Move retrieve connection if am_cursor_retrieve_handler */ - else if (Gp_role == GP_ROLE_EXECUTE && !IS_QUERY_DISPATCHER()) + else if ((Gp_role == GP_ROLE_EXECUTE || am_cursor_retrieve_handler) && + !IS_QUERY_DISPATCHER()) { SpinLockAcquire(&MyProc->movetoMutex); groupId = MyProc->movetoGroupId; @@ -4930,6 +5040,8 @@ HandleMoveResourceGroup(void) /* Add into cgroup */ ResGroupOps_AssignGroup(self->groupId, &(self->caps), MyProcPid); } + + pgstat_report_resgroup(GetCurrentTimestamp(), groupId); } static bool diff --git a/src/backend/utils/resource_manager/resource_manager.c b/src/backend/utils/resource_manager/resource_manager.c index d3d3ff2c790b..3180094da7ad 100644 --- a/src/backend/utils/resource_manager/resource_manager.c +++ b/src/backend/utils/resource_manager/resource_manager.c @@ -15,6 +15,7 @@ #include "postgres.h" #include "cdb/cdbvars.h" +#include "cdb/cdbendpoint.h" #include "cdb/memquota.h" #include "executor/spi.h" #include "postmaster/fts.h" @@ -63,11 +64,9 @@ InitResManager(void) InitResQueues(); } - else if (IsResGroupEnabled() && - (Gp_role == GP_ROLE_DISPATCH || Gp_role == GP_ROLE_EXECUTE) && - IsUnderPostmaster && - !amAuxiliaryBgWorker() && - !am_walsender && !am_ftshandler && !am_faulthandler) + else if (IsResGroupEnabled() && IsResGroupRoleAllowed() && + IsUnderPostmaster && !amAuxiliaryBgWorker() && !am_walsender && + !am_ftshandler && !am_faulthandler) { /* * InitResManager() is called under PostgresMain(), so resource group is not @@ -98,8 +97,8 @@ InitResManager(void) SPI_InitMemoryReservation(); } - if (MySessionState && - !IsBackgroundWorker && - (Gp_role == GP_ROLE_DISPATCH || Gp_role == GP_ROLE_EXECUTE)) + if (MySessionState && !IsBackgroundWorker && IsResGroupRoleAllowed()) + { GPMemoryProtect_TrackStartupMemory(); + } } diff --git a/src/backend/utils/session_state.c b/src/backend/utils/session_state.c index 6e6e6bfb468d..25cedf13051f 100644 --- a/src/backend/utils/session_state.c +++ b/src/backend/utils/session_state.c @@ -19,6 +19,7 @@ #include "utils/memutils.h" #include "cdb/cdbvars.h" +#include "cdb/cdbendpoint.h" #include "miscadmin.h" #include "port/atomics.h" #include "storage/lwlock.h" @@ -101,6 +102,7 @@ SessionState_Acquire(int sessionId) acquired->idle_start = 0; acquired->latestCursorCommandId = 0; acquired->resGroupSlot = NULL; + acquired->bypassResGroupId = InvalidOid; #ifdef USE_ASSERT_CHECKING acquired->isModifiedSessionId = false; @@ -176,6 +178,7 @@ SessionState_Release(SessionState *acquired) acquired->latestCursorCommandId = 0; Assert(acquired->resGroupSlot == NULL); acquired->resGroupSlot = NULL; + acquired->bypassResGroupId = InvalidOid; #ifdef USE_ASSERT_CHECKING acquired->isModifiedSessionId = false; diff --git a/src/bin/gpfdist/gpfdist.c b/src/bin/gpfdist/gpfdist.c index af2fcd65ca76..a42f24897657 100644 --- a/src/bin/gpfdist/gpfdist.c +++ b/src/bin/gpfdist/gpfdist.c @@ -4697,6 +4697,7 @@ static int gpfdist_socket_send(const request_t *r, const void *buf, const size_t */ static int gpfdist_SSL_send(const request_t *r, const void *buf, const size_t buflen) { + errno = 0; /* Write the data to socket */ int n = BIO_write(r->io, buf, buflen); diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index 081289180c45..6498f5c440ea 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -2274,7 +2274,7 @@ setup_cdb_schema(void) /* Collect all files with .sql suffix in array. */ nscripts = 0; - while ((file = readdir(dir)) != NULL) + while (errno = 0, (file = readdir(dir)) != NULL) { int namelen = strlen(file->d_name); @@ -2296,9 +2296,7 @@ setup_cdb_schema(void) errno = 0; #endif - closedir(dir); - - if (errno != 0) + if (errno) { /* some kind of I/O error? */ printf(_("error while reading cdb_init.d directory: %s\n"), @@ -2307,6 +2305,8 @@ setup_cdb_schema(void) exit_nicely(); } + closedir(dir); + /* * Sort the array. This allows simple dependencies between scripts, by * naming them like "01_before.sql" and "02_after.sql" diff --git a/src/bin/pg_controldata/pg_controldata.c b/src/bin/pg_controldata/pg_controldata.c index 97ea43aa22f2..ecc5eb10acc6 100644 --- a/src/bin/pg_controldata/pg_controldata.c +++ b/src/bin/pg_controldata/pg_controldata.c @@ -146,6 +146,7 @@ main(int argc, char *argv[]) exit(2); } + errno = 0; if (read(fd, &ControlFile, sizeof(ControlFileData)) != sizeof(ControlFileData)) { fprintf(stderr, _("%s: could not read file \"%s\": %s\n"), diff --git a/src/bin/pg_rewind/file_ops.c b/src/bin/pg_rewind/file_ops.c index a8eb04846571..d331d61c8e94 100644 --- a/src/bin/pg_rewind/file_ops.c +++ b/src/bin/pg_rewind/file_ops.c @@ -348,6 +348,7 @@ slurpFile(const char *datadir, const char *path, size_t *filesize) buffer = pg_malloc(len + 1); + errno = 0; if (read(fd, buffer, len) != len) pg_fatal("could not read file \"%s\": %s\n", fullpath, strerror(errno)); diff --git a/src/bin/pg_rewind/parsexlog.c b/src/bin/pg_rewind/parsexlog.c index 673f6d3bcea1..490f4e8b8a36 100644 --- a/src/bin/pg_rewind/parsexlog.c +++ b/src/bin/pg_rewind/parsexlog.c @@ -291,6 +291,7 @@ SimpleXLogPageRead(XLogReaderState *xlogreader, XLogRecPtr targetPagePtr, return -1; } + errno = 0; if (read(xlogreadfd, readBuf, XLOG_BLCKSZ) != XLOG_BLCKSZ) { printf(_("could not read from file \"%s\": %s\n"), xlogfpath, diff --git a/src/include/access/aocssegfiles.h b/src/include/access/aocssegfiles.h index 99937ebbae24..2032f5fcdb83 100644 --- a/src/include/access/aocssegfiles.h +++ b/src/include/access/aocssegfiles.h @@ -137,7 +137,6 @@ extern AOCSFileSegInfo *GetAOCSFileSegInfo(Relation prel, Snapshot appendOnlyMetaDataSnapshot, int32 segno); - extern AOCSFileSegInfo **GetAllAOCSFileSegInfo(Relation prel, Snapshot appendOnlyMetaDataSnapshot, int *totalseg); diff --git a/src/include/cdb/cdbdisp.h b/src/include/cdb/cdbdisp.h index 3f8febafe550..941bba27b3a1 100644 --- a/src/include/cdb/cdbdisp.h +++ b/src/include/cdb/cdbdisp.h @@ -50,6 +50,7 @@ typedef struct CdbDispatcherState #ifdef USE_ASSERT_CHECKING bool isGangDestroying; #endif + bool destroyIdleReaderGang; } CdbDispatcherState; typedef struct DispatcherInternalFuncs diff --git a/src/include/cdb/cdbendpoint.h b/src/include/cdb/cdbendpoint.h index 155e185a7ea1..339d3ccd7837 100644 --- a/src/include/cdb/cdbendpoint.h +++ b/src/include/cdb/cdbendpoint.h @@ -30,6 +30,8 @@ #include "executor/tqueue.h" #include "storage/shm_toc.h" #include "nodes/execnodes.h" +#include "utils/resgroup.h" +#include "utils/resource_manager.h" /* * Endpoint allocate positions. @@ -57,6 +59,10 @@ enum EndPointExecPosition #define ENDPOINT_READY_ACK_MSG "ENDPOINT_READY" #define ENDPOINT_FINISHED_ACK_MSG "ENDPOINT_FINISHED" +#define ShouldUseRetrieveResGroup() \ + (am_cursor_retrieve_handler && gp_resource_group_retrieve && \ + IsResGroupActivated()) + /* * Endpoint attach status, used by parallel retrieve cursor. */ @@ -160,10 +166,12 @@ extern bool AuthEndpoint(Oid userID, const char *tokenStr); extern TupleDesc GetRetrieveStmtTupleDesc(const RetrieveStmt *stmt); extern void ExecRetrieveStmt(const RetrieveStmt *stmt, DestReceiver *dest); extern void check_parallel_retrieve_cursor_errors(EState *estate); +extern int RetrieveSessionId(void); /* Endpoint shared memory utility functions in "cdbendpoint.c" */ extern Endpoint *get_endpointdesc_by_index(int index); extern void get_token_from_session_hashtable(int sessionId, Oid userID, int8 *token /* out */ ); +extern bool sharedEndpointsContain(int receiverPid, int sessionId); /* utility functions in "cdbendpointutilities.c" */ extern void endpoint_token_str2arr(const char *tokenStr, int8 *token); diff --git a/src/include/optimizer/subselect.h b/src/include/optimizer/subselect.h index ac51a2d96c15..b713dc830214 100644 --- a/src/include/optimizer/subselect.h +++ b/src/include/optimizer/subselect.h @@ -50,6 +50,7 @@ extern void check_multi_subquery_correlated(PlannerInfo *root, Var *var); extern List *generate_subquery_vars(PlannerInfo *root, List *tlist, Index varno); extern bool QueryHasDistributedRelation(Query *q, bool recursive); +extern bool QueryHasMasterOnlyRelation(Query *q); extern bool cte_contains_dml(Node *ctequery, PlannerInfo *root); diff --git a/src/include/storage/smgr.h b/src/include/storage/smgr.h index eca15813302a..31354c8bbe88 100644 --- a/src/include/storage/smgr.h +++ b/src/include/storage/smgr.h @@ -63,12 +63,14 @@ typedef struct SMgrRelationData /* additional public fields may someday exist here */ + /* Obsolete storage manager selector, should not be used for any particular purpose */ + /* In GGDB, this field is used to store the table type: Heap or AO . */ + int smgr_which; + /* * Fields below here are intended to be private to smgr.c and its * submodules. Do not touch them from elsewhere. */ - /* Obsolete storage manager selector, should not be used for any particular purpose */ - int smgr_which; /* for md.c; NULL for forks that are not open */ struct _MdfdVec *md_fd[MAX_FORKNUM + 1]; diff --git a/src/include/utils/elog.h b/src/include/utils/elog.h index 7399945928ae..f048009a594a 100644 --- a/src/include/utils/elog.h +++ b/src/include/utils/elog.h @@ -599,6 +599,9 @@ extern void DebugFileOpen(void); extern char *unpack_sql_state(int sql_state); extern bool in_error_recursion_trouble(void); +extern bool in_oom_error_trouble(void); +extern void reset_oom_flag(void); + #ifdef HAVE_SYSLOG extern void set_syslog_parameters(const char *ident, int facility); #endif diff --git a/src/include/utils/guc.h b/src/include/utils/guc.h index 712fd7bc6557..188c36555b61 100644 --- a/src/include/utils/guc.h +++ b/src/include/utils/guc.h @@ -604,6 +604,8 @@ extern bool gp_allow_date_field_width_5digits; extern bool gp_track_pending_delete; +extern bool gp_dispatch_drop_always; + typedef enum { INDEX_CHECK_NONE, diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 24d39757f4cc..308b181565bc 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -451,6 +451,9 @@ typedef struct ViewOptions #define RelationIsMapped(relation) \ ((relation)->rd_rel->relfilenode == InvalidOid) +#define RelationStorageIsAO(relation) \ + (RelationIsAoRows(relation) || RelationIsAoCols(relation)) + /* * RelationOpenSmgr * Open the relation at the smgr level, if not already done. @@ -458,7 +461,10 @@ typedef struct ViewOptions #define RelationOpenSmgr(relation) \ do { \ if ((relation)->rd_smgr == NULL) \ - smgrsetowner(&((relation)->rd_smgr), smgropen((relation)->rd_node, (relation)->rd_backend)); \ + { \ + smgrsetowner(&((relation)->rd_smgr), smgropen((relation)->rd_node, (relation)->rd_backend)); \ + (relation)->rd_smgr->smgr_which = RelationStorageIsAO(relation) ? RELSTORAGE_AOROWS : RELSTORAGE_HEAP; \ + } \ } while (0) /* diff --git a/src/include/utils/resgroup.h b/src/include/utils/resgroup.h index c20bc8674cc0..f2680269b5c7 100644 --- a/src/include/utils/resgroup.h +++ b/src/include/utils/resgroup.h @@ -107,6 +107,7 @@ extern bool gp_resource_group_bypass; extern int gp_resource_group_queuing_timeout; extern bool gp_resource_group_bypass_catalog_query; extern int gp_resource_group_move_timeout; +extern bool gp_resource_group_retrieve; /* * Non-GUC global variables. @@ -168,11 +169,15 @@ extern void DeserializeResGroupInfo(struct ResGroupCaps *capsOut, extern bool ShouldAssignResGroupOnMaster(void); extern bool ShouldUnassignResGroup(void); +extern bool ShouldBypassQueryFromParseTree(List *parse_tree); +extern void AttachResGroupSlot(void); extern void AssignResGroupOnMaster(void); extern void UnassignResGroup(void); extern void SwitchResGroupOnSegment(const char *buf, int len); +extern void SwitchResGroupOnRetrieveSession(void); extern bool ResGroupIsAssigned(void); +extern bool ResGroupIsBypassed(void); /* Retrieve statistic information of type from resource group */ extern Datum ResGroupGetStat(Oid groupId, ResGroupStatType type); diff --git a/src/include/utils/resource_manager.h b/src/include/utils/resource_manager.h index 007c93f23673..be0d939f272e 100644 --- a/src/include/utils/resource_manager.h +++ b/src/include/utils/resource_manager.h @@ -37,6 +37,10 @@ #define IsResGroupActivated() \ (ResGroupActivated) +#define IsResGroupRoleAllowed() \ + (Gp_role == GP_ROLE_DISPATCH || Gp_role == GP_ROLE_EXECUTE || \ + am_cursor_retrieve_handler) + typedef enum { RESOURCE_MANAGER_POLICY_QUEUE, diff --git a/src/include/utils/session_state.h b/src/include/utils/session_state.h index 230c19c8e28f..3c2e325720a3 100644 --- a/src/include/utils/session_state.h +++ b/src/include/utils/session_state.h @@ -99,6 +99,12 @@ typedef struct SessionState /* MyProc->queryCommandId of the latest cursor command in this session */ int latestCursorCommandId; + /* + * When gp_resource_group_bypass is enabled, stores the bypass group ID + * so retrieve sessions can grab it from the backend holding the cursor. + */ + Oid bypassResGroupId; + #ifdef USE_ASSERT_CHECKING /* If we modify the sessionId in ProcMppSessionId, this field is turned on */ bool isModifiedSessionId; diff --git a/src/include/utils/unsync_guc_name.h b/src/include/utils/unsync_guc_name.h index 1dcad86fcc01..8f5151eb3af1 100644 --- a/src/include/utils/unsync_guc_name.h +++ b/src/include/utils/unsync_guc_name.h @@ -247,6 +247,7 @@ "gp_resource_group_queuing_timeout", "gp_resource_group_enable_recalculate_query_mem", "gp_resource_group_move_timeout", + "gp_resource_group_retrieve", "gp_resource_manager", "gp_resqueue_memory_policy", "gp_resqueue_priority", @@ -566,3 +567,4 @@ "xmloption", "zero_damaged_pages", "gp_track_pending_delete", + "gp_dispatch_drop_always", diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c index 9979a60b9e7a..5a175ab64a2a 100644 --- a/src/interfaces/libpq/fe-connect.c +++ b/src/interfaces/libpq/fe-connect.c @@ -109,13 +109,31 @@ int getpeereid(int, uid_t *__restrict__, gid_t *__restrict__); * than looking into errcodes.h since it reflects historical behavior * rather than that of the current code. */ +#ifdef ERRCODE_APPNAME_UNKNOWN +#undef ERRCODE_APPNAME_UNKNOWN +#endif + #define ERRCODE_APPNAME_UNKNOWN "42704" /* This is part of the protocol so just define it */ +#ifdef ERRCODE_INVALID_PASSWORD +#undef ERRCODE_INVALID_PASSWORD +#endif + #define ERRCODE_INVALID_PASSWORD "28P01" + /* This too */ +#ifdef ERRCODE_CANNOT_CONNECT_NOW +#undef ERRCODE_CANNOT_CONNECT_NOW +#endif + #define ERRCODE_CANNOT_CONNECT_NOW "57P03" + /* And this GPDB-specific one, too */ +#ifdef ERRCODE_MIRROR_READY +#undef ERRCODE_MIRROR_READY +#endif + #define ERRCODE_MIRROR_READY "57M02" /* diff --git a/src/interfaces/libpq/fe-exec.c b/src/interfaces/libpq/fe-exec.c index f13c18bad621..bf4f7871e96a 100644 --- a/src/interfaces/libpq/fe-exec.c +++ b/src/interfaces/libpq/fe-exec.c @@ -151,7 +151,7 @@ PQmakeEmptyPGresult(PGconn *conn, ExecStatusType status) { PGresult *result; - result = (PGresult *) malloc(sizeof(PGresult)); + result = (PGresult *) pqPalloc(sizeof(PGresult)); if (!result) return NULL; @@ -407,7 +407,7 @@ dupEvents(PGEvent *events, int count) if (!events || count <= 0) return NULL; - newEvents = (PGEvent *) malloc(count * sizeof(PGEvent)); + newEvents = (PGEvent *) pqPalloc(count * sizeof(PGEvent)); if (!newEvents) return NULL; @@ -417,12 +417,12 @@ dupEvents(PGEvent *events, int count) newEvents[i].passThrough = events[i].passThrough; newEvents[i].data = NULL; newEvents[i].resultInitialized = FALSE; - newEvents[i].name = strdup(events[i].name); + newEvents[i].name = pqPstrdup(events[i].name); if (!newEvents[i].name) { while (--i >= 0) - free(newEvents[i].name); - free(newEvents); + pqPfree(newEvents[i].name); + pqPfree(newEvents); return NULL; } } @@ -585,7 +585,7 @@ pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary) */ if (nBytes >= PGRESULT_SEP_ALLOC_THRESHOLD) { - block = (PGresult_data *) malloc(nBytes + PGRESULT_BLOCK_OVERHEAD); + block = (PGresult_data *) pqPalloc(nBytes + PGRESULT_BLOCK_OVERHEAD); if (!block) return NULL; space = block->space + PGRESULT_BLOCK_OVERHEAD; @@ -609,7 +609,7 @@ pqResultAlloc(PGresult *res, size_t nBytes, bool isBinary) } /* Otherwise, start a new block. */ - block = (PGresult_data *) malloc(PGRESULT_DATA_BLOCKSIZE); + block = (PGresult_data *) pqPalloc(PGRESULT_DATA_BLOCKSIZE); if (!block) return NULL; block->next = res->curBlock; @@ -709,18 +709,18 @@ PQclear(PGresult *res) } if (res->events) - free(res->events); + pqPfree(res->events); /* Free all the subsidiary blocks */ while ((block = res->curBlock) != NULL) { res->curBlock = block->next; - free(block); + pqPfree(block); } /* Free the top-level tuple pointer array */ if (res->tuples) - free(res->tuples); + pqPfree(res->tuples); /* zero out the pointer fields to catch programming errors */ res->attDescs = NULL; @@ -732,20 +732,20 @@ PQclear(PGresult *res) /* res->curBlock was zeroed out earlier */ if (res->extras) - free(res->extras); + pqPfree(res->extras); res->extraslen = 0; res->extras = NULL; if (res->aotupcounts) - free(res->aotupcounts); + pqPfree(res->aotupcounts); res->naotupcounts = 0; if (res->waitGxids) - free(res->waitGxids); + pqPfree(res->waitGxids); res->waitGxids = NULL; res->nWaits = 0; /* Free the PGresult structure itself */ - free(res); + pqPfree(res); } /* @@ -951,10 +951,10 @@ pqAddTuple(PGresult *res, PGresAttValue *tup, const char **errmsgp) if (res->tuples == NULL) newTuples = (PGresAttValue **) - malloc(newSize * sizeof(PGresAttValue *)); + pqPalloc(newSize * sizeof(PGresAttValue *)); else newTuples = (PGresAttValue **) - realloc(res->tuples, newSize * sizeof(PGresAttValue *)); + pqRepalloc(res->tuples, newSize * sizeof(PGresAttValue *)); if (!newTuples) return FALSE; /* malloc or realloc failed */ res->tupArrSize = newSize; diff --git a/src/interfaces/libpq/fe-lobj.c b/src/interfaces/libpq/fe-lobj.c index a8c01a8e3889..d1e3261d2b30 100644 --- a/src/interfaces/libpq/fe-lobj.c +++ b/src/interfaces/libpq/fe-lobj.c @@ -785,6 +785,7 @@ lo_export(PGconn *conn, Oid lobjId, const char *filename) */ while ((nbytes = lo_read(conn, lobj, buf, LO_BUFSIZE)) > 0) { + errno = 0; tmp = write(fd, buf, nbytes); if (tmp != nbytes) { diff --git a/src/interfaces/libpq/fe-protocol3.c b/src/interfaces/libpq/fe-protocol3.c index c311a7ccbd31..25a0c731c168 100644 --- a/src/interfaces/libpq/fe-protocol3.c +++ b/src/interfaces/libpq/fe-protocol3.c @@ -267,7 +267,7 @@ pqParseInput3(PGconn *conn) /* now just loop through */ conn->result->aotupcounts = - malloc(sizeof(PQaoRelTupCount) * conn->result->naotupcounts); + pqPalloc(sizeof(PQaoRelTupCount) * conn->result->naotupcounts); ao = conn->result->aotupcounts; for (i = 0; i < conn->result->naotupcounts; i++) { @@ -529,7 +529,7 @@ pqParseInput3(PGconn *conn) if (pqGetInt(&conn->result->extraslen, 4, conn)) return; - conn->result->extras = malloc(conn->result->extraslen); + conn->result->extras = pqPalloc(conn->result->extraslen); if (pqGetnchar((char *)conn->result->extras, conn->result->extraslen, conn)) return; conn->asyncStatus = PGASYNC_READY; @@ -555,7 +555,7 @@ pqParseInput3(PGconn *conn) { if (conn->result->waitGxids == NULL) conn->result->waitGxids = - malloc(sizeof(int) * conn->result->nWaits); + pqPalloc(sizeof(int) * conn->result->nWaits); for (i = 0; i < conn->result->nWaits; i++) { int gxid; diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h index 8f17aa323721..cb0c11f534ea 100644 --- a/src/interfaces/libpq/libpq-int.h +++ b/src/interfaces/libpq/libpq-int.h @@ -83,6 +83,34 @@ typedef struct #endif #endif /* USE_SSL */ +/* + * Definitions meant to lessen the malloc() usage for CDB routines in + * server-sided code for struct PGresult allocations. + */ +#ifndef FRONTEND +#include "postgres.h" +#include "utils/memutils.h" + +/* + * TopTransactionContext's lifetime lasts until the end of the current query, + * which does the job well for backends. Auxiliary processes do not set + * transaction contexts, so we have to use TopMemoryContext to achieve a + * lifetime equivalent to malloc(). + */ +#define PQ_PALLOC_CONTEXT \ + ((TopTransactionContext != NULL) ? TopTransactionContext : TopMemoryContext) + +#define pqPalloc(sz) MemoryContextAlloc(PQ_PALLOC_CONTEXT, sz) +#define pqPstrdup(x) MemoryContextStrdup(PQ_PALLOC_CONTEXT, x) +#define pqRepalloc(x, sz) repalloc(x, sz) +#define pqPfree(x) pfree(x) +#else +#define pqPalloc(sz) malloc(sz) +#define pqPstrdup(x) strdup(x) +#define pqRepalloc(x, sz) realloc(x, sz) +#define pqPfree(x) free(x) +#endif + /* * POSTGRES backend dependent Constants. */ diff --git a/src/pl/plpython/plpython.h b/src/pl/plpython/plpython.h index e438bc27e650..275c6f111fee 100644 --- a/src/pl/plpython/plpython.h +++ b/src/pl/plpython/plpython.h @@ -120,9 +120,6 @@ typedef int Py_ssize_t; #undef TEXTDOMAIN #define TEXTDOMAIN PG_TEXTDOMAIN("plpython") -#include -#include - /* put back our snprintf and vsnprintf */ #ifdef USE_REPL_SNPRINTF #ifdef snprintf diff --git a/src/test/isolation/expected/ao-insert-eof.out b/src/test/isolation/expected/ao-insert-eof.out index 52a13404b320..7aa0318fc76e 100644 --- a/src/test/isolation/expected/ao-insert-eof.out +++ b/src/test/isolation/expected/ao-insert-eof.out @@ -1,8 +1,7 @@ Parsed test spec with 2 sessions -starting permutation: s1begin s1setguc s1insert s2begin s2select s1commit s2insert s2commit s2select +starting permutation: s1begin s1insert s2begin s2select s1commit s2insert s2commit s2select step s1begin: BEGIN; -step s1setguc: SET test_AppendOnlyHash_eviction_vs_just_marking_not_inuse=1; step s1insert: INSERT INTO appendonly_eof SELECT * FROM generate_series(1, 1000); step s2begin: BEGIN ISOLATION LEVEL SERIALIZABLE; step s2select: SELECT count(*) from appendonly_eof; diff --git a/src/test/isolation/specs/ao-insert-eof.spec b/src/test/isolation/specs/ao-insert-eof.spec index 58d70e552b09..d9c3aa47f7d2 100644 --- a/src/test/isolation/specs/ao-insert-eof.spec +++ b/src/test/isolation/specs/ao-insert-eof.spec @@ -22,7 +22,6 @@ setup session "s1" step "s1begin" { BEGIN; } -step "s1setguc" { SET test_AppendOnlyHash_eviction_vs_just_marking_not_inuse=1; } step "s1insert" { INSERT INTO appendonly_eof SELECT * FROM generate_series(1, 1000); } step "s1commit" { COMMIT; } @@ -33,4 +32,4 @@ step "s2insert" { INSERT INTO appendonly_eof SELECT * FROM generate_series(1, 1 step "s2commit" { COMMIT; } -permutation "s1begin" "s1setguc" "s1insert" "s2begin" "s2select" "s1commit" "s2insert" "s2commit" "s2select" +permutation "s1begin" "s1insert" "s2begin" "s2select" "s1commit" "s2insert" "s2commit" "s2select" diff --git a/src/test/isolation2/.gitignore b/src/test/isolation2/.gitignore index 8ad72bb1d222..027f9dfd3dfd 100644 --- a/src/test/isolation2/.gitignore +++ b/src/test/isolation2/.gitignore @@ -31,3 +31,8 @@ sql/idle_gang_cleaner.sql # Generated subdirectories /results/ +/parallelretrcursor/ +/resgroup/ +/ic_tcp/ +/ic_proxy/ +/mirrorless/ diff --git a/src/test/isolation2/Makefile b/src/test/isolation2/Makefile index b192a86db3b4..dfb61d2b2593 100644 --- a/src/test/isolation2/Makefile +++ b/src/test/isolation2/Makefile @@ -20,7 +20,7 @@ endif override CPPFLAGS := -I$(srcdir) -I$(libpq_srcdir) -I$(srcdir)/../regress $(CPPFLAGS) override LDLIBS := $(libpq_pgport) $(LDLIBS) -all: test_python pg_isolation2_regress$(X) all-lib data scan_flaky_fault_injectors test_parallel_retrieve_cursor_extended_query test_parallel_retrieve_cursor_extended_query_error +all: pg_isolation2_regress$(X) all-lib data scan_flaky_fault_injectors test_parallel_retrieve_cursor_extended_query test_parallel_retrieve_cursor_extended_query_error test_python: python helpers_test.py @@ -53,6 +53,8 @@ explain.pm: data: rm -f $@ && $(LN_S) $(top_builddir)/src/test/regress/data +isolation2_regress.o: submake-libpgport + .PHONY: scan_flaky_fault_injectors scan_flaky_fault_injectors: $(top_builddir)/src/test/regress/scan_flaky_fault_injectors.sh @@ -63,30 +65,47 @@ pg_isolation2_regress$(X): isolation2_main.o pg_regress.o submake-libpgport subm clean distclean: rm -f pg_isolation2_regress$(X) $(OBJS) isolation2_main.o isolation2_regress.so rm -f pg_regress.o test_parallel_retrieve_cursor_extended_query test_parallel_retrieve_cursor_extended_query_error - rm -f gpstringsubs.pl gpdiff.pl atmsort.pm explain.pm + rm -f gpstringsubs.pl gpdiff.pl GPTest.pm atmsort.pm explain.pm rm -f data rm -rf $(pg_regress_clean_files) install: all gpdiff.pl gpstringsubs.pl - -installcheck: install installcheck-parallel-retrieve-cursor installcheck-ic-tcp installcheck-ic-proxy - ./pg_isolation2_regress $(EXTRA_REGRESS_OPTS) --init-file=$(top_builddir)/src/test/regress/init_file --init-file=./init_file_isolation2 --psqldir='$(PSQLDIR)' --inputdir=$(srcdir) --schedule=$(srcdir)/isolation2_schedule - -installcheck-resgroup: install - ./pg_isolation2_regress $(EXTRA_REGRESS_OPTS) --init-file=$(top_builddir)/src/test/regress/init_file --init-file=./init_file_resgroup --psqldir='$(PSQLDIR)' --inputdir=$(srcdir) --dbname=isolation2resgrouptest --schedule=$(srcdir)/isolation2_resgroup_schedule - -installcheck-parallel-retrieve-cursor: install - ./pg_isolation2_regress $(EXTRA_REGRESS_OPTS) --init-file=$(top_builddir)/src/test/regress/init_file --init-file=./init_file_parallel_retrieve_cursor --psqldir='$(PSQLDIR)' --inputdir=$(srcdir) --dbname=isolation2parallelretrcursor --load-extension=gp_inject_fault --schedule=$(srcdir)/parallel_retrieve_cursor_schedule - -installcheck-mirrorless: install - ./pg_isolation2_regress $(EXTRA_REGRESS_OPTS) --init-file=$(top_builddir)/src/test/regress/init_file --init-file=./init_file_isolation2 --schedule=$(srcdir)/mirrorless_schedule --dbname=isolation2-mirrorless --load-extension=gp_inject_fault - -installcheck-ic-tcp: install + $(MKDIR_P) '$(DESTDIR)$(pgxsdir)/$(subdir)' + $(INSTALL_PROGRAM) pg_isolation2_regress$(X) '$(DESTDIR)$(pgxsdir)/$(subdir)/pg_isolation2_regress$(X)' + $(INSTALL_PROGRAM) sql_isolation_testcase.py '$(DESTDIR)$(pgxsdir)/$(subdir)/sql_isolation_testcase.py' + $(LN_S) -f '$(DESTDIR)$(pgxsdir)/src/test/regress/gpdiff.pl' '$(DESTDIR)$(pgxsdir)/$(subdir)/gpdiff.pl' + $(LN_S) -f '$(DESTDIR)$(pgxsdir)/src/test/regress/gpstringsubs.pl' '$(DESTDIR)$(pgxsdir)/$(subdir)/gpstringsubs.pl' + $(LN_S) -f '$(DESTDIR)$(pgxsdir)/src/test/regress/GPTest.pm' '$(DESTDIR)$(pgxsdir)/$(subdir)/GPTest.pm' + $(LN_S) -f '$(DESTDIR)$(pgxsdir)/src/test/regress/atmsort.pm' '$(DESTDIR)$(pgxsdir)/$(subdir)/atmsort.pm' + $(LN_S) -f '$(DESTDIR)$(pgxsdir)/src/test/regress/explain.pm' '$(DESTDIR)$(pgxsdir)/$(subdir)/explain.pm' + +uninstall: + rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/pg_isolation2_regress$(X)' + rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/sql_isolation_testcase.py' + rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/gpdiff.pl' + rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/gpstringsubs.pl' + rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/GPTest.pm' + rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/atmsort.pm' + rm -f '$(DESTDIR)$(pgxsdir)/$(subdir)/explain.pm' + +installcheck: test_python installcheck-parallel-retrieve-cursor installcheck-ic-tcp installcheck-ic-proxy + $(pg_isolation2_regress_installcheck) --init-file=$(top_builddir)/src/test/regress/init_file --init-file=./init_file_isolation2 --schedule=$(srcdir)/isolation2_schedule + +installcheck-resgroup: all-lib data + $(pg_isolation2_regress_installcheck) --init-file=$(top_builddir)/src/test/regress/init_file --init-file=./init_file_resgroup --dbname=isolation2resgrouptest --outputdir=resgroup --schedule=$(srcdir)/isolation2_resgroup_schedule + +installcheck-parallel-retrieve-cursor: all-lib data test_parallel_retrieve_cursor_extended_query test_parallel_retrieve_cursor_extended_query_error + $(pg_isolation2_regress_installcheck) --init-file=$(top_builddir)/src/test/regress/init_file --init-file=./init_file_parallel_retrieve_cursor --dbname=isolation2parallelretrcursor --outputdir=parallelretrcursor --load-extension=gp_inject_fault --schedule=$(srcdir)/parallel_retrieve_cursor_schedule + +installcheck-mirrorless: all-lib data + $(pg_isolation2_regress_installcheck) --init-file=$(top_builddir)/src/test/regress/init_file --init-file=./init_file_isolation2 --schedule=$(srcdir)/mirrorless_schedule --outputdir=mirrorless --dbname=isolation2-mirrorless --load-extension=gp_inject_fault + +installcheck-ic-tcp: all-lib data ifeq ($(findstring gp_interconnect_type=tcp,$(PGOPTIONS)),gp_interconnect_type=tcp) - ./pg_isolation2_regress $(EXTRA_REGRESS_OPTS) --init-file=$(top_builddir)/src/test/regress/init_file --init-file=./init_file_isolation2 --psqldir='$(PSQLDIR)' --inputdir=$(srcdir) --load-extension=gp_inject_fault --schedule=$(srcdir)/isolation2_ic_tcp_schedule + $(pg_isolation2_regress_installcheck) --init-file=$(top_builddir)/src/test/regress/init_file --init-file=./init_file_isolation2 --outputdir=ic_tcp --load-extension=gp_inject_fault --schedule=$(srcdir)/isolation2_ic_tcp_schedule endif -installcheck-ic-proxy: install +installcheck-ic-proxy: all-lib data ifeq ($(findstring gp_interconnect_type=proxy,$(PGOPTIONS)),gp_interconnect_type=proxy) - ./pg_isolation2_regress $(EXTRA_REGRESS_OPTS) --init-file=$(top_builddir)/src/test/regress/init_file --init-file=./init_file_isolation2 --psqldir='$(PSQLDIR)' --inputdir=$(srcdir) --load-extension=gp_inject_fault --schedule=$(srcdir)/isolation2_ic_proxy_schedule + $(pg_isolation2_regress_installcheck) --init-file=$(top_builddir)/src/test/regress/init_file --init-file=./init_file_isolation2 --outputdir=ic_proxy --load-extension=gp_inject_fault --schedule=$(srcdir)/isolation2_ic_proxy_schedule endif diff --git a/src/test/isolation2/expected/drop_rename.out b/src/test/isolation2/expected/drop_rename.out index af0916cb2939..db6e14d0a75f 100644 --- a/src/test/isolation2/expected/drop_rename.out +++ b/src/test/isolation2/expected/drop_rename.out @@ -110,3 +110,85 @@ DROP ERROR: relation "t3" does not exist LINE 1: select count(*) from t3; ^ + +-- Ensure DROP doesn't make inconsistency +-- start_ignore +drop table if exists t4; +DROP +-- end_ignore +select gp_inject_fault('wait_before_drop_dispatch', 'suspend', 1); + gp_inject_fault +----------------- + Success: +(1 row) +1&:drop table if exists t4; +create table t4 (a int, b text) distributed by (a); +CREATE +select gp_wait_until_triggered_fault('wait_before_drop_dispatch', 1, 1); + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) +select gp_inject_fault('wait_before_drop_dispatch', 'reset', 1); + gp_inject_fault +----------------- + Success: +(1 row) +1<: <... completed> +DROP +drop table t4; +DROP + +-- start_ignore +drop type if exists t5; +DROP +-- end_ignore +select gp_inject_fault('wait_before_drop_dispatch', 'suspend', 1); + gp_inject_fault +----------------- + Success: +(1 row) +1&:drop type if exists t5; +create type t5 as (a int, b text); +CREATE +select gp_wait_until_triggered_fault('wait_before_drop_dispatch', 1, 1); + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) +select gp_inject_fault('wait_before_drop_dispatch', 'reset', 1); + gp_inject_fault +----------------- + Success: +(1 row) +1<: <... completed> +DROP +drop type t5; +DROP + +-- start_ignore +drop schema if exists t6; +DROP +-- end_ignore +select gp_inject_fault('wait_before_drop_dispatch', 'suspend', 1); + gp_inject_fault +----------------- + Success: +(1 row) +1&:drop schema if exists t6; +create schema t6; +CREATE +select gp_wait_until_triggered_fault('wait_before_drop_dispatch', 1, 1); + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) +select gp_inject_fault('wait_before_drop_dispatch', 'reset', 1); + gp_inject_fault +----------------- + Success: +(1 row) +1<: <... completed> +DROP +drop schema t6; +DROP diff --git a/src/test/isolation2/expected/fts_segment_reset.out b/src/test/isolation2/expected/fts_segment_reset.out index 206880fb48b4..dc662e7fd26c 100644 --- a/src/test/isolation2/expected/fts_segment_reset.out +++ b/src/test/isolation2/expected/fts_segment_reset.out @@ -29,6 +29,19 @@ select gp_inject_fault_infinite('postmaster_delay_termination_bg_writer', 'skip' Success: (1 row) +-- We need to set fault at the handler of abort signal from backend +-- so then we can wait until it is triggered. We need to do this because +-- sometimes process of calling abort() (which is issued by the injection +-- of 'panic' fault in the next lines of this test) and abortion itself can +-- take a long time to complete. So, sometimes this test can give unexpected +-- results, when you think that commands sended after issuing panic fault +-- should fail, but they are being executed without any errors. +select gp_inject_fault('backend_abort_handling', 'skip', dbid) from gp_segment_configuration where role = 'p' and content = 0; + gp_inject_fault +----------------- + Success: +(1 row) + -- Now bring down primary of seg0. There're a lot of ways to do that, in order -- to better emulate a real-world scnarios we're injecting a PANIC to do that. 1:select gp_inject_fault('start_prepare', 'panic', dbid) from gp_segment_configuration where role = 'p' AND content = 0; @@ -38,6 +51,14 @@ select gp_inject_fault_infinite('postmaster_delay_termination_bg_writer', 'skip' (1 row) 1&:create table fts_reset_t(a int); +-- We now wait till our seg0 will start reaping it's childs and resetting. +-- We can ignore the results of this command, because it can throw 3 things: +-- error because we couldn't send command because seg0 already restarting; +-- error because reaper killed backend on seg0 because it started reaping +-- backends (previous panic fault injection) +-- no error, because we managed to overrun reaper and sendeed results +-- of wait_until_triggered back + -- This should fail due to the seg0 in reset mode 2&:create table fts_reset_t2(a int); diff --git a/src/test/isolation2/expected/intra-grant-inplace-db.out b/src/test/isolation2/expected/intra-grant-inplace-db.out index e21a5c7cef94..7b8a39d9f235 100644 --- a/src/test/isolation2/expected/intra-grant-inplace-db.out +++ b/src/test/isolation2/expected/intra-grant-inplace-db.out @@ -46,3 +46,63 @@ DROP 1q: ... 2q: ... 3q: ... + +-- Same test as the above, except the GRANT transaction commits before the +-- second transaction check the wait gxid, it should get the gxid from +-- pg_distributedlog instead of the procarray. +CREATE ROLE regress_temp_grantee; +CREATE + +3: CREATE TEMPORARY TABLE frozen_witness (x xid) distributed by (x); +CREATE +-- observe datfrozenxid +3: INSERT INTO frozen_witness SELECT datfrozenxid FROM pg_database WHERE datname = current_catalog; +INSERT 1 +1: BEGIN; +BEGIN +-- heap_update(pg_database) +1: GRANT TEMP ON DATABASE isolation2test TO regress_temp_grantee; +GRANT +-- suspend before get 'wait gxid' +2: SELECT gp_inject_fault('before_get_distributed_xid', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault +----------------- + Success: +(1 row) +-- inplace update +2&: VACUUM (FREEZE); +3: SELECT gp_wait_until_triggered_fault('before_get_distributed_xid', 1, dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) +1: COMMIT; +COMMIT +3: INSERT INTO frozen_witness SELECT datfrozenxid FROM pg_database WHERE datname = current_catalog; +INSERT 1 +3: SELECT gp_inject_fault('before_get_distributed_xid', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + gp_inject_fault +----------------- + Success: +(1 row) + +2<: <... completed> +VACUUM +-- Save the result in an environment variable. +-- We get the raw xid to be sure that the age in the next query will be executed on the coordinator. +3: @post_run 'TOKEN=`echo "${RAW_STR}" | awk \'NR==3\' | awk \'{print $1}\'` && echo ""' : SELECT min(x::varchar::int) FROM frozen_witness; + +-- observe datfrozenxid +3: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': SELECT 'datfrozenxid retreated' FROM pg_database WHERE datname = current_catalog AND age(datfrozenxid) > age('@TOKEN'::xid); + ?column? +---------- +(0 rows) + +REVOKE ALL ON DATABASE isolation2test FROM regress_temp_grantee; +REVOKE +DROP ROLE regress_temp_grantee; +DROP + +1q: ... +2q: ... +3q: ... diff --git a/src/test/isolation2/expected/standby_replay_dtx_info.out b/src/test/isolation2/expected/standby_replay_dtx_info.out index df3166190d2d..028077a90754 100644 --- a/src/test/isolation2/expected/standby_replay_dtx_info.out +++ b/src/test/isolation2/expected/standby_replay_dtx_info.out @@ -95,5 +95,41 @@ select gp_inject_fault_infinite('standby_gxacts_overflow', 'reset', dbid) from g (1 row) drop table test_dtx_standby_tbl; DROP + +-- Verify that max_tm_gxacts is reset from 1. In order to do so, +-- create 2 distributed transactions that are postponed before the point where +-- 'distributed forget' is inserted into the WAL, and check that standby can +-- successfully replay the WAL. +select gp_inject_fault_infinite('dtm_before_insert_forget_comitted', 'suspend', dbid) from gp_segment_configuration where role = 'p' and content = -1; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) + +1&: create table test1(a int) distributed by (a); +2&: create table test2(a int) distributed by (a); + +-- Ensure that replay on standby is ok. +select wait_for_standby_replay(1200); + wait_for_standby_replay +------------------------- + t +(1 row) + +select gp_inject_fault_infinite('dtm_before_insert_forget_comitted', 'reset', dbid) from gp_segment_configuration where role = 'p' and content = -1; + gp_inject_fault_infinite +-------------------------- + Success: +(1 row) + +1<: <... completed> +CREATE +2<: <... completed> +CREATE + +drop table test1; +DROP +drop table test2; +DROP drop function wait_for_standby_replay(int); DROP diff --git a/src/test/isolation2/expected/uao_crash_compaction_column.out b/src/test/isolation2/expected/uao_crash_compaction_column.out index 11c2ccbb3c94..047c732b7b2c 100644 --- a/src/test/isolation2/expected/uao_crash_compaction_column.out +++ b/src/test/isolation2/expected/uao_crash_compaction_column.out @@ -628,7 +628,10 @@ ERROR: Error on receive from seg0 127.0.0.1:7002 pid=29553: server closed the c 1 | 0 | 1 | 10 | 2 | 1 1 | 1 | 129 | 10 | 2 | 1 1 | 2 | 257 | 10 | 2 | 1 -(3 rows) + 2 | 0 | 2 | 0 | 0 | 1 + 2 | 1 | 130 | 0 | 0 | 1 + 2 | 2 | 258 | 0 | 0 | 1 +(6 rows) -- generates truncate xlog record for all the files having entry in -- pg_aocsseg table. 6:VACUUM crash_vacuum_in_appendonly_insert_1; diff --git a/src/test/isolation2/input/parallel_retrieve_cursor/fault_inject.source b/src/test/isolation2/input/parallel_retrieve_cursor/fault_inject.source index 4e222432f611..355d4a649b65 100644 --- a/src/test/isolation2/input/parallel_retrieve_cursor/fault_inject.source +++ b/src/test/isolation2/input/parallel_retrieve_cursor/fault_inject.source @@ -249,3 +249,28 @@ SELECT gp_inject_fault('fetch_tuples_from_endpoint', 'resume', dbid) WHERE content=2 AND role='p'; DROP TABLE t2; + +SELECT gp_inject_fault('alloc_endpoint_slot_full', 'reset', 2); +SELECT gp_inject_fault('alloc_endpoint_slot_full_reset', 'reset', 2); + +-- Test 8: QD shouldn't hang waiting. + +-- start_ignore +DROP TABLE t3; +-- end_ignore + +CREATE TABLE t3 AS SELECT generate_series(1, 10) AS a DISTRIBUTED by (a); + +SELECT gp_inject_fault('alloc_endpoint_slot_full', 'error', dbid) +FROM gp_segment_configuration WHERE role = 'p' AND content = 0; + +BEGIN; +-- QE encounters error and destroys the endpoint immediately. QD successfully +-- resets the query, sends ACKs, and discards transaction. +DECLARE c1 PARALLEL RETRIEVE CURSOR FOR SELECT * FROM t3; +ROLLBACK; + +SELECT gp_inject_fault('alloc_endpoint_slot_full', 'reset', dbid) +FROM gp_segment_configuration WHERE role = 'p' AND content = 0; + +DROP TABLE t3; diff --git a/src/test/isolation2/input/resgroup/resgroup_alter_memory.source b/src/test/isolation2/input/resgroup/resgroup_alter_memory.source index 70e4d235cfb7..e0ee90066e8c 100644 --- a/src/test/isolation2/input/resgroup/resgroup_alter_memory.source +++ b/src/test/isolation2/input/resgroup/resgroup_alter_memory.source @@ -6,7 +6,7 @@ DROP RESOURCE GROUP rg2_memory_test; -- end_ignore CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS -'@abs_builddir@/../regress/regress@DLSUFFIX@', 'resGroupPalloc' +'@abs_builddir@/../../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; CREATE OR REPLACE FUNCTION hold_memory_by_percent(int, float) RETURNS int AS $$ diff --git a/src/test/isolation2/input/resgroup/resgroup_bypass.source b/src/test/isolation2/input/resgroup/resgroup_bypass.source index 10647d018d5a..9af746ead0f0 100644 --- a/src/test/isolation2/input/resgroup/resgroup_bypass.source +++ b/src/test/isolation2/input/resgroup/resgroup_bypass.source @@ -12,7 +12,7 @@ CREATE RESOURCE GROUP rg_bypass_test WITH CREATE ROLE role_bypass_test RESOURCE GROUP rg_bypass_test; CREATE OR REPLACE FUNCTION repeatPalloc(int, int) RETURNS int AS -'@abs_builddir@/../regress/regress@DLSUFFIX@', 'repeatPalloc' +'@abs_builddir@/../../regress/regress@DLSUFFIX@', 'repeatPalloc' LANGUAGE C READS SQL DATA; CREATE OR REPLACE FUNCTION hold_memory(int, int) RETURNS int AS $$ @@ -207,6 +207,18 @@ SELECT pg_cancel_backend(pid) FROM pg_stat_activity 61q: 62q: +-- +-- resource group should be shown in pg_stat_activity even when it's bypassed +-- + +61: SET gp_resource_group_bypass TO on; +61&: SELECT pg_sleep(3) FROM gp_dist_random('gp_id'); +0U: SELECT query, rsgname FROM pg_stat_activity WHERE query LIKE '%gp_dist_random%'; +61<: + +61q: +0Uq: + -- -- cleanup -- diff --git a/src/test/isolation2/input/resgroup/resgroup_memory_limit.source b/src/test/isolation2/input/resgroup/resgroup_memory_limit.source index 0e7d44f8b901..fc3a4e89564d 100644 --- a/src/test/isolation2/input/resgroup/resgroup_memory_limit.source +++ b/src/test/isolation2/input/resgroup/resgroup_memory_limit.source @@ -5,7 +5,7 @@ DROP RESOURCE GROUP rg2_memory_test; -- end_ignore CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS -'@abs_builddir@/../regress/regress@DLSUFFIX@', 'resGroupPalloc' +'@abs_builddir@/../../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; CREATE OR REPLACE FUNCTION hold_memory_by_percent(float) RETURNS int AS $$ diff --git a/src/test/isolation2/input/resgroup/resgroup_memory_runaway.source b/src/test/isolation2/input/resgroup/resgroup_memory_runaway.source index 0e99446ab254..111996678a8e 100644 --- a/src/test/isolation2/input/resgroup/resgroup_memory_runaway.source +++ b/src/test/isolation2/input/resgroup/resgroup_memory_runaway.source @@ -5,7 +5,7 @@ DROP RESOURCE GROUP rg2_memory_test; -- end_ignore CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS -'@abs_builddir@/../regress/regress@DLSUFFIX@', 'resGroupPalloc' +'@abs_builddir@/../../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; CREATE OR REPLACE FUNCTION hold_memory_by_percent(float) RETURNS int AS $$ diff --git a/src/test/isolation2/input/resgroup/resgroup_memory_statistic.source b/src/test/isolation2/input/resgroup/resgroup_memory_statistic.source index a86c5bc58afb..2557672dbcda 100644 --- a/src/test/isolation2/input/resgroup/resgroup_memory_statistic.source +++ b/src/test/isolation2/input/resgroup/resgroup_memory_statistic.source @@ -6,7 +6,7 @@ DROP RESOURCE GROUP rg2_memory_test; -- end_ignore CREATE OR REPLACE FUNCTION repeatPalloc(int, int) RETURNS int AS -'@abs_builddir@/../regress/regress@DLSUFFIX@', 'repeatPalloc' +'@abs_builddir@/../../regress/regress@DLSUFFIX@', 'repeatPalloc' LANGUAGE C READS SQL DATA; CREATE OR REPLACE FUNCTION hold_memory(int, int) RETURNS int AS $$ diff --git a/src/test/isolation2/input/resgroup/resgroup_move_query.source b/src/test/isolation2/input/resgroup/resgroup_move_query.source index d65925e552bc..189e73262dfc 100644 --- a/src/test/isolation2/input/resgroup/resgroup_move_query.source +++ b/src/test/isolation2/input/resgroup/resgroup_move_query.source @@ -12,7 +12,7 @@ -- end_matchsubs CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS -'@abs_builddir@/../regress/regress@DLSUFFIX@', 'resGroupPalloc' +'@abs_builddir@/../../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; CREATE OR REPLACE FUNCTION hold_memory_by_percent(int, float) RETURNS int AS $$ @@ -306,12 +306,20 @@ SELECT num_running FROM gp_toolkit.gp_resgroup_status WHERE rsgname='rg_move_que --spawn all backends at first short call to guarantee correct pg_resgroup_move_query() execution 1: SELECT * FROM gp_dist_random('gp_id'), pg_sleep(1) LIMIT 1; 1&: SELECT * FROM gp_dist_random('gp_id'), pg_sleep(3) LIMIT 1; +-- segments should display the resource group name +1U: SELECT rsgname, query FROM pg_stat_activity WHERE rsgname LIKE 'rg_move_query%'; +-- there are two backends on coordinator, the second one is for gather motion 2: SELECT gp_toolkit.pg_resgroup_move_query(pid, 'rg_move_query') FROM pg_stat_activity WHERE query LIKE '%pg_sleep%' AND rsgname='rg_move_query_mem_small'; +SELECT pg_sleep(1); +1U: SELECT rsgname, query FROM pg_stat_activity WHERE rsgname LIKE 'rg_move_query%'; 1<: 2: SELECT is_session_in_group(pid, 'rg_move_query') FROM pg_stat_activity WHERE query LIKE '%pg_sleep%' AND state = 'idle in transaction'; -- and check we can move it back right in the same transaction 1&: SELECT * FROM gp_dist_random('gp_id'), pg_sleep(3) LIMIT 1; +1U: SELECT rsgname, query FROM pg_stat_activity WHERE rsgname LIKE 'rg_move_query%'; 2: SELECT gp_toolkit.pg_resgroup_move_query(pid, 'rg_move_query_mem_small') FROM pg_stat_activity WHERE query LIKE '%pg_sleep%' AND rsgname='rg_move_query'; +SELECT pg_sleep(1); +1U: SELECT rsgname, query FROM pg_stat_activity WHERE rsgname LIKE 'rg_move_query%'; 1<: 2: SELECT is_session_in_group(pid, 'rg_move_query_mem_small') FROM pg_stat_activity WHERE query LIKE '%pg_sleep%' AND state = 'idle in transaction'; 1: END; diff --git a/src/test/isolation2/input/resgroup/resgroup_oom.source b/src/test/isolation2/input/resgroup/resgroup_oom.source new file mode 100644 index 000000000000..35b6d1783ffa --- /dev/null +++ b/src/test/isolation2/input/resgroup/resgroup_oom.source @@ -0,0 +1,53 @@ +-- start_matchsubs +-- m/ERROR: Out of memory.*/ +-- s/ERROR: Out of memory.*/ERROR: Out of memory/ +-- m/ERROR: Canceling query because of high VMEM usage.*/ +-- s/ERROR: Canceling query because of high VMEM usage.*/ERROR: Out of memory/ +-- end_matchsubs + +-- start_ignore +CREATE EXTENSION gp_inject_fault; +DROP FUNCTION gp_mock_cdbdispatchcommand(amount int); +DROP ROLE role_oom_test; +DROP RESOURCE GROUP rg_oom_test; +-- end_ignore +CREATE RESOURCE GROUP rg_oom_test +WITH (cpu_rate_limit=20, memory_limit=20, memory_shared_quota=100); +CREATE ROLE role_oom_test RESOURCE GROUP rg_oom_test; +CREATE FUNCTION gp_mock_cdbdispatchcommand(amount int) +RETURNS SETOF text AS '@abs_srcdir@/../regress/regress.so', +'gp_mock_cdbdispatchcommand' LANGUAGE C; + +1: SET ROLE TO role_oom_test; + +-- Freeze coordinator's session after it reads results from segments. +SELECT gp_inject_fault('check_dispatch_result_end', 'suspend', dbid) +FROM gp_segment_configuration WHERE role = 'p' AND content = -1; + +-- Send the heavy query. +1&: SELECT count(*) FROM gp_mock_cdbdispatchcommand(1000000); + +-- Wait until we receive everything. +SELECT gp_wait_until_triggered_fault('check_dispatch_result_end', 1, dbid) +FROM gp_segment_configuration WHERE role = 'p' AND content = -1; + +-- The query should've used ~135 MB of memory. Allow 15 MB error. +WITH r AS ( + SELECT (memory_usage->'-1'->'used')::text::int AS mb + FROM gp_toolkit.gp_resgroup_status WHERE rsgname = 'rg_oom_test' +) +SELECT r.mb < 150 AS "under 150 MB", r.mb > 120 AS "above 120 MB" +FROM r; + +SELECT gp_inject_fault('check_dispatch_result_end', 'reset', dbid) FROM +gp_segment_configuration WHERE role = 'p' AND content = -1; + +1<: + +-- And finally, make sure we don't enter error recursion on fail. +ALTER RESOURCE GROUP rg_oom_test SET memory_shared_quota 0; +1: SELECT count(*) FROM gp_mock_cdbdispatchcommand(10000000); + +DROP FUNCTION gp_mock_cdbdispatchcommand(amount int); +DROP ROLE role_oom_test; +DROP RESOURCE GROUP rg_oom_test; diff --git a/src/test/isolation2/input/resgroup/resgroup_parallel_retrieve.source b/src/test/isolation2/input/resgroup/resgroup_parallel_retrieve.source new file mode 100644 index 000000000000..d9c597c6c1c4 --- /dev/null +++ b/src/test/isolation2/input/resgroup/resgroup_parallel_retrieve.source @@ -0,0 +1,194 @@ +-- start_ignore +CREATE EXTENSION IF NOT EXISTS gp_parallel_retrieve_cursor; + +DROP TABLE IF EXISTS t CASCADE; +DROP ROLE r; +DROP RESOURCE GROUP rg; +DROP RESOURCE GROUP rg2; + +CREATE TABLE t (i INT) DISTRIBUTED BY (i); +CREATE RESOURCE GROUP rg WITH (concurrency=10, cpu_rate_limit=10, memory_limit=20); +CREATE RESOURCE GROUP rg2 WITH (concurrency=10, cpu_rate_limit=10, memory_limit=40); + +CREATE ROLE r SUPERUSER RESOURCE GROUP rg2; + +INSERT INTO t SELECT generate_series(1, 7); + +GRANT ALL ON t TO r; + +ALTER ROLE gpadmin WITH RESOURCE GROUP rg; +-- end_ignore +-- start_matchsubs +-- m/ERROR: (.*) \([a-zA-Z_]+\.c:[0-9]+\)$/ +-- s/ERROR: (.*) \([a-zA-Z_]+\.c:[0-9]+\)$/ERROR: $1/ +-- end_matchsubs + +-- +-- Normal mode with GUC enabled. +-- + +!\retcode gpconfig -c gp_resource_group_retrieve -v on; +!\retcode gpstop -u; + +1: BEGIN; +1: DECLARE c1 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(2), i FROM t; +1: @post_run 'parse_endpoint_info 1 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c1'; + +1: SELECT gp_inject_fault('switch_resgroup_ppc', 'skip', dbid) + FROM gp_segment_configuration WHERE role = 'p' and content = 0; +1&: SELECT gp_wait_until_triggered_fault('switch_resgroup_ppc', 1, dbid) + FROM gp_segment_configuration WHERE role = 'p' and content = 0; + +0R&: @pre_run 'set_endpoint_variable @ENDPOINT1': RETRIEVE 1 FROM ENDPOINT "@ENDPOINT1"; + +0U: SHOW gp_resource_group_retrieve; +0U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE 1%'; + +0R<: +1<: + +1: SELECT gp_inject_fault('all', 'reset', dbid) + FROM gp_segment_configuration WHERE role = 'p' and content = 0; +1q: + +-- Retrieve on closed cursor. +0R: @pre_run 'set_endpoint_variable @ENDPOINT1': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT1"; +0Rq: + +-- +-- Normal mode with GUC disabled. +-- + +!\retcode gpconfig -c gp_resource_group_retrieve -v off; +!\retcode gpstop -u; + +1: BEGIN; +1: DECLARE c2 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(2), i FROM t; +1: @post_run 'parse_endpoint_info 2 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c2'; + +0R&: @pre_run 'set_endpoint_variable @ENDPOINT2': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT2"; + +0U: SHOW gp_resource_group_retrieve; +-- No resource groups assigned. +0U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE ALL%'; + +0R<: +0Rq: +1: ABORT; + +!\retcode gpconfig -c gp_resource_group_retrieve -v on; +!\retcode gpconfig -c gp_resource_group_bypass -v on; +!\retcode gpstop -u; + +-- +-- Bypass mode with GUC enabled. +-- + +1: BEGIN; + +1: DECLARE c3 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(2), i FROM t; +1: @post_run 'parse_endpoint_info 3 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c3'; + +0R&: @pre_run 'set_endpoint_variable @ENDPOINT3': RETRIEVE 1 FROM ENDPOINT "@ENDPOINT3"; + +0U: SHOW gp_resource_group_bypass; +0U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE 1%'; + +0R<: + +-- All subsequent queries are run with bypass mode. + +1: SELECT gp_inject_fault('switch_resgroup_ppc_bypass', 'skip', dbid), + gp_inject_fault('switch_resgroup_ppc', 'error', dbid) + FROM gp_segment_configuration WHERE role = 'p' and content = 0; +1&: SELECT gp_wait_until_triggered_fault('switch_resgroup_ppc_bypass', 1, dbid) + FROM gp_segment_configuration WHERE role = 'p' and content = 0; + +0R: @pre_run 'set_endpoint_variable @ENDPOINT3': RETRIEVE 1 FROM ENDPOINT "@ENDPOINT3"; + +1<: + +1: SELECT gp_inject_fault('all', 'reset', dbid) + FROM gp_segment_configuration WHERE role = 'p' and content = 0; +1q: + +-- Retrieve on closed cursor with bypass mode. +0R: @pre_run 'set_endpoint_variable @ENDPOINT3': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT3"; +0Rq: + +!\retcode gpconfig -r gp_resource_group_bypass; +!\retcode gpstop -u; + +-- +-- Multiple retrieve sessions sharing slot. +-- + +1: BEGIN; + +1: DECLARE c4 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(3), i FROM t; +1: @post_run 'parse_endpoint_info 4 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c4'; +1: DECLARE c5 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(3), i FROM t; +1: @post_run 'parse_endpoint_info 5 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c5'; +1: DECLARE c6 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(3), i FROM t; +1: @post_run 'parse_endpoint_info 6 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c6'; + +0R&: @pre_run 'set_endpoint_variable @ENDPOINT4': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT4"; +1R&: @pre_run 'set_endpoint_variable @ENDPOINT5': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT5"; +2R&: @pre_run 'set_endpoint_variable @ENDPOINT6': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT6"; + +-- All should have the same resource group. +0U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE ALL%'; +1U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE ALL%'; +2U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE ALL%'; + +0R<: +1R<: +2R<: + +0Rq: + +1: COMMIT; +1q: + +-- +-- GUC value must be the same on segments and on the master. +-- + +!\retcode gpconfig -c gp_resource_group_retrieve -v on -m off; + +--- +--- Moving resource group should move the retrieve sessions as well. +--- + +1: BEGIN; + +1: DECLARE c7 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(5), i FROM t; +1: @post_run 'parse_endpoint_info 7 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c7'; + +0R&: @pre_run 'set_endpoint_variable @ENDPOINT7': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT7"; + +0U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE ALL%'; + +2: SET ROLE r; +2: SELECT gp_toolkit.pg_resgroup_move_query(pid, 'rg2') FROM pg_stat_activity WHERE rsgname = 'rg'; + +0U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE ALL%'; + +0R<: + +1: ABORT; + +1q: +0Rq: +0Uq: +-- start_ignore +! gpconfig -r gp_resource_group_retrieve; +! gpstop -u; + +ALTER ROLE gpadmin WITH RESOURCE GROUP admin_group; + +DROP TABLE t; +DROP ROLE r; +DROP RESOURCE GROUP rg; +DROP RESOURCE GROUP rg2; +-- end_ignore diff --git a/src/test/isolation2/input/resgroup/resgroup_startup_memory.source b/src/test/isolation2/input/resgroup/resgroup_startup_memory.source index 75e431ea5ca0..9a235ea3dad9 100644 --- a/src/test/isolation2/input/resgroup/resgroup_startup_memory.source +++ b/src/test/isolation2/input/resgroup/resgroup_startup_memory.source @@ -8,13 +8,13 @@ drop resource group rg2; create extension if not exists gp_inject_fault; -create or replace function resGroupPalloc(float) returns int as '@abs_builddir@/../regress/regress@DLSUFFIX@', 'resGroupPalloc' language C reads sql data; +create or replace function resGroupPalloc(float) returns int as '@abs_builddir@/../../regress/regress@DLSUFFIX@', 'resGroupPalloc' language C reads sql data; create or replace function hold_memory_by_percent_on_qe(float) returns int as $$ select resGroupPalloc($1) from gp_dist_random('gp_id') $$ language sql; create or replace function repeatPalloc(int, int) returns int as -'@abs_builddir@/../regress/regress@DLSUFFIX@', 'repeatPalloc' +'@abs_builddir@/../../regress/regress@DLSUFFIX@', 'repeatPalloc' language C reads sql data; -- In the next test, we need to be able to allocate 100% of the available diff --git a/src/test/isolation2/isolation2_main.c b/src/test/isolation2/isolation2_main.c index 5c2b9a88f94e..f641fd38478d 100644 --- a/src/test/isolation2/isolation2_main.c +++ b/src/test/isolation2/isolation2_main.c @@ -15,6 +15,8 @@ #include #include +static char sql_isolation_testcase[MAXPGPATH]; + /* * start a Python isolation tester process for specified file (including * redirection), and return process ID @@ -107,7 +109,8 @@ isolation_start_test(const char *testname, "%s ", launcher); snprintf(psql_cmd + offset, sizeof(psql_cmd) - offset, - "python ./sql_isolation_testcase.py --dbname=\"%s\" --initfile_prefix=\"%s\" < \"%s\" > \"%s\" 2>&1", + "python %s --dbname=\"%s\" --initfile_prefix=\"%s\" < \"%s\" > \"%s\" 2>&1", + sql_isolation_testcase, dblist->str, outfile, infile, @@ -130,6 +133,23 @@ isolation_init(int argc, char **argv) { /* set default regression database name */ add_stringlist_item(&dblist, "isolation2test"); + + /* find python script to run */ + if (find_other_exec(argv[0], "sql_isolation_testcase.py", + NULL, sql_isolation_testcase) != 0) + { + char full_path[MAXPGPATH]; + const char *progname = get_progname(argv[0]); + + if (find_my_exec(argv[0], full_path) < 0) + strlcpy(full_path, progname, sizeof(full_path)); + + fprintf(stderr, + _("The program \"sql_isolation_testcase.py\" is needed by %s " + "but was not found in the same directory as \"%s\".\n"), + progname, full_path); + exit(1); + } } int diff --git a/src/test/isolation2/isolation2_resgroup_schedule b/src/test/isolation2/isolation2_resgroup_schedule index 17e191bde5a5..9116f39cb46d 100644 --- a/src/test/isolation2/isolation2_resgroup_schedule +++ b/src/test/isolation2/isolation2_resgroup_schedule @@ -61,4 +61,9 @@ test: resgroup/resgroup_large_group_id test: resgroup/resgroup_startup_memory +test: resgroup/resgroup_oom + +# parallel retrieve cursor integration +test: resgroup/resgroup_parallel_retrieve + test: resgroup/disable_resgroup diff --git a/src/test/isolation2/isolation2_schedule b/src/test/isolation2/isolation2_schedule index dd3b99330059..ec9f4c73e352 100644 --- a/src/test/isolation2/isolation2_schedule +++ b/src/test/isolation2/isolation2_schedule @@ -68,7 +68,8 @@ test: deadlock_under_entry_db_singleton # conflict when running in parallel with other cases. test: misc -test: starve_case pg_views_concurrent_drop alter_blocks_for_update_and_viceversa drop_rename reader_waits_for_lock resource_queue +test: drop_rename +test: starve_case pg_views_concurrent_drop alter_blocks_for_update_and_viceversa reader_waits_for_lock resource_queue test: vacuum_drop_phase_ao # Test simple cancellation for resource queues and cancellation/deadlocks for @@ -266,8 +267,7 @@ test: pg_basebackup_with_tablespaces test: segwalrep/hintbit_throttle test: fts_manual_probe test: fts_session_reset -# FIXME: temporary disable as unstable -# test: fts_segment_reset +test: fts_segment_reset # Reindex tests test: reindex/abort_reindex diff --git a/src/test/isolation2/output/parallel_retrieve_cursor/fault_inject.source b/src/test/isolation2/output/parallel_retrieve_cursor/fault_inject.source index 9a963b076992..890d75e73f61 100644 --- a/src/test/isolation2/output/parallel_retrieve_cursor/fault_inject.source +++ b/src/test/isolation2/output/parallel_retrieve_cursor/fault_inject.source @@ -770,3 +770,47 @@ ROLLBACK DROP TABLE t2; DROP + +SELECT gp_inject_fault('alloc_endpoint_slot_full', 'reset', 2); + gp_inject_fault +----------------- + Success: +(1 row) +SELECT gp_inject_fault('alloc_endpoint_slot_full_reset', 'reset', 2); + gp_inject_fault +----------------- + Success: +(1 row) + +-- Test 8: QD shouldn't hang waiting. + +-- start_ignore +DROP TABLE t3; +-- end_ignore + +CREATE TABLE t3 AS SELECT generate_series(1, 10) AS a DISTRIBUTED by (a); +CREATE 10 + +SELECT gp_inject_fault('alloc_endpoint_slot_full', 'error', dbid) FROM gp_segment_configuration WHERE role = 'p' AND content = 0; + gp_inject_fault +----------------- + Success: +(1 row) + +BEGIN; +BEGIN +-- QE encounters error and destroys the endpoint immediately. QD successfully +-- resets the query, sends ACKs, and discards transaction. +DECLARE c1 PARALLEL RETRIEVE CURSOR FOR SELECT * FROM t3; +ERROR: fault triggered, fault name:'alloc_endpoint_slot_full' fault type:'error' (seg0 127.0.0.1:6002 pid=8916) +ROLLBACK; +ROLLBACK + +SELECT gp_inject_fault('alloc_endpoint_slot_full', 'reset', dbid) FROM gp_segment_configuration WHERE role = 'p' AND content = 0; + gp_inject_fault +----------------- + Success: +(1 row) + +DROP TABLE t3; +DROP diff --git a/src/test/isolation2/output/resgroup/resgroup_alter_memory.source b/src/test/isolation2/output/resgroup/resgroup_alter_memory.source index 9a6fcd3fcc0c..3eeaedadd26a 100644 --- a/src/test/isolation2/output/resgroup/resgroup_alter_memory.source +++ b/src/test/isolation2/output/resgroup/resgroup_alter_memory.source @@ -9,7 +9,7 @@ DROP RESOURCE GROUP rg2_memory_test; ERROR: resource group "rg2_memory_test" does not exist -- end_ignore -CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS '@abs_builddir@/../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; +CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS '@abs_builddir@/../../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; CREATE CREATE OR REPLACE FUNCTION hold_memory_by_percent(int, float) RETURNS int AS $$ SELECT * FROM resGroupPalloc($2) $$ LANGUAGE sql; diff --git a/src/test/isolation2/output/resgroup/resgroup_bypass.source b/src/test/isolation2/output/resgroup/resgroup_bypass.source index 793f100ef57e..23fe2457cc9c 100644 --- a/src/test/isolation2/output/resgroup/resgroup_bypass.source +++ b/src/test/isolation2/output/resgroup/resgroup_bypass.source @@ -14,7 +14,7 @@ CREATE CREATE ROLE role_bypass_test RESOURCE GROUP rg_bypass_test; CREATE -CREATE OR REPLACE FUNCTION repeatPalloc(int, int) RETURNS int AS '@abs_builddir@/../regress/regress@DLSUFFIX@', 'repeatPalloc' LANGUAGE C READS SQL DATA; +CREATE OR REPLACE FUNCTION repeatPalloc(int, int) RETURNS int AS '@abs_builddir@/../../regress/regress@DLSUFFIX@', 'repeatPalloc' LANGUAGE C READS SQL DATA; CREATE CREATE OR REPLACE FUNCTION hold_memory(int, int) RETURNS int AS $$ SELECT * FROM repeatPalloc(1, $2) $$ LANGUAGE sql; @@ -357,6 +357,30 @@ ERROR: canceling statement due to user request 61q: ... 62q: ... +-- +-- resource group should be shown in pg_stat_activity even when it's bypassed +-- + +61: SET gp_resource_group_bypass TO on; +SET +61&: SELECT pg_sleep(3) FROM gp_dist_random('gp_id'); +0U: SELECT query, rsgname FROM pg_stat_activity WHERE query LIKE '%gp_dist_random%'; + query | rsgname +----------------------------------------------------------------------------------+------------- + SELECT pg_sleep(3) FROM gp_dist_random('gp_id'); | admin_group + SELECT query, rsgname FROM pg_stat_activity WHERE query LIKE '%gp_dist_random%'; | unknown +(2 rows) +61<: <... completed> + pg_sleep +---------- + + + +(3 rows) + +61q: ... +0Uq: ... + -- -- cleanup -- diff --git a/src/test/isolation2/output/resgroup/resgroup_memory_limit.source b/src/test/isolation2/output/resgroup/resgroup_memory_limit.source index d322439b2d3d..dd8262f8574f 100644 --- a/src/test/isolation2/output/resgroup/resgroup_memory_limit.source +++ b/src/test/isolation2/output/resgroup/resgroup_memory_limit.source @@ -7,7 +7,7 @@ DROP RESOURCE GROUP rg2_memory_test; ERROR: resource group "rg2_memory_test" does not exist -- end_ignore -CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS '@abs_builddir@/../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; +CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS '@abs_builddir@/../../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; CREATE CREATE OR REPLACE FUNCTION hold_memory_by_percent(float) RETURNS int AS $$ SELECT * FROM resGroupPalloc($1) $$ LANGUAGE sql; diff --git a/src/test/isolation2/output/resgroup/resgroup_memory_runaway.source b/src/test/isolation2/output/resgroup/resgroup_memory_runaway.source index fe7cda87d761..2143e026e248 100644 --- a/src/test/isolation2/output/resgroup/resgroup_memory_runaway.source +++ b/src/test/isolation2/output/resgroup/resgroup_memory_runaway.source @@ -7,7 +7,7 @@ DROP RESOURCE GROUP rg2_memory_test; ERROR: resource group "rg2_memory_test" does not exist -- end_ignore -CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS '@abs_builddir@/../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; +CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS '@abs_builddir@/../../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; CREATE CREATE OR REPLACE FUNCTION hold_memory_by_percent(float) RETURNS int AS $$ SELECT * FROM resGroupPalloc($1) $$ LANGUAGE sql; diff --git a/src/test/isolation2/output/resgroup/resgroup_memory_statistic.source b/src/test/isolation2/output/resgroup/resgroup_memory_statistic.source index 6b679bb59865..fe7e93d7ae0e 100644 --- a/src/test/isolation2/output/resgroup/resgroup_memory_statistic.source +++ b/src/test/isolation2/output/resgroup/resgroup_memory_statistic.source @@ -9,7 +9,7 @@ DROP RESOURCE GROUP rg2_memory_test; ERROR: resource group "rg2_memory_test" does not exist -- end_ignore -CREATE OR REPLACE FUNCTION repeatPalloc(int, int) RETURNS int AS '@abs_builddir@/../regress/regress@DLSUFFIX@', 'repeatPalloc' LANGUAGE C READS SQL DATA; +CREATE OR REPLACE FUNCTION repeatPalloc(int, int) RETURNS int AS '@abs_builddir@/../../regress/regress@DLSUFFIX@', 'repeatPalloc' LANGUAGE C READS SQL DATA; CREATE CREATE OR REPLACE FUNCTION hold_memory(int, int) RETURNS int AS $$ SELECT * FROM repeatPalloc(1, $2) $$ LANGUAGE sql; diff --git a/src/test/isolation2/output/resgroup/resgroup_move_query.source b/src/test/isolation2/output/resgroup/resgroup_move_query.source index 02587e1575b8..19aed4b23982 100644 --- a/src/test/isolation2/output/resgroup/resgroup_move_query.source +++ b/src/test/isolation2/output/resgroup/resgroup_move_query.source @@ -11,7 +11,7 @@ -- -- end_matchsubs -CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS '@abs_builddir@/../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; +CREATE OR REPLACE FUNCTION resGroupPalloc(float) RETURNS int AS '@abs_builddir@/../../regress/regress@DLSUFFIX@', 'resGroupPalloc' LANGUAGE C READS SQL DATA; CREATE CREATE OR REPLACE FUNCTION hold_memory_by_percent(int, float) RETURNS int AS $$ SELECT * FROM resGroupPalloc($2) $$ LANGUAGE sql; @@ -646,10 +646,28 @@ BEGIN Greenplum | -1 | -1 | -1 | (1 row) 1&: SELECT * FROM gp_dist_random('gp_id'), pg_sleep(3) LIMIT 1; +-- segments should display the resource group name +1U: SELECT rsgname, query FROM pg_stat_activity WHERE rsgname LIKE 'rg_move_query%'; + rsgname | query +-------------------------+------------------------------------------------------------- + rg_move_query_mem_small | SELECT * FROM gp_dist_random('gp_id'), pg_sleep(3) LIMIT 1; +(1 row) +-- there are two backends on coordinator, the second one is for gather motion 2: SELECT gp_toolkit.pg_resgroup_move_query(pid, 'rg_move_query') FROM pg_stat_activity WHERE query LIKE '%pg_sleep%' AND rsgname='rg_move_query_mem_small'; pg_resgroup_move_query ------------------------ t + t +(2 rows) +SELECT pg_sleep(1); + pg_sleep +---------- + +(1 row) +1U: SELECT rsgname, query FROM pg_stat_activity WHERE rsgname LIKE 'rg_move_query%'; + rsgname | query +---------------+------------------------------------------------------------- + rg_move_query | SELECT * FROM gp_dist_random('gp_id'), pg_sleep(3) LIMIT 1; (1 row) 1<: <... completed> gpname | numsegments | dbid | content | pg_sleep @@ -663,10 +681,26 @@ BEGIN (1 row) -- and check we can move it back right in the same transaction 1&: SELECT * FROM gp_dist_random('gp_id'), pg_sleep(3) LIMIT 1; +1U: SELECT rsgname, query FROM pg_stat_activity WHERE rsgname LIKE 'rg_move_query%'; + rsgname | query +---------------+------------------------------------------------------------- + rg_move_query | SELECT * FROM gp_dist_random('gp_id'), pg_sleep(3) LIMIT 1; +(1 row) 2: SELECT gp_toolkit.pg_resgroup_move_query(pid, 'rg_move_query_mem_small') FROM pg_stat_activity WHERE query LIKE '%pg_sleep%' AND rsgname='rg_move_query'; pg_resgroup_move_query ------------------------ t + t +(2 rows) +SELECT pg_sleep(1); + pg_sleep +---------- + +(1 row) +1U: SELECT rsgname, query FROM pg_stat_activity WHERE rsgname LIKE 'rg_move_query%'; + rsgname | query +-------------------------+------------------------------------------------------------- + rg_move_query_mem_small | SELECT * FROM gp_dist_random('gp_id'), pg_sleep(3) LIMIT 1; (1 row) 1<: <... completed> gpname | numsegments | dbid | content | pg_sleep diff --git a/src/test/isolation2/output/resgroup/resgroup_oom.source b/src/test/isolation2/output/resgroup/resgroup_oom.source new file mode 100644 index 000000000000..20e0598d34d0 --- /dev/null +++ b/src/test/isolation2/output/resgroup/resgroup_oom.source @@ -0,0 +1,66 @@ +-- start_matchsubs +-- m/ERROR: Out of memory.*/ +-- s/ERROR: Out of memory.*/ERROR: Out of memory/ +-- m/ERROR: Canceling query because of high VMEM usage.*/ +-- s/ERROR: Canceling query because of high VMEM usage.*/ERROR: Out of memory/ +-- end_matchsubs + +CREATE RESOURCE GROUP rg_oom_test WITH (cpu_rate_limit=20, memory_limit=20, memory_shared_quota=100); +CREATE +CREATE ROLE role_oom_test RESOURCE GROUP rg_oom_test; +CREATE +CREATE FUNCTION gp_mock_cdbdispatchcommand(amount int) RETURNS SETOF text AS '@abs_srcdir@/../regress/regress.so', 'gp_mock_cdbdispatchcommand' LANGUAGE C; +CREATE + +1: SET ROLE TO role_oom_test; +SET + +-- Freeze coordinator's session after it reads results from segments. +SELECT gp_inject_fault('check_dispatch_result_end', 'suspend', dbid) FROM gp_segment_configuration WHERE role = 'p' AND content = -1; + gp_inject_fault +----------------- + Success: +(1 row) + +-- Send the heavy query. +1&: SELECT count(*) FROM gp_mock_cdbdispatchcommand(1000000); + +-- Wait until we receive everything. +SELECT gp_wait_until_triggered_fault('check_dispatch_result_end', 1, dbid) FROM gp_segment_configuration WHERE role = 'p' AND content = -1; + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) + +-- The query should've used ~135 MB of memory. Allow 15 MB error. +WITH r AS ( SELECT (memory_usage->'-1'->'used')::text::int AS mb FROM gp_toolkit.gp_resgroup_status WHERE rsgname = 'rg_oom_test' ) SELECT r.mb < 150 AS "under 150 MB", r.mb > 120 AS "above 120 MB" FROM r; + under 150 MB | above 120 MB +--------------+-------------- + t | t +(1 row) + +SELECT gp_inject_fault('check_dispatch_result_end', 'reset', dbid) FROM gp_segment_configuration WHERE role = 'p' AND content = -1; + gp_inject_fault +----------------- + Success: +(1 row) + +1<: <... completed> + count +--------- + 4000000 +(1 row) + +-- And finally, make sure we don't enter error recursion on fail. +ALTER RESOURCE GROUP rg_oom_test SET memory_shared_quota 0; +ALTER +1: SELECT count(*) FROM gp_mock_cdbdispatchcommand(10000000); +ERROR: Out of memory +DETAIL: Resource group memory limit reached + +DROP FUNCTION gp_mock_cdbdispatchcommand(amount int); +DROP +DROP ROLE role_oom_test; +DROP +DROP RESOURCE GROUP rg_oom_test; +DROP diff --git a/src/test/isolation2/output/resgroup/resgroup_oom_1.source b/src/test/isolation2/output/resgroup/resgroup_oom_1.source new file mode 100644 index 000000000000..bdcb8bbc92f8 --- /dev/null +++ b/src/test/isolation2/output/resgroup/resgroup_oom_1.source @@ -0,0 +1,65 @@ +-- start_matchsubs +-- m/ERROR: Out of memory.*/ +-- s/ERROR: Out of memory.*/ERROR: Out of memory/ +-- m/ERROR: Canceling query because of high VMEM usage.*/ +-- s/ERROR: Canceling query because of high VMEM usage.*/ERROR: Out of memory/ +-- end_matchsubs + +CREATE RESOURCE GROUP rg_oom_test WITH (cpu_rate_limit=20, memory_limit=20, memory_shared_quota=100); +CREATE +CREATE ROLE role_oom_test RESOURCE GROUP rg_oom_test; +CREATE +CREATE FUNCTION gp_mock_cdbdispatchcommand(amount int) RETURNS SETOF text AS '@abs_srcdir@/../regress/regress.so', 'gp_mock_cdbdispatchcommand' LANGUAGE C; +CREATE + +1: SET ROLE TO role_oom_test; +SET + +-- Freeze coordinator's session after it reads results from segments. +SELECT gp_inject_fault('check_dispatch_result_end', 'suspend', dbid) FROM gp_segment_configuration WHERE role = 'p' AND content = -1; + gp_inject_fault +----------------- + Success: +(1 row) + +-- Send the heavy query. +1&: SELECT count(*) FROM gp_mock_cdbdispatchcommand(1000000); + +-- Wait until we receive everything. +SELECT gp_wait_until_triggered_fault('check_dispatch_result_end', 1, dbid) FROM gp_segment_configuration WHERE role = 'p' AND content = -1; + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) + +-- The query should've used ~135 MB of memory. Allow 15 MB error. +WITH r AS ( SELECT (memory_usage->'-1'->'used')::text::int AS mb FROM gp_toolkit.gp_resgroup_status WHERE rsgname = 'rg_oom_test' ) SELECT r.mb < 150 AS "under 150 MB", r.mb > 120 AS "above 120 MB" FROM r; + under 150 MB | above 120 MB +--------------+-------------- + t | t +(1 row) + +SELECT gp_inject_fault('check_dispatch_result_end', 'reset', dbid) FROM gp_segment_configuration WHERE role = 'p' AND content = -1; + gp_inject_fault +----------------- + Success: +(1 row) + +1<: <... completed> + count +--------- + 4000000 +(1 row) + +-- And finally, make sure we don't enter error recursion on fail. +ALTER RESOURCE GROUP rg_oom_test SET memory_shared_quota 0; +ALTER +1: SELECT count(*) FROM gp_mock_cdbdispatchcommand(10000000); +ERROR: Out of memory + +DROP FUNCTION gp_mock_cdbdispatchcommand(amount int); +DROP +DROP ROLE role_oom_test; +DROP +DROP RESOURCE GROUP rg_oom_test; +DROP diff --git a/src/test/isolation2/output/resgroup/resgroup_parallel_retrieve.source b/src/test/isolation2/output/resgroup/resgroup_parallel_retrieve.source new file mode 100644 index 000000000000..9dcb375e68a5 --- /dev/null +++ b/src/test/isolation2/output/resgroup/resgroup_parallel_retrieve.source @@ -0,0 +1,326 @@ +-- start_matchsubs +-- m/ERROR: (.*) \([a-zA-Z_]+\.c:[0-9]+\)$/ +-- s/ERROR: (.*) \([a-zA-Z_]+\.c:[0-9]+\)$/ERROR: $1/ +-- end_matchsubs + +-- +-- Normal mode with GUC enabled. +-- + +!\retcode gpconfig -c gp_resource_group_retrieve -v on; +(exited with code 0) +!\retcode gpstop -u; +(exited with code 0) + +1: BEGIN; +BEGIN +1: DECLARE c1 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(2), i FROM t; +DECLARE +1: @post_run 'parse_endpoint_info 1 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c1'; + endpoint_id1 | token_id | host_id | port_id | READY + endpoint_id1 | token_id | host_id | port_id | READY + endpoint_id1 | token_id | host_id | port_id | READY +(3 rows) + +1: SELECT gp_inject_fault('switch_resgroup_ppc', 'skip', dbid) FROM gp_segment_configuration WHERE role = 'p' and content = 0; + gp_inject_fault +----------------- + Success: +(1 row) +1&: SELECT gp_wait_until_triggered_fault('switch_resgroup_ppc', 1, dbid) FROM gp_segment_configuration WHERE role = 'p' and content = 0; + +0R&: @pre_run 'set_endpoint_variable @ENDPOINT1': RETRIEVE 1 FROM ENDPOINT "@ENDPOINT1"; + +0U: SHOW gp_resource_group_retrieve; + gp_resource_group_retrieve +---------------------------- + on +(1 row) +0U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE 1%'; + rsgname | query +---------+------------------------------------------------ + rg | RETRIEVE 1 FROM ENDPOINT "endpoint_id1 "; +(1 row) + +0R<: <... completed> + pg_sleep | i +----------+--- + | 2 +(1 row) +1<: <... completed> + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) + +1: SELECT gp_inject_fault('all', 'reset', dbid) FROM gp_segment_configuration WHERE role = 'p' and content = 0; + gp_inject_fault +----------------- + Success: +(1 row) +1q: ... + +-- Retrieve on closed cursor. +0R: @pre_run 'set_endpoint_variable @ENDPOINT1': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT1"; +ERROR: endpoint is not available because the parallel retrieve cursor was aborted +0Rq: ... + +-- +-- Normal mode with GUC disabled. +-- + +!\retcode gpconfig -c gp_resource_group_retrieve -v off; +(exited with code 0) +!\retcode gpstop -u; +(exited with code 0) + +1: BEGIN; +BEGIN +1: DECLARE c2 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(2), i FROM t; +DECLARE +1: @post_run 'parse_endpoint_info 2 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c2'; + endpoint_id2 | token_id | host_id | port_id | READY + endpoint_id2 | token_id | host_id | port_id | READY + endpoint_id2 | token_id | host_id | port_id | READY +(3 rows) + +0R&: @pre_run 'set_endpoint_variable @ENDPOINT2': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT2"; + +0U: SHOW gp_resource_group_retrieve; + gp_resource_group_retrieve +---------------------------- + off +(1 row) +-- No resource groups assigned. +0U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE ALL%'; + rsgname | query +---------+-------------------------------------------------- + unknown | RETRIEVE ALL FROM ENDPOINT "endpoint_id2 "; +(1 row) + +0R<: <... completed> + pg_sleep | i +----------+--- + | 2 + | 3 + | 4 + | 7 +(4 rows) +0Rq: ... +1: ABORT; +ABORT + +!\retcode gpconfig -c gp_resource_group_retrieve -v on; +(exited with code 0) +!\retcode gpconfig -c gp_resource_group_bypass -v on; +(exited with code 0) +!\retcode gpstop -u; +(exited with code 0) + +-- +-- Bypass mode with GUC enabled. +-- + +1: BEGIN; +BEGIN + +1: DECLARE c3 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(2), i FROM t; +DECLARE +1: @post_run 'parse_endpoint_info 3 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c3'; + endpoint_id3 | token_id | host_id | port_id | READY + endpoint_id3 | token_id | host_id | port_id | READY + endpoint_id3 | token_id | host_id | port_id | READY +(3 rows) + +0R&: @pre_run 'set_endpoint_variable @ENDPOINT3': RETRIEVE 1 FROM ENDPOINT "@ENDPOINT3"; + +0U: SHOW gp_resource_group_bypass; + gp_resource_group_bypass +-------------------------- + on +(1 row) +0U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE 1%'; + rsgname | query +---------+------------------------------------------------ + rg | RETRIEVE 1 FROM ENDPOINT "endpoint_id3 "; +(1 row) + +0R<: <... completed> + pg_sleep | i +----------+--- + | 2 +(1 row) + +-- All subsequent queries are run with bypass mode. + +1: SELECT gp_inject_fault('switch_resgroup_ppc_bypass', 'skip', dbid), gp_inject_fault('switch_resgroup_ppc', 'error', dbid) FROM gp_segment_configuration WHERE role = 'p' and content = 0; + gp_inject_fault | gp_inject_fault +-----------------+----------------- + Success: | Success: +(1 row) +1&: SELECT gp_wait_until_triggered_fault('switch_resgroup_ppc_bypass', 1, dbid) FROM gp_segment_configuration WHERE role = 'p' and content = 0; + +0R: @pre_run 'set_endpoint_variable @ENDPOINT3': RETRIEVE 1 FROM ENDPOINT "@ENDPOINT3"; + pg_sleep | i +----------+--- + | 3 +(1 row) + +1<: <... completed> + gp_wait_until_triggered_fault +------------------------------- + Success: +(1 row) + +1: SELECT gp_inject_fault('all', 'reset', dbid) FROM gp_segment_configuration WHERE role = 'p' and content = 0; + gp_inject_fault +----------------- + Success: +(1 row) +1q: ... + +-- Retrieve on closed cursor with bypass mode. +0R: @pre_run 'set_endpoint_variable @ENDPOINT3': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT3"; +ERROR: endpoint is not available because the parallel retrieve cursor was aborted +0Rq: ... + +!\retcode gpconfig -r gp_resource_group_bypass; +(exited with code 0) +!\retcode gpstop -u; +(exited with code 0) + +-- +-- Multiple retrieve sessions sharing slot. +-- + +1: BEGIN; +BEGIN + +1: DECLARE c4 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(3), i FROM t; +DECLARE +1: @post_run 'parse_endpoint_info 4 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c4'; + endpoint_id4 | token_id | host_id | port_id | READY + endpoint_id4 | token_id | host_id | port_id | READY + endpoint_id4 | token_id | host_id | port_id | READY +(3 rows) +1: DECLARE c5 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(3), i FROM t; +DECLARE +1: @post_run 'parse_endpoint_info 5 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c5'; + endpoint_id5 | token_id | host_id | port_id | READY + endpoint_id5 | token_id | host_id | port_id | READY + endpoint_id5 | token_id | host_id | port_id | READY +(3 rows) +1: DECLARE c6 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(3), i FROM t; +DECLARE +1: @post_run 'parse_endpoint_info 6 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c6'; + endpoint_id6 | token_id | host_id | port_id | READY + endpoint_id6 | token_id | host_id | port_id | READY + endpoint_id6 | token_id | host_id | port_id | READY +(3 rows) + +0R&: @pre_run 'set_endpoint_variable @ENDPOINT4': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT4"; +1R&: @pre_run 'set_endpoint_variable @ENDPOINT5': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT5"; +2R&: @pre_run 'set_endpoint_variable @ENDPOINT6': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT6"; + +-- All should have the same resource group. +0U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE ALL%'; + rsgname | query +---------+-------------------------------------------------- + rg | RETRIEVE ALL FROM ENDPOINT "endpoint_id4 "; +(1 row) +1U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE ALL%'; + rsgname | query +---------+-------------------------------------------------- + rg | RETRIEVE ALL FROM ENDPOINT "endpoint_id5 "; +(1 row) +2U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE ALL%'; + rsgname | query +---------+-------------------------------------------------- + rg | RETRIEVE ALL FROM ENDPOINT "endpoint_id6 "; +(1 row) + +0R<: <... completed> + pg_sleep | i +----------+--- + | 2 + | 3 + | 4 + | 7 +(4 rows) +1R<: <... completed> + pg_sleep | i +----------+--- + | 1 +(1 row) +2R<: <... completed> + pg_sleep | i +----------+--- + | 5 + | 6 +(2 rows) + +0Rq: ... + +1: COMMIT; +COMMIT +1q: ... + +-- +-- GUC value must be the same on segments and on the master. +-- + +!\retcode gpconfig -c gp_resource_group_retrieve -v on -m off; +(exited with code 1) + +--- +--- Moving resource group should move the retrieve sessions as well. +--- + +1: BEGIN; +BEGIN + +1: DECLARE c7 PARALLEL RETRIEVE CURSOR FOR SELECT pg_sleep(5), i FROM t; +DECLARE +1: @post_run 'parse_endpoint_info 7 1 2 3 4': SELECT endpointname, auth_token, hostname, port, state FROM gp_get_endpoints() WHERE cursorname = 'c7'; + endpoint_id7 | token_id | host_id | port_id | READY + endpoint_id7 | token_id | host_id | port_id | READY + endpoint_id7 | token_id | host_id | port_id | READY +(3 rows) + +0R&: @pre_run 'set_endpoint_variable @ENDPOINT7': RETRIEVE ALL FROM ENDPOINT "@ENDPOINT7"; + +0U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE ALL%'; + rsgname | query +---------+-------------------------------------------------- + rg | RETRIEVE ALL FROM ENDPOINT "endpoint_id7 "; +(1 row) + +2: SET ROLE r; +SET +2: SELECT gp_toolkit.pg_resgroup_move_query(pid, 'rg2') FROM pg_stat_activity WHERE rsgname = 'rg'; + pg_resgroup_move_query +------------------------ + t +(1 row) + +0U: SELECT rsgname, query FROM pg_stat_activity WHERE query LIKE 'RETRIEVE ALL%'; + rsgname | query +---------+-------------------------------------------------- + rg2 | RETRIEVE ALL FROM ENDPOINT "endpoint_id7 "; +(1 row) + +0R<: <... completed> + pg_sleep | i +----------+--- + | 2 + | 3 + | 4 + | 7 +(4 rows) + +1: ABORT; +ABORT + +1q: ... +0Rq: ... +0Uq: ... diff --git a/src/test/isolation2/output/resgroup/resgroup_startup_memory.source b/src/test/isolation2/output/resgroup/resgroup_startup_memory.source index 5880df12ab35..527190f24f0a 100644 --- a/src/test/isolation2/output/resgroup/resgroup_startup_memory.source +++ b/src/test/isolation2/output/resgroup/resgroup_startup_memory.source @@ -9,12 +9,12 @@ drop resource group rg2; create extension if not exists gp_inject_fault; CREATE -create or replace function resGroupPalloc(float) returns int as '/home/gpadmin/gpdb_src/src/test/isolation2/../regress/regress.so', 'resGroupPalloc' language C reads sql data; +create or replace function resGroupPalloc(float) returns int as '@abs_builddir@/../../regress/regress@DLSUFFIX@', 'resGroupPalloc' language C reads sql data; CREATE create or replace function hold_memory_by_percent_on_qe(float) returns int as $$ select resGroupPalloc($1) from gp_dist_random('gp_id') $$ language sql; CREATE -create or replace function repeatPalloc(int, int) returns int as '/home/gpadmin/gpdb_src/src/test/isolation2/../regress/regress.so', 'repeatPalloc' language C reads sql data; +create or replace function repeatPalloc(int, int) returns int as '@abs_builddir@/../../regress/regress@DLSUFFIX@', 'repeatPalloc' language C reads sql data; CREATE -- In the next test, we need to be able to allocate 100% of the available diff --git a/src/test/isolation2/sql/drop_rename.sql b/src/test/isolation2/sql/drop_rename.sql index 6cd6115f036c..ecede5a8f531 100644 --- a/src/test/isolation2/sql/drop_rename.sql +++ b/src/test/isolation2/sql/drop_rename.sql @@ -54,3 +54,37 @@ 3<: 2<: 2:select count(*) from t3; + +-- Ensure DROP doesn't make inconsistency +-- start_ignore +drop table if exists t4; +-- end_ignore +select gp_inject_fault('wait_before_drop_dispatch', 'suspend', 1); +1&:drop table if exists t4; +create table t4 (a int, b text) distributed by (a); +select gp_wait_until_triggered_fault('wait_before_drop_dispatch', 1, 1); +select gp_inject_fault('wait_before_drop_dispatch', 'reset', 1); +1<: +drop table t4; + +-- start_ignore +drop type if exists t5; +-- end_ignore +select gp_inject_fault('wait_before_drop_dispatch', 'suspend', 1); +1&:drop type if exists t5; +create type t5 as (a int, b text); +select gp_wait_until_triggered_fault('wait_before_drop_dispatch', 1, 1); +select gp_inject_fault('wait_before_drop_dispatch', 'reset', 1); +1<: +drop type t5; + +-- start_ignore +drop schema if exists t6; +-- end_ignore +select gp_inject_fault('wait_before_drop_dispatch', 'suspend', 1); +1&:drop schema if exists t6; +create schema t6; +select gp_wait_until_triggered_fault('wait_before_drop_dispatch', 1, 1); +select gp_inject_fault('wait_before_drop_dispatch', 'reset', 1); +1<: +drop schema t6; diff --git a/src/test/isolation2/sql/fts_segment_reset.sql b/src/test/isolation2/sql/fts_segment_reset.sql index 135e7891375d..9c618fc454ac 100644 --- a/src/test/isolation2/sql/fts_segment_reset.sql +++ b/src/test/isolation2/sql/fts_segment_reset.sql @@ -23,12 +23,34 @@ select gp_inject_fault_infinite('postmaster_delay_termination_bg_writer', 'skip', dbid) from gp_segment_configuration where role = 'p' and content = 0; +-- We need to set fault at the handler of abort signal from backend +-- so then we can wait until it is triggered. We need to do this because +-- sometimes process of calling abort() (which is issued by the injection +-- of 'panic' fault in the next lines of this test) and abortion itself can +-- take a long time to complete. So, sometimes this test can give unexpected +-- results, when you think that commands sended after issuing panic fault +-- should fail, but they are being executed without any errors. +select gp_inject_fault('backend_abort_handling', 'skip', dbid) +from gp_segment_configuration where role = 'p' and content = 0; + -- Now bring down primary of seg0. There're a lot of ways to do that, in order -- to better emulate a real-world scnarios we're injecting a PANIC to do that. 1:select gp_inject_fault('start_prepare', 'panic', dbid) from gp_segment_configuration where role = 'p' AND content = 0; 1&:create table fts_reset_t(a int); +-- We now wait till our seg0 will start reaping it's childs and resetting. +-- We can ignore the results of this command, because it can throw 3 things: +-- error because we couldn't send command because seg0 already restarting; +-- error because reaper killed backend on seg0 because it started reaping +-- backends (previous panic fault injection) +-- no error, because we managed to overrun reaper and sendeed results +-- of wait_until_triggered back +-- start_ignore +select gp_wait_until_triggered_fault('backend_abort_handling', 1, dbid) +from gp_segment_configuration where role = 'p' and content = 0; +-- end_ignore + -- This should fail due to the seg0 in reset mode 2&:create table fts_reset_t2(a int); diff --git a/src/test/isolation2/sql/intra-grant-inplace-db.sql b/src/test/isolation2/sql/intra-grant-inplace-db.sql index 8b9f90ac2a0d..9c80ea4378d0 100644 --- a/src/test/isolation2/sql/intra-grant-inplace-db.sql +++ b/src/test/isolation2/sql/intra-grant-inplace-db.sql @@ -31,3 +31,37 @@ DROP ROLE regress_temp_grantee; 1q: 2q: 3q: + +-- Same test as the above, except the GRANT transaction commits before the +-- second transaction check the wait gxid, it should get the gxid from +-- pg_distributedlog instead of the procarray. +CREATE ROLE regress_temp_grantee; + +3: CREATE TEMPORARY TABLE frozen_witness (x xid) distributed by (x); +-- observe datfrozenxid +3: INSERT INTO frozen_witness SELECT datfrozenxid FROM pg_database WHERE datname = current_catalog; +1: BEGIN; +-- heap_update(pg_database) +1: GRANT TEMP ON DATABASE isolation2test TO regress_temp_grantee; +-- suspend before get 'wait gxid' +2: SELECT gp_inject_fault('before_get_distributed_xid', 'suspend', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; +-- inplace update +2&: VACUUM (FREEZE); +3: SELECT gp_wait_until_triggered_fault('before_get_distributed_xid', 1, dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; +1: COMMIT; +3: INSERT INTO frozen_witness SELECT datfrozenxid FROM pg_database WHERE datname = current_catalog; +3: SELECT gp_inject_fault('before_get_distributed_xid', 'reset', dbid) FROM gp_segment_configuration WHERE role='p' AND content=0; + +2<: +-- Save the result in an environment variable. +-- We get the raw xid to be sure that the age in the next query will be executed on the coordinator. +3: @post_run 'TOKEN=`echo "${RAW_STR}" | awk \'NR==3\' | awk \'{print $1}\'` && echo ""' : SELECT min(x::varchar::int) FROM frozen_witness; +-- observe datfrozenxid +3: @pre_run 'echo "${RAW_STR}" | sed "s#@TOKEN#${TOKEN}#"': SELECT 'datfrozenxid retreated' FROM pg_database WHERE datname = current_catalog AND age(datfrozenxid) > age('@TOKEN'::xid); + +REVOKE ALL ON DATABASE isolation2test FROM regress_temp_grantee; +DROP ROLE regress_temp_grantee; + +1q: +2q: +3q: diff --git a/src/test/isolation2/sql/standby_replay_dtx_info.sql b/src/test/isolation2/sql/standby_replay_dtx_info.sql index d4757a498eb9..0dbce5b81db4 100644 --- a/src/test/isolation2/sql/standby_replay_dtx_info.sql +++ b/src/test/isolation2/sql/standby_replay_dtx_info.sql @@ -72,4 +72,26 @@ select wait_for_standby_replay(1200); select gp_inject_fault_infinite('standby_gxacts_overflow', 'reset', dbid) from gp_segment_configuration where content = -1 and role = 'm'; drop table test_dtx_standby_tbl; + +-- Verify that max_tm_gxacts is reset from 1. In order to do so, +-- create 2 distributed transactions that are postponed before the point where +-- 'distributed forget' is inserted into the WAL, and check that standby can +-- successfully replay the WAL. +select gp_inject_fault_infinite('dtm_before_insert_forget_comitted', 'suspend', dbid) +from gp_segment_configuration where role = 'p' and content = -1; + +1&: create table test1(a int) distributed by (a); +2&: create table test2(a int) distributed by (a); + +-- Ensure that replay on standby is ok. +select wait_for_standby_replay(1200); + +select gp_inject_fault_infinite('dtm_before_insert_forget_comitted', 'reset', dbid) +from gp_segment_configuration where role = 'p' and content = -1; + +1<: +2<: + +drop table test1; +drop table test2; drop function wait_for_standby_replay(int); diff --git a/src/test/isolation2/sql_isolation_testcase.py b/src/test/isolation2/sql_isolation_testcase.py old mode 100644 new mode 100755 index 7e32fe6c7a27..95134c1ff0f1 --- a/src/test/isolation2/sql_isolation_testcase.py +++ b/src/test/isolation2/sql_isolation_testcase.py @@ -1,3 +1,5 @@ +#!/usr/bin/env python + """ Copyright (c) 2004-Present Pivotal Software, Inc. diff --git a/src/test/recovery/t/020_archive_status.pl b/src/test/recovery/t/020_archive_status.pl index a21dbf3781ff..c2d78f7e72ce 100644 --- a/src/test/recovery/t/020_archive_status.pl +++ b/src/test/recovery/t/020_archive_status.pl @@ -5,7 +5,7 @@ use warnings; use PostgresNode; use TestLib; -use Test::More tests => 7; +use Test::More tests => 16; use Config; my $primary = get_new_node('master'); @@ -106,3 +106,127 @@ $segment_name_1, "archive success reported in pg_stat_archiver for WAL segment $segment_name_1" ); + +# Create some WAL activity and a new checkpoint so as the next standby can +# create a restartpoint. As this standby starts in crash recovery because +# of the cold backup taken previously, it needs a clean restartpoint to deal +# with existing status files. +$primary->safe_psql( + 'postgres', q{ + INSERT INTO mine SELECT generate_series(10,20) AS x; + SELECT pg_switch_xlog(); + CHECKPOINT; +}); +my $segment_name_2 = $primary->safe_psql('postgres', + q{SELECT pg_xlogfile_name(pg_current_xlog_location())}); +my $segment_path_2 = "pg_xlog/archive_status/$segment_name_2"; +my $segment_path_2_ready = "$segment_path_2.ready"; +my $segment_path_2_done = "$segment_path_2.done"; + +# Test standby with archive_mode = on. +my $standby1 = get_new_node('standby'); +$standby1->init_from_backup($primary, 'backup', has_restoring => 1); +$standby1->append_conf('postgresql.conf', q{ +archive_mode = on +wal_keep_segments = 0 +}); +my $standby1_data = $standby1->data_dir; +$standby1->start; +# First restartpoint +$standby1->safe_psql('postgres', q{CHECKPOINT}); + +# Segments are cleaned after the second restartpoint, so create a second +# one. +$primary->safe_psql( + 'postgres', q{ + INSERT INTO mine SELECT generate_series(21,30) AS x; + CHECKPOINT; + SELECT pg_switch_xlog(); +}); + +# Make sure that the standby has caught here. +my $primary_lsn = $primary->safe_psql('postgres', + q{SELECT pg_current_xlog_location()}); +$standby1->poll_query_until('postgres', + qq{ SELECT pg_xlog_location_diff(pg_last_xlog_replay_location(), '$primary_lsn') >= 0 }) + or die "Timed out while waiting for xlog replay"; + +# Second restartpoint. +$standby1->safe_psql('postgres', q{CHECKPOINT}); + +# Recovery with archive_mode=on removed .ready signal files inherited +# from backup after two checkpoints. Note that this WAL segment +# existed in the backup. +ok( !-f "$standby1_data/$segment_path_1_ready", + ".ready file for WAL segment $segment_name_1 present in backup removed with archive_mode=on on standby" +); + +# Recovery with archive_mode=on should not create .ready files. +# Note that this segment did not exist in the backup. +ok( !-f "$standby1_data/$segment_path_2_ready", + ".ready file for WAL segment $segment_name_2 not created on standby when archive_mode=on on standby" +); + +# Recovery with archive_mode = on creates .done files. +ok( -f "$standby1_data/$segment_path_2_done", + ".done file for WAL segment $segment_name_2 created when archive_mode=on on standby" +); + +# Test recovery with archive_mode = always, which should always keep +# .ready files if archiving is enabled, though here we want the archive +# command to fail to persist the .ready files. Note that this node +# has inherited the archive command of the previous cold backup that +# will cause archiving failures. +my $standby2 = get_new_node('standby2'); +$standby2->init_from_backup($primary, 'backup', has_restoring => 1); +$standby2->append_conf('postgresql.conf', 'archive_mode = always'); +my $standby2_data = $standby2->data_dir; +$standby2->start; + +$standby2->safe_psql('postgres', q{CHECKPOINT}); + +ok( -f "$standby2_data/$segment_path_1_ready", + ".ready file for WAL segment $segment_name_1 existing in backup is kept with archive_mode=always on standby" +); + +ok( -f "$standby2_data/$segment_path_2_ready", + ".ready file for WAL segment $segment_name_2 created with archive_mode=always on standby" +); + +# Reset statistics of the archiver for the next checks. +$standby2->safe_psql('postgres', q{SELECT pg_stat_reset_shared('archiver')}); + +# Now crash the cluster to check that recovery step does not +# remove non-archived WAL segments on a standby where archiving +# is enabled. +$standby2->stop('immediate'); +$standby2->start; + +ok( -f "$standby2_data/$segment_path_1_ready", + "WAL segment still ready to archive after crash recovery on standby with archive_mode=always" +); + +# Allow WAL archiving again, and wait for the segments to be archived. +$standby2->safe_psql( + 'postgres', q{ + ALTER SYSTEM RESET archive_command; + SELECT pg_reload_conf(); +}); +$standby2->poll_query_until('postgres', + qq{SELECT last_archived_wal = '$segment_name_2' FROM pg_stat_archiver}) + or die "Timed out while waiting for archiving to finish"; + +is( $standby2->safe_psql( + 'postgres', q{SELECT archived_count FROM pg_stat_archiver}), + '3', + 'correct number of WAL segments archived from standby'); + +ok( !-f "$standby2_data/$segment_path_1_ready" + && !-f "$standby2_data/$segment_path_2_ready", + ".ready files removed after archive success with archive_mode=always on standby" +); + +ok( -f "$standby2_data/$segment_path_1_done" + && -f "$standby2_data/$segment_path_2_done", + ".done files created after archive success with archive_mode=always on standby" +); diff --git a/src/test/regress/expected/alter_table_aocs.out b/src/test/regress/expected/alter_table_aocs.out index 5a118b0a0806..d1f2400d6ce5 100644 --- a/src/test/regress/expected/alter_table_aocs.out +++ b/src/test/regress/expected/alter_table_aocs.out @@ -895,3 +895,68 @@ SELECT * FROM gp_toolkit.__gp_aocsseg('aoco_insert_empty_row'::regclass); --------+-------+------------+----------------+----------+-----+------------------+----------+---------------+------- (0 rows) +-- test case: Ensure that reads don't fail after aborting an add column + insert operation and we don't project the aborted column +CREATE TABLE aocs_addcol_abort(a int, b int) WITH (APPENDONLY=TRUE, ORIENTATION=COLUMN); +INSERT INTO aocs_addcol_abort SELECT i,i FROM generate_series(1,10)i; +BEGIN; +ALTER TABLE aocs_addcol_abort ADD COLUMN c int; +INSERT INTO aocs_addcol_abort SELECT i,i,i FROM generate_series(1,10)i; +-- check state of aocsseg for entries of add column + insert +SELECT * FROM gp_toolkit.__gp_aocsseg('aocs_addcol_abort') ORDER BY column_num; + gp_tid | segno | column_num | physical_segno | tupcount | eof | eof_uncompressed | modcount | formatversion | state +--------+-------+------------+----------------+----------+-----+------------------+----------+---------------+------- + (0,4) | 1 | 0 | 1 | 20 | 0 | 0 | 3 | 3 | 1 + (0,4) | 1 | 1 | 129 | 20 | 0 | 0 | 3 | 3 | 1 + (0,4) | 1 | 2 | 257 | 20 | 0 | 0 | 3 | 3 | 1 +(3 rows) + +SELECT * FROM aocs_addcol_abort; + a | b | c +----+----+---- + 5 | 5 | 5 + 6 | 6 | 6 + 9 | 9 | 9 + 10 | 10 | 10 + 5 | 5 | + 6 | 6 | + 9 | 9 | + 10 | 10 | + 1 | 1 | 1 + 1 | 1 | + 2 | 2 | 2 + 3 | 3 | 3 + 4 | 4 | 4 + 7 | 7 | 7 + 8 | 8 | 8 + 2 | 2 | + 3 | 3 | + 4 | 4 | + 7 | 7 | + 8 | 8 | +(20 rows) + +ABORT; +-- check state of aocsseg if entries for new column are rolled back correctly +SELECT * FROM gp_toolkit.__gp_aocsseg('aocs_addcol_abort') ORDER BY column_num; + gp_tid | segno | column_num | physical_segno | tupcount | eof | eof_uncompressed | modcount | formatversion | state +--------+-------+------------+----------------+----------+-----+------------------+----------+---------------+------- + (0,2) | 1 | 0 | 1 | 10 | 0 | 0 | 1 | 3 | 1 + (0,2) | 1 | 1 | 129 | 10 | 0 | 0 | 1 | 3 | 1 +(2 rows) + +SELECT * FROM aocs_addcol_abort; + a | b +----+---- + 5 | 5 + 6 | 6 + 9 | 9 + 10 | 10 + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 7 | 7 + 8 | 8 +(10 rows) + +DROP TABLE aocs_addcol_abort; diff --git a/src/test/regress/expected/bfv_joins.out b/src/test/regress/expected/bfv_joins.out index 82f9d718f6fe..4919518bf574 100644 --- a/src/test/regress/expected/bfv_joins.out +++ b/src/test/regress/expected/bfv_joins.out @@ -4127,6 +4127,58 @@ select * from r_table2 where ra2 in ( select a from l_table join r_table1 on b = 1 | 1 (1 row) +-- Testcase for hash join rescan clearing batch files for outer subplan +truncate l_table; +truncate r_table1; +insert into l_table select i, i%100 from generate_series(1, 20000) i; +insert into r_table1 select i%100, i from generate_series(1, 10000) i; +insert into r_table1 select i%100, i from generate_series(1, 10000) i; +analyze l_table; +analyze r_table1; +set statement_mem="1MB"; +explain analyze select * from r_table2 where ra2 in (select ra1 from l_table join r_table1 on b = rb1); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------ + Gather Motion 1:1 (slice1; segments: 1) (cost=30000000473.00..30000001205.61 rows=16 width=8) (actual time=73.649..73.651 rows=2 loops=1) + -> Nested Loop Semi Join (cost=30000000473.00..30000001205.61 rows=16 width=8) (actual time=29.419..73.334 rows=2 loops=1) + Join Filter: (r_table2.ra2 = r_table1.ra1) + -> Seq Scan on r_table2 (cost=10000000000.00..10000000001.02 rows=2 width=8) (actual time=0.003..0.004 rows=2 loops=1) + -> Hash Join (cost=20000000473.00..20000001196.00 rows=40000 width=4) (actual time=5.144..34.441 rows=20807 loops=2) + Hash Cond: (l_table.b = r_table1.rb1) + Extra Text: Initial batch 0: + Wrote 198K bytes to inner workfile. + Wrote 111K bytes to outer workfile. + Work file set: 2 files (0 compressed), avg file size 147456, compression buffer size 0 bytes + Hash chain length 3.4 avg, 14 max, using 2907 of 4096 buckets. Skipped 1 empty batches. + -> Seq Scan on l_table (cost=10000000000.00..10000000223.00 rows=20000 width=4) (actual time=0.007..15.150 rows=20000 loops=2) + -> Hash (cost=10000000223.00..10000000223.00 rows=6667 width=8) (actual time=10.240..10.240 rows=20000 loops=1) + -> Seq Scan on r_table1 (cost=10000000000.00..10000000223.00 rows=20000 width=8) (actual time=0.013..3.960 rows=20000 loops=1) + Planning time: 1.497 ms + (slice0) Executor memory: 123K bytes. + * (slice1) Executor memory: 1228K bytes (seg2). Work_mem: 525K bytes max, 575K bytes wanted. + Memory used: 1024kB + Memory wanted: 1174kB + Optimizer: Postgres query optimizer + Execution time: 74.293 ms +(21 rows) + +select * from r_table2 where ra2 in (select ra1 from l_table join r_table1 on b = rb1); + ra2 | rb2 +-----+----- + 11 | 11 + 1 | 1 +(2 rows) + +set gp_workfile_compression=on; +select * from r_table2 where ra2 in (select ra1 from l_table join r_table1 on b = rb1); + ra2 | rb2 +-----+----- + 11 | 11 + 1 | 1 +(2 rows) + +reset gp_workfile_compression; +reset statement_mem; reset optimizer; reset enable_nestloop; reset enable_bitmapscan; @@ -4369,6 +4421,26 @@ select from (values ('')) tmp(b) join lateral (1 row) drop table t1; +-- test that empty table gets hashed instead of a bigger table +create table big_table(s smallint) distributed replicated; +create table empty_table(i int) distributed replicated; +insert into big_table select generate_series(1, 10000); +analyze big_table; +analyze empty_table; +explain select * from big_table, empty_table where s = i; + QUERY PLAN +------------------------------------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) (cost=1.01..150.65 rows=14 width=6) + -> Hash Join (cost=1.01..150.65 rows=14 width=6) + Hash Cond: (big_table.s = empty_table.i) + -> Seq Scan on big_table (cost=0.00..112.00 rows=10000 width=2) + -> Hash (cost=1.00..1.00 rows=1 width=4) + -> Seq Scan on empty_table (cost=0.00..1.00 rows=1 width=4) + Optimizer: Postgres query optimizer +(7 rows) + +drop table big_table; +drop table empty_table; -- Clean up. None of the objects we create are very interesting to keep around. reset search_path; set client_min_messages='warning'; diff --git a/src/test/regress/expected/bfv_joins_optimizer.out b/src/test/regress/expected/bfv_joins_optimizer.out index 2c71caada8a4..505cd9b14366 100644 --- a/src/test/regress/expected/bfv_joins_optimizer.out +++ b/src/test/regress/expected/bfv_joins_optimizer.out @@ -3368,30 +3368,30 @@ INNER JOIN member_subgroup ON member_group.group_id = member_subgroup.group_id LEFT OUTER JOIN region ON (member_group.group_id IN (12,13,14,15) AND member_subgroup.subgroup_name = region.county_name); - QUERY PLAN ---------------------------------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------------------- Gather Motion 3:1 (slice5; segments: 3) - -> Hash Left Join - Hash Cond: (member_subgroup.subgroup_name = (region.county_name)::text) + -> Hash Right Join + Hash Cond: ((region.county_name)::text = member_subgroup.subgroup_name) Join Filter: (member_group."group_id" = ANY ('{12,13,14,15}'::integer[])) - -> Redistribute Motion 3:3 (slice3; segments: 3) - Hash Key: member_subgroup.subgroup_name - -> Hash Join - Hash Cond: (member_group."group_id" = member."group_id") - -> Seq Scan on member_group - -> Hash - -> Redistribute Motion 3:3 (slice2; segments: 3) - Hash Key: member_subgroup."group_id" - -> Hash Join - Hash Cond: (member."group_id" = member_subgroup."group_id") - -> Seq Scan on member - -> Hash - -> Broadcast Motion 3:3 (slice1; segments: 3) - -> Seq Scan on member_subgroup + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: region.county_name + -> Seq Scan on region -> Hash -> Redistribute Motion 3:3 (slice4; segments: 3) - Hash Key: region.county_name - -> Seq Scan on region + Hash Key: member_subgroup.subgroup_name + -> Hash Join + Hash Cond: (member_group."group_id" = member."group_id") + -> Seq Scan on member_group + -> Hash + -> Redistribute Motion 3:3 (slice3; segments: 3) + Hash Key: member_subgroup."group_id" + -> Hash Join + Hash Cond: (member."group_id" = member_subgroup."group_id") + -> Seq Scan on member + -> Hash + -> Broadcast Motion 3:3 (slice2; segments: 3) + -> Seq Scan on member_subgroup Optimizer: Pivotal Optimizer (GPORCA) (23 rows) @@ -4118,6 +4118,58 @@ select * from r_table2 where ra2 in ( select a from l_table join r_table1 on b = 1 | 1 (1 row) +-- Testcase for hash join rescan clearing batch files for outer subplan +truncate l_table; +truncate r_table1; +insert into l_table select i, i%100 from generate_series(1, 20000) i; +insert into r_table1 select i%100, i from generate_series(1, 10000) i; +insert into r_table1 select i%100, i from generate_series(1, 10000) i; +analyze l_table; +analyze r_table1; +set statement_mem="1MB"; +explain analyze select * from r_table2 where ra2 in (select ra1 from l_table join r_table1 on b = rb1); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------ + Gather Motion 1:1 (slice1; segments: 1) (cost=30000000473.00..30000001205.61 rows=16 width=8) (actual time=73.649..73.651 rows=2 loops=1) + -> Nested Loop Semi Join (cost=30000000473.00..30000001205.61 rows=16 width=8) (actual time=29.419..73.334 rows=2 loops=1) + Join Filter: (r_table2.ra2 = r_table1.ra1) + -> Seq Scan on r_table2 (cost=10000000000.00..10000000001.02 rows=2 width=8) (actual time=0.003..0.004 rows=2 loops=1) + -> Hash Join (cost=20000000473.00..20000001196.00 rows=40000 width=4) (actual time=5.144..34.441 rows=20807 loops=2) + Hash Cond: (l_table.b = r_table1.rb1) + Extra Text: Initial batch 0: + Wrote 198K bytes to inner workfile. + Wrote 111K bytes to outer workfile. + Work file set: 2 files (0 compressed), avg file size 147456, compression buffer size 0 bytes + Hash chain length 3.4 avg, 14 max, using 2907 of 4096 buckets. Skipped 1 empty batches. + -> Seq Scan on l_table (cost=10000000000.00..10000000223.00 rows=20000 width=4) (actual time=0.007..15.150 rows=20000 loops=2) + -> Hash (cost=10000000223.00..10000000223.00 rows=6667 width=8) (actual time=10.240..10.240 rows=20000 loops=1) + -> Seq Scan on r_table1 (cost=10000000000.00..10000000223.00 rows=20000 width=8) (actual time=0.013..3.960 rows=20000 loops=1) + Planning time: 1.497 ms + (slice0) Executor memory: 123K bytes. + * (slice1) Executor memory: 1228K bytes (seg2). Work_mem: 525K bytes max, 575K bytes wanted. + Memory used: 1024kB + Memory wanted: 1174kB + Optimizer: Postgres query optimizer + Execution time: 74.293 ms +(21 rows) + +select * from r_table2 where ra2 in (select ra1 from l_table join r_table1 on b = rb1); + ra2 | rb2 +-----+----- + 11 | 11 + 1 | 1 +(2 rows) + +set gp_workfile_compression=on; +select * from r_table2 where ra2 in (select ra1 from l_table join r_table1 on b = rb1); + ra2 | rb2 +-----+----- + 11 | 11 + 1 | 1 +(2 rows) + +reset gp_workfile_compression; +reset statement_mem; reset optimizer; reset enable_nestloop; reset enable_bitmapscan; @@ -4360,6 +4412,26 @@ select from (values ('')) tmp(b) join lateral (1 row) drop table t1; +-- test that empty table gets hashed instead of a bigger table +create table big_table(s smallint) distributed replicated; +create table empty_table(i int) distributed replicated; +insert into big_table select generate_series(1, 10000); +analyze big_table; +analyze empty_table; +explain select * from big_table, empty_table where s = i; + QUERY PLAN +------------------------------------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) (cost=0.00..863.96 rows=1 width=6) + -> Hash Join (cost=0.00..863.96 rows=1 width=6) + Hash Cond: ((big_table.s)::integer = empty_table.i) + -> Seq Scan on big_table (cost=0.00..431.18 rows=10000 width=2) + -> Hash (cost=431.00..431.00 rows=1 width=4) + -> Seq Scan on empty_table (cost=0.00..431.00 rows=1 width=4) + Optimizer: Pivotal Optimizer (GPORCA) +(7 rows) + +drop table big_table; +drop table empty_table; -- Clean up. None of the objects we create are very interesting to keep around. reset search_path; set client_min_messages='warning'; diff --git a/src/test/regress/expected/bfv_oom.out b/src/test/regress/expected/bfv_oom.out new file mode 100644 index 000000000000..76b295316e9a --- /dev/null +++ b/src/test/regress/expected/bfv_oom.out @@ -0,0 +1,40 @@ +-- start_matchsubs +-- m/WARNING:.*Any temporary tables for this session have been dropped because the gang was disconnected/ +-- s/session id \=\s*\d+/session id \= DUMMY/gm +-- end_matchsubs +CREATE TEMP TABLE t1(); +NOTICE: Table doesn't have 'DISTRIBUTED BY' clause, and no column type is suitable for a distribution key. Creating a NULL policy entry. +WARNING: creating a table with no columns. +-- Emulate an OOM error and throw FATAL on any palloc() call. +SELECT gp_inject_fault('cdb_freelist_append_oom', 'skip', dbid), + gp_inject_fault('fatal_on_palloc_oom', 'skip', dbid) + FROM gp_segment_configuration + WHERE role = 'p' AND content = -1; + gp_inject_fault | gp_inject_fault +-----------------+----------------- + Success: | Success: +(1 row) + +-- We should gracefully recover instead of entering recursion, getting SIGSEGV, +-- or trying to allocate any more memory. +DO $$ + DECLARE + rec1 RECORD; + BEGIN + FOR rec1 IN SELECT * FROM t1 + LOOP + NULL; + END LOOP; + END; +$$; +WARNING: Any temporary tables for this session have been dropped because the gang was disconnected (session id = DUMMY) +ERROR: out of memory was emulated +CONTEXT: PL/pgSQL function inline_code_block line 5 at FOR over SELECT rows +SELECT gp_inject_fault('all', 'reset', dbid) + FROM gp_segment_configuration + WHERE role = 'p' AND content = -1; + gp_inject_fault +----------------- + Success: +(1 row) + diff --git a/src/test/regress/expected/bfv_subquery_optimizer.out b/src/test/regress/expected/bfv_subquery_optimizer.out index 0430d10952e4..81f6e88611bb 100644 --- a/src/test/regress/expected/bfv_subquery_optimizer.out +++ b/src/test/regress/expected/bfv_subquery_optimizer.out @@ -507,20 +507,22 @@ analyze t1; -- Function Scan explain select count(*) from pg_backend_pid() b(a) where b.a % 100000 in (select a from t1); - QUERY PLAN ------------------------------------------------------------------------------------- - Aggregate (cost=0.00..450.95 rows=1 width=8) - -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..450.95 rows=1 width=1) - -> Hash Semi Join (cost=0.00..450.95 rows=1 width=1) - Hash Cond: ((b % 100000) = a) - -> Result (cost=0.00..0.00 rows=1 width=4) - -> Result (cost=0.00..0.00 rows=1 width=4) - -> Result (cost=0.00..0.00 rows=1 width=4) + QUERY PLAN +----------------------------------------------------------------------------------------------------------- + Aggregate (cost=0.00..450.99 rows=1 width=8) + -> GroupAggregate (cost=0.00..450.99 rows=1 width=1) + Group Key: + -> Sort (cost=0.00..450.99 rows=1 width=1) + Sort Key: + -> Hash Join (cost=0.00..450.99 rows=1 width=1) + Hash Cond: (a = (b % 100000)) + -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..433.36 rows=100000 width=4) + -> Seq Scan on t1 (cost=0.00..431.62 rows=33334 width=4) + -> Hash (cost=0.00..0.00 rows=1 width=5) + -> Result (cost=0.00..0.00 rows=1 width=5) -> Result (cost=0.00..0.00 rows=1 width=1) - -> Hash (cost=431.62..431.62 rows=33334 width=4) - -> Seq Scan on t1 (cost=0.00..431.62 rows=33334 width=4) Optimizer: Pivotal Optimizer (GPORCA) -(11 rows) +(13 rows) select count(*) from pg_backend_pid() b(a) where b.a % 100000 in (select a from t1); count @@ -537,10 +539,10 @@ explain select count(*) from ( values :lots_of_values ) as b(a) where b.a % 100000 in (select a from t1); QUERY PLAN --------------------------------------------------------------------------------------------------- - Aggregate (cost=0.00..443.14 rows=1 width=8) - -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..443.14 rows=1 width=8) - -> Aggregate (cost=0.00..443.14 rows=1 width=8) - -> Hash Semi Join (cost=0.00..443.14 rows=22000 width=1) + Aggregate (cost=0.00..446.47 rows=1 width=8) + -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..446.47 rows=1 width=8) + -> Aggregate (cost=0.00..446.47 rows=1 width=8) + -> Hash Semi Join (cost=0.00..446.47 rows=22000 width=1) Hash Cond: (("Values".column1 % 100000) = t1.a) -> Result (cost=0.00..0.95 rows=22000 width=4) -> Result (cost=0.00..0.95 rows=22000 width=4) diff --git a/src/test/regress/expected/direct_dispatch.out b/src/test/regress/expected/direct_dispatch.out index 42e3ef6d97a3..b7c104c9e128 100644 --- a/src/test/regress/expected/direct_dispatch.out +++ b/src/test/regress/expected/direct_dispatch.out @@ -658,7 +658,6 @@ INFO: Distributed transaction command 'Distributed Commit Prepared' to ALL cont -- the tests will fail. drop table if exists bar_randDistr; NOTICE: table "bar_randdistr" does not exist, skipping -INFO: Distributed transaction command 'Distributed Commit (one-phase)' to ALL contents: 0 1 2 create table bar_randDistr(col1 int, col2 int) distributed randomly; INFO: Distributed transaction command 'Distributed Prepare' to ALL contents: 0 1 2 INFO: Distributed transaction command 'Distributed Commit Prepared' to ALL contents: 0 1 2 diff --git a/src/test/regress/expected/direct_dispatch_optimizer.out b/src/test/regress/expected/direct_dispatch_optimizer.out index 69fbfbd80c62..8e79cfcd792d 100644 --- a/src/test/regress/expected/direct_dispatch_optimizer.out +++ b/src/test/regress/expected/direct_dispatch_optimizer.out @@ -679,7 +679,6 @@ INFO: Distributed transaction command 'Distributed Commit Prepared' to ALL cont -- the tests will fail. drop table if exists bar_randDistr; NOTICE: table "bar_randdistr" does not exist, skipping -INFO: Distributed transaction command 'Distributed Commit (one-phase)' to ALL contents: 0 1 2 create table bar_randDistr(col1 int, col2 int) distributed randomly; INFO: Distributed transaction command 'Distributed Prepare' to ALL contents: 0 1 2 INFO: Distributed transaction command 'Distributed Commit Prepared' to ALL contents: 0 1 2 diff --git a/src/test/regress/expected/function_extensions.out b/src/test/regress/expected/function_extensions.out index 195f7681b14a..bcb2638838ac 100644 --- a/src/test/regress/expected/function_extensions.out +++ b/src/test/regress/expected/function_extensions.out @@ -751,3 +751,21 @@ select count(*) from (select * from (select pg_catalog.gp_acquire_sample_rows('t (1 row) drop table test_ao3; +-- Test initplan function referring the outer query. +-- The query below previously led to a SIGSEGV. +-- start_matchsubs +-- m/ \(subselect\.c:.*\)/ +-- s/ \(subselect\.c:.*\)// +-- end_matchsubs +create table test_table(a text); +create function test_function(param_in text) returns +table (param_out text) as +$function$ +select param_in; +$function$ +language sql execute on initplan; +create table tnew as +select * from test_table l join test_function(l.a) r on l.a = r.param_out; +ERROR: plan should not reference subplan's variable +drop function test_function(param_in text); +drop table test_table; diff --git a/src/test/regress/expected/function_extensions_optimizer.out b/src/test/regress/expected/function_extensions_optimizer.out index 91fac75190bd..20d42dc43404 100644 --- a/src/test/regress/expected/function_extensions_optimizer.out +++ b/src/test/regress/expected/function_extensions_optimizer.out @@ -753,3 +753,21 @@ select count(*) from (select * from (select pg_catalog.gp_acquire_sample_rows('t (1 row) drop table test_ao3; +-- Test initplan function referring the outer query. +-- The query below previously led to a SIGSEGV. +-- start_matchsubs +-- m/ \(subselect\.c:.*\)/ +-- s/ \(subselect\.c:.*\)// +-- end_matchsubs +create table test_table(a text); +create function test_function(param_in text) returns +table (param_out text) as +$function$ +select param_in; +$function$ +language sql execute on initplan; +create table tnew as +select * from test_table l join test_function(l.a) r on l.a = r.param_out; +ERROR: plan should not reference subplan's variable +drop function test_function(param_in text); +drop table test_table; diff --git a/src/test/regress/expected/gp_cast.out b/src/test/regress/expected/gp_cast.out new file mode 100644 index 000000000000..bc91dd334202 --- /dev/null +++ b/src/test/regress/expected/gp_cast.out @@ -0,0 +1,1207 @@ +-- This file contains tests related to the casting behavior, primarily in joins. +-- Some of the tests performed here may already be present inside other files, +-- but it is nice to have a centralized place to observe and compare the behavior of the planners. +-- Tables here are prefixed with cst (which stands for 'cast') to avoid collisions. +-- One of the tests below fails with an assertion, that prints its location in the source code. +-- Make sure that we don't need to update this file when its line changes. +-- start_matchsubs +-- m/DETAIL: CTranslatorQueryToDXL.cpp:\d+: Failed assertion/ +-- s/DETAIL: CTranslatorQueryToDXL.cpp:\d+: Failed assertion/DETAIL: CTranslatorQueryToDXL.cpp:###: Failed assertion/ +-- end_matchsubs +set optimizer_enable_mergejoin = false; +-- We want to specifically test hashjoins for several queries below. +-- Nested loop joins are not constructed for these queries at the time, +-- and probably never will be, but let's make them additionally unlikely just in case. +set optimizer_nestloop_factor = 102400; +set enable_mergejoin = false; +set enable_nestloop = false; +set optimizer_trace_fallback = true; +create table cst_int2 as (select a::int2 from generate_series(0, 10) as a) distributed by (a); +create table cst_int4 as (select a::int4 from generate_series(5, 15) as a) distributed by (a); +create table cst_int8 as (select a::int8 from generate_series(10, 20) as a) distributed by (a); +create table cst_float4 as (select a::float4 from generate_series(5, 15, 1) as a) distributed by (a); +create table cst_float8 as (select a::float8 from generate_series(5, 15, 1) as a) distributed by (a); +create table cst_text as (select a::text from generate_series(5, 15) as a) distributed by (a); +create table cst_varchar as (select a::varchar from generate_series(5, 15) as a) distributed by (a); +create table cst_int2_int4 as (select gen::int2 as a, gen::int4 as b from generate_series(1, 10) as gen) distributed by (a, b); +create table cst_int4_int8 as (select gen::int4 as a, gen::int8 as b from generate_series(1, 10) as gen) distributed by (a, b); +-- Perform an inner join on all hash opfamilies containing more than one type. +-- We shouldn't see any redistributions, because: +-- The postgres-based planner has operators that work on different types. +-- ORCA doesn't support such operations, but it knows when a cast doesn't change a distribution. +set optimizer_join_order = query; +explain (verbose, costs off) select * from cst_int2 join cst_int4 using(a); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Hash Join + Output: cst_int4.a + Hash Cond: (cst_int2.a = cst_int4.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int2 join cst_int4 using(a); + a +---- + 7 + 8 + 5 + 6 + 9 + 10 +(6 rows) + +explain (verbose, costs off) select * from cst_int2 join cst_int8 using(a); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int8.a + -> Hash Join + Output: cst_int8.a + Hash Cond: (cst_int2.a = cst_int8.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Hash + Output: cst_int8.a + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int2 join cst_int8 using(a); + a +---- + 10 +(1 row) + +explain (verbose, costs off) select * from cst_int4 join cst_int8 using(a); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int8.a + -> Hash Join + Output: cst_int8.a + Hash Cond: (cst_int4.a = cst_int8.a) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int8.a + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int4 join cst_int8 using(a); + a +---- + 12 + 15 + 10 + 11 + 13 + 14 +(6 rows) + +explain (verbose, costs off) select * from cst_float4 join cst_float8 using(a); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_float8.a + -> Hash Join + Output: cst_float8.a + Hash Cond: (cst_float4.a = cst_float8.a) + -> Seq Scan on public.cst_float4 + Output: cst_float4.a + -> Hash + Output: cst_float8.a + -> Seq Scan on public.cst_float8 + Output: cst_float8.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_float4 join cst_float8 using(a); + a +---- + 6 + 7 + 8 + 9 + 11 + 12 + 13 + 14 + 15 + 10 + 5 +(11 rows) + +-- Same thing with the sides swapped +explain (verbose, costs off) select * from cst_int4 join cst_int2 using(a); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Hash Join + Output: cst_int4.a + Hash Cond: (cst_int4.a = cst_int2.a) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int4 join cst_int2 using(a); + a +---- + 7 + 8 + 5 + 6 + 9 + 10 +(6 rows) + +explain (verbose, costs off) select * from cst_int8 join cst_int2 using(a); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int8.a + -> Hash Join + Output: cst_int8.a + Hash Cond: (cst_int8.a = cst_int2.a) + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int8 join cst_int2 using(a); + a +---- + 10 +(1 row) + +explain (verbose, costs off) select * from cst_int8 join cst_int4 using(a); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int8.a + -> Hash Join + Output: cst_int8.a + Hash Cond: (cst_int8.a = cst_int4.a) + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int8 join cst_int4 using(a); + a +---- + 10 + 11 + 13 + 14 + 12 + 15 +(6 rows) + +explain (verbose, costs off) select * from cst_float8 join cst_float4 using(a); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_float8.a + -> Hash Join + Output: cst_float8.a + Hash Cond: (cst_float8.a = cst_float4.a) + -> Seq Scan on public.cst_float8 + Output: cst_float8.a + -> Hash + Output: cst_float4.a + -> Seq Scan on public.cst_float4 + Output: cst_float4.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_float8 join cst_float4 using(a); + a +---- + 5 + 10 + 6 + 7 + 8 + 9 + 11 + 12 + 13 + 14 + 15 +(11 rows) + +-- Confirm that casting logic works recursively +explain (verbose, costs off) +select * from cst_int2 + join cst_int8 using(a) + join cst_int4 using(a); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int8.a + -> Hash Join + Output: cst_int8.a + Hash Cond: (cst_int2.a = cst_int4.a) + -> Hash Join + Output: cst_int2.a, cst_int8.a + Hash Cond: (cst_int2.a = cst_int8.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Hash + Output: cst_int8.a + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(20 rows) + +select * from cst_int2 + join cst_int8 using(a) + join cst_int4 using(a); + a +---- + 10 +(1 row) + +reset optimizer_join_order; +-- BUG: this test is failing for ORCA. +-- It's the test that requires start_matchsubs. +explain (verbose, costs off) select * from cst_int2 left join cst_int4 using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((cst_int2.a)::integer) + -> Hash Left Join + Output: cst_int2.a + Hash Cond: (cst_int2.a = cst_int4.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int2 left join cst_int4 using(a); + a +---- + 2 + 3 + 4 + 7 + 8 + 5 + 6 + 9 + 10 + 0 + 1 +(11 rows) + +explain (verbose, costs off) select * from cst_int2 right join cst_int4 using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Hash Left Join + Output: cst_int4.a + Hash Cond: (cst_int4.a = cst_int2.a) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int2 right join cst_int4 using(a); + a +---- + 12 + 15 + 5 + 6 + 9 + 10 + 11 + 13 + 14 + 7 + 8 +(11 rows) + +explain (verbose, costs off) +select * from cst_int4 +where exists (select * + from cst_int2 + where cst_int4.a = cst_int2.a); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Hash Semi Join + Output: cst_int4.a + Hash Cond: (cst_int4.a = cst_int2.a) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int4 +where exists (select * + from cst_int2 + where cst_int4.a = cst_int2.a); + a +---- + 5 + 6 + 9 + 10 + 7 + 8 +(6 rows) + +explain (verbose, costs off) +select * from cst_int4 +where not exists (select * + from cst_int2 + where cst_int4.a = cst_int2.a); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Hash Anti Join + Output: cst_int4.a + Hash Cond: (cst_int4.a = cst_int2.a) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int4 +where not exists (select * + from cst_int2 + where cst_int4.a = cst_int2.a); + a +---- + 12 + 15 + 11 + 13 + 14 +(5 rows) + +explain (verbose, costs off) +select * from cst_int4 +where cst_int4.a not in (select * from cst_int2); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice2; segments: 3) + Output: cst_int4.a + -> Hash Left Anti Semi (Not-In) Join + Output: cst_int4.a + Hash Cond: (cst_int4.a = cst_int2.a) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int2.a + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(15 rows) + +select * from cst_int4 +where cst_int4.a not in (select * from cst_int2); + a +---- + 11 + 13 + 14 + 12 + 15 +(5 rows) + +explain (verbose, costs off) +select * from cst_int2 natural join cst_int4; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Hash Join + Output: cst_int4.a + Hash Cond: (cst_int2.a = cst_int4.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int2 natural join cst_int4; + a +---- + 5 + 6 + 9 + 10 + 7 + 8 +(6 rows) + +-- Here, instead of an implicit cast, an explicit one is present. +-- The postgres-based planner should require a redistribution, because +-- distribution of the cst_int2 table is not directly equal to the left-hand side of the expression. +-- ORCA, on the other hand, can see that redistribution is unnecessary in this case. +explain (verbose, costs off) select * from cst_int2 join cst_int4 on cst_int2.a::int4 = cst_int4.a; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice2; segments: 3) + Output: cst_int2.a, cst_int4.a + -> Hash Join + Output: cst_int2.a, cst_int4.a + Hash Cond: ((cst_int2.a)::integer = cst_int4.a) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Output: cst_int2.a + Hash Key: (cst_int2.a)::integer + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(16 rows) + +select * from cst_int2 join cst_int4 on cst_int2.a::int4 = cst_int4.a; + a | a +----+---- + 7 | 7 + 8 | 8 + 5 | 5 + 6 | 6 + 9 | 9 + 10 | 10 +(6 rows) + +-- The same thing, but with multiple casts in a row. +-- Because the first cast tends to be converted directly to a conversion function, +-- ORCA shouldn't be able to detect the first coercion and should require a redistribution. +explain (verbose, costs off) select * from cst_float4 as cst_float4_f join cst_float4 as cst_float4_s on cst_float4_f.a::int::float4 = cst_float4_s.a; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice2; segments: 3) + Output: cst_float4_f.a, cst_float4_s.a + -> Hash Join + Output: cst_float4_f.a, cst_float4_s.a + Hash Cond: (((cst_float4_f.a)::integer)::real = cst_float4_s.a) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Output: cst_float4_f.a + Hash Key: ((cst_float4_f.a)::integer)::real + -> Seq Scan on public.cst_float4 cst_float4_f + Output: cst_float4_f.a + -> Hash + Output: cst_float4_s.a + -> Seq Scan on public.cst_float4 cst_float4_s + Output: cst_float4_s.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(16 rows) + +select * from cst_float4 as cst_float4_f join cst_float4 as cst_float4_s on cst_float4_f.a::int::float4 = cst_float4_s.a; + a | a +----+---- + 10 | 10 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + 12 | 12 + 13 | 13 + 14 | 14 + 15 | 15 +(11 rows) + +-- Check that binary coercible casts are ruled out +explain (verbose, costs off) select * from cst_varchar as foo join cst_varchar as bar using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: foo.a + -> Hash Join + Output: foo.a + Hash Cond: ((foo.a)::text = (bar.a)::text) + -> Seq Scan on public.cst_varchar foo + Output: foo.a + -> Hash + Output: bar.a + -> Seq Scan on public.cst_varchar bar + Output: bar.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_varchar as foo join cst_varchar as bar using(a); + a +---- + 7 + 5 + 6 + 8 + 15 + 9 + 10 + 11 + 12 + 13 + 14 +(11 rows) + +explain (verbose, costs off) select * from cst_varchar join cst_text using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_varchar.a + -> Hash Join + Output: cst_varchar.a + Hash Cond: ((cst_varchar.a)::text = cst_text.a) + -> Seq Scan on public.cst_varchar + Output: cst_varchar.a + -> Hash + Output: cst_text.a + -> Seq Scan on public.cst_text + Output: cst_text.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_varchar join cst_text using(a); + a +---- + 5 + 6 + 8 + 15 + 7 + 9 + 10 + 11 + 12 + 13 + 14 +(11 rows) + +-- Сheck that we don't rule out necessary distributions. +-- Most basic cases: +explain (verbose, costs off) select * from cst_float4 join cst_int4 using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice2; segments: 3) + Output: cst_float4.a + -> Hash Join + Output: cst_float4.a + Hash Cond: ((cst_int4.a)::double precision = cst_float4.a) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Output: cst_int4.a + Hash Key: (cst_int4.a)::double precision + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_float4.a + -> Seq Scan on public.cst_float4 + Output: cst_float4.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(16 rows) + +select * from cst_float4 join cst_int4 using(a); + a +---- + 10 + 5 + 12 + 15 + 7 + 8 + 6 + 9 + 11 + 13 + 14 +(11 rows) + +explain (verbose, costs off) select * from cst_int4 join cst_text on cst_int4.a = cst_text.a::int4; + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice2; segments: 3) + Output: cst_int4.a, cst_text.a + -> Hash Join + Output: cst_int4.a, cst_text.a + Hash Cond: ((cst_text.a)::integer = cst_int4.a) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Output: cst_text.a + Hash Key: (cst_text.a)::integer + -> Seq Scan on public.cst_text + Output: cst_text.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(16 rows) + +select * from cst_int4 join cst_text on cst_int4.a = cst_text.a::int4; + a | a +----+---- + 8 | 8 + 7 | 7 + 15 | 15 + 12 | 12 + 5 | 5 + 6 | 6 + 9 | 9 + 10 | 10 + 11 | 11 + 13 | 13 + 14 | 14 +(11 rows) + +-- ORCA: in order for there queries to work, equivalent expressions should be matched correctly +explain (verbose, costs off) +with int8_cte as (select * from cst_int8) +select * from (cst_int2 join int8_cte as cte_1 using(a)) + join (int8_cte as cte_2 join cst_int4 using(a)) using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int8.a + -> Hash Join + Output: cst_int8.a + Hash Cond: (cst_int2.a = cst_int4.a) + -> Hash Join + Output: cst_int2.a, cst_int8.a, cst_int8_1.a + Hash Cond: (cst_int2.a = cst_int8_1.a) + -> Hash Join + Output: cst_int2.a, cst_int8.a + Hash Cond: (cst_int2.a = cst_int8.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Hash + Output: cst_int8.a + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + -> Hash + Output: cst_int8_1.a + -> Seq Scan on public.cst_int8 cst_int8_1 + Output: cst_int8_1.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(27 rows) + +with int8_cte as (select * from cst_int8) +select * from (cst_int2 join int8_cte as cte_1 using(a)) + join (int8_cte as cte_2 join cst_int4 using(a)) using(a); + a +---- + 10 +(1 row) + +explain (verbose, costs off) +with int8_cte as (select * from cst_int8) +select * from (cst_int2 join int8_cte as cte_1 using(a)) + join (cst_int4 join int8_cte as cte_2 using(a)) using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int8.a + -> Hash Join + Output: cst_int8.a + Hash Cond: (cst_int2.a = cst_int8_1.a) + -> Hash Join + Output: cst_int2.a, cst_int8.a, cst_int4.a + Hash Cond: (cst_int2.a = cst_int4.a) + -> Hash Join + Output: cst_int2.a, cst_int8.a + Hash Cond: (cst_int2.a = cst_int8.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Hash + Output: cst_int8.a + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int8_1.a + -> Seq Scan on public.cst_int8 cst_int8_1 + Output: cst_int8_1.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(27 rows) + +with int8_cte as (select * from cst_int8) +select * from (cst_int2 join int8_cte as cte_1 using(a)) + join (cst_int4 join int8_cte as cte_2 using(a)) using(a); + a +---- + 10 +(1 row) + +-- Test distribution by multiple keys +explain (verbose, costs off) +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.a and t1.b = t2.b); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: t1.a, t1.b, t2.a, t2.b + -> Hash Join + Output: t1.a, t1.b, t2.a, t2.b + Hash Cond: ((t1.a = t2.a) AND (t1.b = t2.b)) + -> Seq Scan on public.cst_int2_int4 t1 + Output: t1.a, t1.b + -> Hash + Output: t2.a, t2.b + -> Seq Scan on public.cst_int4_int8 t2 + Output: t2.a, t2.b + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.a and t1.b = t2.b); + a | b | a | b +----+----+----+---- + 2 | 2 | 2 | 2 + 3 | 3 | 3 | 3 + 4 | 4 | 4 | 4 + 5 | 5 | 5 | 5 + 7 | 7 | 7 | 7 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 + 1 | 1 | 1 | 1 + 6 | 6 | 6 | 6 + 8 | 8 | 8 | 8 +(10 rows) + +explain (verbose, costs off) +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.b and t1.b = t2.a); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice2; segments: 3) + Output: t1.a, t1.b, t2.a, t2.b + -> Hash Join + Output: t1.a, t1.b, t2.a, t2.b + Hash Cond: ((t1.a = t2.b) AND (t1.b = t2.a)) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Output: t1.a, t1.b + Hash Key: t1.b, t1.a + -> Seq Scan on public.cst_int2_int4 t1 + Output: t1.a, t1.b + -> Hash + Output: t2.a, t2.b + -> Seq Scan on public.cst_int4_int8 t2 + Output: t2.a, t2.b + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(16 rows) + +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.b and t1.b = t2.a); + a | b | a | b +----+----+----+---- + 2 | 2 | 2 | 2 + 3 | 3 | 3 | 3 + 4 | 4 | 4 | 4 + 5 | 5 | 5 | 5 + 7 | 7 | 7 | 7 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 + 1 | 1 | 1 | 1 + 6 | 6 | 6 | 6 + 8 | 8 | 8 | 8 +(10 rows) + +explain (verbose, costs off) +select * from cst_int2_int4 as t1 join cst_int2 as t2 on (t1.a = t2.a); + QUERY PLAN +------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice2; segments: 3) + Output: t1.a, t1.b, t2.a + -> Hash Join + Output: t1.a, t1.b, t2.a + Hash Cond: (t1.a = t2.a) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Output: t1.a, t1.b + Hash Key: t1.a + -> Seq Scan on public.cst_int2_int4 t1 + Output: t1.a, t1.b + -> Hash + Output: t2.a + -> Seq Scan on public.cst_int2 t2 + Output: t2.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_nestloop_factor=102400 +(16 rows) + +select * from cst_int2_int4 as t1 join cst_int2 as t2 on (t1.a = t2.a); + a | b | a +----+----+---- + 2 | 2 | 2 + 3 | 3 | 3 + 4 | 4 | 4 + 7 | 7 | 7 + 8 | 8 | 8 + 1 | 1 | 1 + 9 | 9 | 9 + 10 | 10 | 10 + 5 | 5 | 5 + 6 | 6 | 6 +(10 rows) + +set optimizer_join_order = query; +explain (verbose, costs off) +with cst_int2_int4_copy as (select * from cst_int2_int4) +select * from cst_int2_int4 + natural join cst_int4_int8 + natural join cst_int2_int4_copy; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4_int8.a, cst_int4_int8.b + -> Hash Join + Output: cst_int4_int8.a, cst_int4_int8.b + Hash Cond: ((cst_int4_int8.a = cst_int2_int4.a) AND (cst_int4_int8.b = cst_int2_int4.b)) + -> Seq Scan on public.cst_int4_int8 + Output: cst_int4_int8.a, cst_int4_int8.b + -> Hash + Output: cst_int2_int4.a, cst_int2_int4.b, cst_int2_int4_1.a, cst_int2_int4_1.b + -> Hash Join + Output: cst_int2_int4.a, cst_int2_int4.b, cst_int2_int4_1.a, cst_int2_int4_1.b + Hash Cond: ((cst_int2_int4.a = cst_int2_int4_1.a) AND (cst_int2_int4.b = cst_int2_int4_1.b)) + -> Seq Scan on public.cst_int2_int4 + Output: cst_int2_int4.a, cst_int2_int4.b + -> Hash + Output: cst_int2_int4_1.a, cst_int2_int4_1.b + -> Seq Scan on public.cst_int2_int4 cst_int2_int4_1 + Output: cst_int2_int4_1.a, cst_int2_int4_1.b + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(20 rows) + +with cst_int2_int4_copy as (select * from cst_int2_int4) +select * from cst_int2_int4 + natural join cst_int4_int8 + natural join cst_int2_int4_copy; + a | b +----+---- + 9 | 9 + 10 | 10 + 1 | 1 + 6 | 6 + 8 | 8 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 7 | 7 +(10 rows) + +-- Test several queries with nested-loop join +reset optimizer_nestloop_factor; +set enable_nestloop = true; +set optimizer_enable_hashjoin = false; +set enable_hashjoin = false; +explain (verbose, costs off) select * from cst_int2 join cst_int4 using(a); + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Nested Loop + Output: cst_int4.a + Join Filter: (cst_int2.a = cst_int4.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Materialize + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Postgres query optimizer + Settings: enable_hashjoin=off, enable_mergejoin=off, enable_nestloop=on, optimizer=off, optimizer_join_order=query +(13 rows) + +select * from cst_int2 join cst_int4 using(a); + a +---- + 5 + 6 + 9 + 10 + 7 + 8 +(6 rows) + +-- Subtle behavior ahead: in ORCA, nested loop joins don't support equivalent expressions +-- like hash joins do. +-- So, when join order is fixed, we need to be careful with the join condition, +-- otherwise we might get a broadcast motion. +explain (verbose, costs off) +select * from cst_int2 + join cst_int4 on cst_int2.a = cst_int4.a + join cst_int8 on cst_int4.a = cst_int8.a; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int2.a, cst_int4.a, cst_int8.a + -> Nested Loop + Output: cst_int2.a, cst_int4.a, cst_int8.a + Join Filter: (cst_int2.a = cst_int8.a) + -> Nested Loop + Output: cst_int2.a, cst_int4.a + Join Filter: (cst_int2.a = cst_int4.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Materialize + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Materialize + Output: cst_int8.a + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + Optimizer: Postgres query optimizer + Settings: enable_hashjoin=off, enable_mergejoin=off, enable_nestloop=on, optimizer=off, optimizer_join_order=query +(20 rows) + +select * from cst_int2 + join cst_int4 on cst_int2.a = cst_int4.a + join cst_int8 on cst_int4.a = cst_int8.a; + a | a | a +----+----+---- + 10 | 10 | 10 +(1 row) + +-- Luckily, when join order is not fixed, optimizer finds a join path that +-- gets rid of the broadcast. +reset optimizer_join_order; +explain (verbose, costs off) +select * from cst_int2 + join cst_int4 on cst_int2.a = cst_int4.a + join cst_int8 on cst_int4.a = cst_int8.a; + QUERY PLAN +---------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int2.a, cst_int4.a, cst_int8.a + -> Nested Loop + Output: cst_int2.a, cst_int4.a, cst_int8.a + Join Filter: (cst_int2.a = cst_int8.a) + -> Nested Loop + Output: cst_int2.a, cst_int4.a + Join Filter: (cst_int2.a = cst_int4.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Materialize + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Materialize + Output: cst_int8.a + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + Optimizer: Postgres query optimizer + Settings: enable_hashjoin=off, enable_mergejoin=off, enable_nestloop=on, optimizer=off +(20 rows) + +select * from cst_int2 + join cst_int4 on cst_int2.a = cst_int4.a + join cst_int8 on cst_int4.a = cst_int8.a; + a | a | a +----+----+---- + 10 | 10 | 10 +(1 row) + +-- Test very specific logic for a join on several keys with an index in ORCA +create index cst_int4_int8_idx on cst_int4_int8 (b); +explain (verbose, costs off) +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.a and t1.b = t2.b); + QUERY PLAN +---------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: t1.a, t1.b, t2.a, t2.b + -> Nested Loop + Output: t1.a, t1.b, t2.a, t2.b + Join Filter: ((t1.a = t2.a) AND (t1.b = t2.b)) + -> Seq Scan on public.cst_int2_int4 t1 + Output: t1.a, t1.b + -> Materialize + Output: t2.a, t2.b + -> Seq Scan on public.cst_int4_int8 t2 + Output: t2.a, t2.b + Optimizer: Postgres query optimizer + Settings: enable_hashjoin=off, enable_mergejoin=off, enable_nestloop=on, optimizer=off +(13 rows) + +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.a and t1.b = t2.b); + a | b | a | b +----+----+----+---- + 2 | 2 | 2 | 2 + 3 | 3 | 3 | 3 + 4 | 4 | 4 | 4 + 5 | 5 | 5 | 5 + 7 | 7 | 7 | 7 + 1 | 1 | 1 | 1 + 6 | 6 | 6 | 6 + 8 | 8 | 8 | 8 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 +(10 rows) + +drop index cst_int4_int8_idx; +-- Binary coercible casts should be ruled out too +explain (verbose, costs off) select * from cst_varchar as foo join cst_varchar as bar using(a); + QUERY PLAN +---------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: foo.a + -> Nested Loop + Output: foo.a + Join Filter: ((foo.a)::text = (bar.a)::text) + -> Seq Scan on public.cst_varchar foo + Output: foo.a + -> Materialize + Output: bar.a + -> Seq Scan on public.cst_varchar bar + Output: bar.a + Optimizer: Postgres query optimizer + Settings: enable_hashjoin=off, enable_mergejoin=off, enable_nestloop=on, optimizer=off +(13 rows) + +select * from cst_varchar as foo join cst_varchar as bar using(a); + a +---- + 9 + 10 + 11 + 12 + 13 + 14 + 5 + 6 + 8 + 15 + 7 +(11 rows) + +explain (verbose, costs off) select * from cst_varchar join cst_text using(a); + QUERY PLAN +---------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_varchar.a + -> Nested Loop + Output: cst_varchar.a + Join Filter: ((cst_varchar.a)::text = cst_text.a) + -> Seq Scan on public.cst_varchar + Output: cst_varchar.a + -> Materialize + Output: cst_text.a + -> Seq Scan on public.cst_text + Output: cst_text.a + Optimizer: Postgres query optimizer + Settings: enable_hashjoin=off, enable_mergejoin=off, enable_nestloop=on, optimizer=off +(13 rows) + +select * from cst_varchar join cst_text using(a); + a +---- + 7 + 9 + 10 + 11 + 12 + 13 + 14 + 5 + 6 + 8 + 15 +(11 rows) + +drop table cst_int2; +drop table cst_int4; +drop table cst_int8; +drop table cst_float4; +drop table cst_float8; +drop table cst_text; +drop table cst_varchar; +drop table cst_int2_int4; +drop table cst_int4_int8; +reset optimizer_trace_fallback; +reset enable_hashjoin; +reset enable_nestloop; +reset enable_mergejoin; +reset optimizer_enable_hashjoin; +reset optimizer_nestloop_factor; +reset optimizer_enable_mergejoin; diff --git a/src/test/regress/expected/gp_cast_optimizer.out b/src/test/regress/expected/gp_cast_optimizer.out new file mode 100644 index 000000000000..996f74215444 --- /dev/null +++ b/src/test/regress/expected/gp_cast_optimizer.out @@ -0,0 +1,1215 @@ +-- This file contains tests related to the casting behavior, primarily in joins. +-- Some of the tests performed here may already be present inside other files, +-- but it is nice to have a centralized place to observe and compare the behavior of the planners. +-- Tables here are prefixed with cst (which stands for 'cast') to avoid collisions. +-- One of the tests below fails with an assertion, that prints its location in the source code. +-- Make sure that we don't need to update this file when its line changes. +-- start_matchsubs +-- m/DETAIL: CTranslatorQueryToDXL.cpp:\d+: Failed assertion/ +-- s/DETAIL: CTranslatorQueryToDXL.cpp:\d+: Failed assertion/DETAIL: CTranslatorQueryToDXL.cpp:###: Failed assertion/ +-- end_matchsubs +set optimizer_enable_mergejoin = false; +-- We want to specifically test hashjoins for several queries below. +-- Nested loop joins are not constructed for these queries at the time, +-- and probably never will be, but let's make them additionally unlikely just in case. +set optimizer_nestloop_factor = 102400; +set enable_mergejoin = false; +set enable_nestloop = false; +set optimizer_trace_fallback = true; +create table cst_int2 as (select a::int2 from generate_series(0, 10) as a) distributed by (a); +create table cst_int4 as (select a::int4 from generate_series(5, 15) as a) distributed by (a); +create table cst_int8 as (select a::int8 from generate_series(10, 20) as a) distributed by (a); +create table cst_float4 as (select a::float4 from generate_series(5, 15, 1) as a) distributed by (a); +create table cst_float8 as (select a::float8 from generate_series(5, 15, 1) as a) distributed by (a); +create table cst_text as (select a::text from generate_series(5, 15) as a) distributed by (a); +create table cst_varchar as (select a::varchar from generate_series(5, 15) as a) distributed by (a); +create table cst_int2_int4 as (select gen::int2 as a, gen::int4 as b from generate_series(1, 10) as gen) distributed by (a, b); +create table cst_int4_int8 as (select gen::int4 as a, gen::int8 as b from generate_series(1, 10) as gen) distributed by (a, b); +-- Perform an inner join on all hash opfamilies containing more than one type. +-- We shouldn't see any redistributions, because: +-- The postgres-based planner has operators that work on different types. +-- ORCA doesn't support such operations, but it knows when a cast doesn't change a distribution. +set optimizer_join_order = query; +explain (verbose, costs off) select * from cst_int2 join cst_int4 using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Hash Join + Output: cst_int4.a + Hash Cond: ((cst_int2.a)::integer = cst_int4.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int2 join cst_int4 using(a); + a +---- + 7 + 8 + 5 + 6 + 9 + 10 +(6 rows) + +explain (verbose, costs off) select * from cst_int2 join cst_int8 using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int8.a + -> Hash Join + Output: cst_int8.a + Hash Cond: ((cst_int2.a)::bigint = cst_int8.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Hash + Output: cst_int8.a + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int2 join cst_int8 using(a); + a +---- + 10 +(1 row) + +explain (verbose, costs off) select * from cst_int4 join cst_int8 using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int8.a + -> Hash Join + Output: cst_int8.a + Hash Cond: ((cst_int4.a)::bigint = cst_int8.a) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int8.a + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int4 join cst_int8 using(a); + a +---- + 10 + 11 + 13 + 14 + 12 + 15 +(6 rows) + +explain (verbose, costs off) select * from cst_float4 join cst_float8 using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_float8.a + -> Hash Join + Output: cst_float8.a + Hash Cond: ((cst_float4.a)::double precision = cst_float8.a) + -> Seq Scan on public.cst_float4 + Output: cst_float4.a + -> Hash + Output: cst_float8.a + -> Seq Scan on public.cst_float8 + Output: cst_float8.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_float4 join cst_float8 using(a); + a +---- + 5 + 10 + 6 + 7 + 8 + 9 + 11 + 12 + 13 + 14 + 15 +(11 rows) + +-- Same thing with the sides swapped +explain (verbose, costs off) select * from cst_int4 join cst_int2 using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Hash Join + Output: cst_int4.a + Hash Cond: (cst_int4.a = (cst_int2.a)::integer) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int4 join cst_int2 using(a); + a +---- + 5 + 6 + 9 + 10 + 7 + 8 +(6 rows) + +explain (verbose, costs off) select * from cst_int8 join cst_int2 using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int8.a + -> Hash Join + Output: cst_int8.a + Hash Cond: (cst_int8.a = (cst_int2.a)::bigint) + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int8 join cst_int2 using(a); + a +---- + 10 +(1 row) + +explain (verbose, costs off) select * from cst_int8 join cst_int4 using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int8.a + -> Hash Join + Output: cst_int8.a + Hash Cond: (cst_int8.a = (cst_int4.a)::bigint) + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int8 join cst_int4 using(a); + a +---- + 10 + 11 + 13 + 14 + 12 + 15 +(6 rows) + +explain (verbose, costs off) select * from cst_float8 join cst_float4 using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_float8.a + -> Hash Join + Output: cst_float8.a + Hash Cond: (cst_float8.a = (cst_float4.a)::double precision) + -> Seq Scan on public.cst_float8 + Output: cst_float8.a + -> Hash + Output: cst_float4.a + -> Seq Scan on public.cst_float4 + Output: cst_float4.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_float8 join cst_float4 using(a); + a +---- + 10 + 6 + 7 + 8 + 9 + 11 + 12 + 13 + 14 + 15 + 5 +(11 rows) + +-- Confirm that casting logic works recursively +explain (verbose, costs off) +select * from cst_int2 + join cst_int8 using(a) + join cst_int4 using(a); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int8.a + -> Hash Join + Output: cst_int8.a + Hash Cond: (cst_int8.a = (cst_int4.a)::bigint) + -> Hash Join + Output: cst_int8.a + Hash Cond: ((cst_int2.a)::bigint = cst_int8.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Hash + Output: cst_int8.a + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(20 rows) + +select * from cst_int2 + join cst_int8 using(a) + join cst_int4 using(a); + a +---- + 10 +(1 row) + +reset optimizer_join_order; +-- BUG: this test is failing for ORCA. +-- It's the test that requires start_matchsubs. +explain (verbose, costs off) select * from cst_int2 left join cst_int4 using(a); +INFO: GPORCA failed to produce a plan, falling back to planner +DETAIL: CTranslatorQueryToDXL.cpp:3970: Failed assertion: ((((const Node*)(join_alias_node))->type) == T_Var) || ((((const Node*)(join_alias_node))->type) == T_CoalesceExpr) || ((((const Node*)(join_alias_node))->type) == T_RelabelType) + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((cst_int2.a)::integer) + -> Hash Left Join + Output: cst_int2.a + Hash Cond: (cst_int2.a = cst_int4.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Postgres query optimizer + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int2 left join cst_int4 using(a); +INFO: GPORCA failed to produce a plan, falling back to planner +DETAIL: CTranslatorQueryToDXL.cpp:3970: Failed assertion: ((((const Node*)(join_alias_node))->type) == T_Var) || ((((const Node*)(join_alias_node))->type) == T_CoalesceExpr) || ((((const Node*)(join_alias_node))->type) == T_RelabelType) + a +---- + 5 + 6 + 9 + 10 + 0 + 1 + 2 + 3 + 4 + 7 + 8 +(11 rows) + +explain (verbose, costs off) select * from cst_int2 right join cst_int4 using(a); + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Hash Left Join + Output: cst_int4.a + Hash Cond: (cst_int4.a = (cst_int2.a)::integer) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int2 right join cst_int4 using(a); + a +---- + 7 + 8 + 12 + 15 + 5 + 6 + 9 + 10 + 11 + 13 + 14 +(11 rows) + +explain (verbose, costs off) +select * from cst_int4 +where exists (select * + from cst_int2 + where cst_int4.a = cst_int2.a); + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Hash Semi Join + Output: cst_int4.a + Hash Cond: (cst_int4.a = (cst_int2.a)::integer) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Filter: (NOT (cst_int4.a IS NULL)) + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(14 rows) + +select * from cst_int4 +where exists (select * + from cst_int2 + where cst_int4.a = cst_int2.a); + a +---- + 7 + 8 + 5 + 6 + 9 + 10 +(6 rows) + +explain (verbose, costs off) +select * from cst_int4 +where not exists (select * + from cst_int2 + where cst_int4.a = cst_int2.a); + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Hash Anti Join + Output: cst_int4.a + Hash Cond: (cst_int4.a = (cst_int2.a)::integer) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int4 +where not exists (select * + from cst_int2 + where cst_int4.a = cst_int2.a); + a +---- + 12 + 15 + 11 + 13 + 14 +(5 rows) + +explain (verbose, costs off) +select * from cst_int4 +where cst_int4.a not in (select * from cst_int2); + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: cst_int4.a + -> Hash Left Anti Semi (Not-In) Join + Output: cst_int4.a + Hash Cond: (cst_int4.a = (cst_int2.a)::integer) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int2.a + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(15 rows) + +select * from cst_int4 +where cst_int4.a not in (select * from cst_int2); + a +---- + 12 + 15 + 11 + 13 + 14 +(5 rows) + +explain (verbose, costs off) +select * from cst_int2 natural join cst_int4; + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Hash Join + Output: cst_int4.a + Hash Cond: (cst_int4.a = (cst_int2.a)::integer) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int2 natural join cst_int4; + a +---- + 7 + 8 + 5 + 6 + 9 + 10 +(6 rows) + +-- Here, instead of an implicit cast, an explicit one is present. +-- The postgres-based planner should require a redistribution, because +-- distribution of the cst_int2 table is not directly equal to the left-hand side of the expression. +-- ORCA, on the other hand, can see that redistribution is unnecessary in this case. +explain (verbose, costs off) select * from cst_int2 join cst_int4 on cst_int2.a::int4 = cst_int4.a; + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int2.a, cst_int4.a + -> Hash Join + Output: cst_int2.a, cst_int4.a + Hash Cond: (cst_int4.a = (cst_int2.a)::integer) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int2 join cst_int4 on cst_int2.a::int4 = cst_int4.a; + a | a +----+---- + 7 | 7 + 8 | 8 + 5 | 5 + 6 | 6 + 9 | 9 + 10 | 10 +(6 rows) + +-- The same thing, but with multiple casts in a row. +-- Because the first cast tends to be converted directly to a conversion function, +-- ORCA shouldn't be able to detect the first coercion and should require a redistribution. +explain (verbose, costs off) select * from cst_float4 as cst_float4_f join cst_float4 as cst_float4_s on cst_float4_f.a::int::float4 = cst_float4_s.a; + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: cst_float4.a, cst_float4_1.a + -> Hash Join + Output: cst_float4.a, cst_float4_1.a + Hash Cond: ((int4(cst_float4.a))::real = cst_float4_1.a) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Output: cst_float4.a + Hash Key: (int4(cst_float4.a))::real + -> Seq Scan on public.cst_float4 + Output: cst_float4.a + -> Hash + Output: cst_float4_1.a + -> Seq Scan on public.cst_float4 cst_float4_1 + Output: cst_float4_1.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(16 rows) + +select * from cst_float4 as cst_float4_f join cst_float4 as cst_float4_s on cst_float4_f.a::int::float4 = cst_float4_s.a; + a | a +----+---- + 10 | 10 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 11 | 11 + 12 | 12 + 13 | 13 + 14 | 14 + 15 | 15 +(11 rows) + +-- Check that binary coercible casts are ruled out +explain (verbose, costs off) select * from cst_varchar as foo join cst_varchar as bar using(a); + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_varchar.a + -> Hash Join + Output: cst_varchar.a + Hash Cond: ((cst_varchar.a)::text = (cst_varchar_1.a)::text) + -> Seq Scan on public.cst_varchar + Output: cst_varchar.a + -> Hash + Output: cst_varchar_1.a + -> Seq Scan on public.cst_varchar cst_varchar_1 + Output: cst_varchar_1.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_varchar as foo join cst_varchar as bar using(a); + a +---- + 9 + 10 + 11 + 12 + 13 + 14 + 5 + 6 + 8 + 15 + 7 +(11 rows) + +explain (verbose, costs off) select * from cst_varchar join cst_text using(a); + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_varchar.a + -> Hash Join + Output: cst_varchar.a + Hash Cond: ((cst_varchar.a)::text = cst_text.a) + -> Seq Scan on public.cst_varchar + Output: cst_varchar.a + -> Hash + Output: cst_text.a + -> Seq Scan on public.cst_text + Output: cst_text.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_varchar join cst_text using(a); + a +---- + 9 + 10 + 11 + 12 + 13 + 14 + 7 + 5 + 6 + 8 + 15 +(11 rows) + +-- Сheck that we don't rule out necessary distributions. +-- Most basic cases: +explain (verbose, costs off) select * from cst_float4 join cst_int4 using(a); + QUERY PLAN +---------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: cst_float4.a + -> Hash Join + Output: cst_float4.a + Hash Cond: ((cst_float4.a)::double precision = (cst_int4.a)::double precision) + -> Seq Scan on public.cst_float4 + Output: cst_float4.a + -> Hash + Output: cst_int4.a + -> Redistribute Motion 3:3 (slice1; segments: 3) + Output: cst_int4.a + Hash Key: (cst_int4.a)::double precision + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(16 rows) + +select * from cst_float4 join cst_int4 using(a); + a +---- + 10 + 5 + 6 + 7 + 8 + 9 + 11 + 12 + 13 + 14 + 15 +(11 rows) + +explain (verbose, costs off) select * from cst_int4 join cst_text on cst_int4.a = cst_text.a::int4; + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: cst_int4.a, cst_text.a + -> Hash Join + Output: cst_int4.a, cst_text.a + Hash Cond: (cst_int4.a = (cst_text.a)::integer) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_text.a + -> Redistribute Motion 3:3 (slice1; segments: 3) + Output: cst_text.a + Hash Key: (cst_text.a)::integer + -> Seq Scan on public.cst_text + Output: cst_text.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(16 rows) + +select * from cst_int4 join cst_text on cst_int4.a = cst_text.a::int4; + a | a +----+---- + 7 | 7 + 8 | 8 + 5 | 5 + 6 | 6 + 9 | 9 + 10 | 10 + 11 | 11 + 13 | 13 + 14 | 14 + 12 | 12 + 15 | 15 +(11 rows) + +-- ORCA: in order for there queries to work, equivalent expressions should be matched correctly +explain (verbose, costs off) +with int8_cte as (select * from cst_int8) +select * from (cst_int2 join int8_cte as cte_1 using(a)) + join (int8_cte as cte_2 join cst_int4 using(a)) using(a); + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: share0_ref2.a + -> Sequence + Output: share0_ref2.a + -> Shared Scan (share slice:id 1:0) + Output: share0_ref1.a + -> Materialize + Output: cst_int8.a + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + -> Hash Join + Output: share0_ref2.a + Hash Cond: (share0_ref3.a = (cst_int4.a)::bigint) + -> Hash Join + Output: share0_ref2.a, share0_ref3.a + Hash Cond: (share0_ref3.a = share0_ref2.a) + -> Shared Scan (share slice:id 1:0) + Output: share0_ref3.a + -> Hash + Output: share0_ref2.a + -> Hash Join + Output: share0_ref2.a + Hash Cond: (share0_ref2.a = (cst_int2.a)::bigint) + -> Shared Scan (share slice:id 1:0) + Output: share0_ref2.a + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Hash + Output: cst_int4.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(35 rows) + +with int8_cte as (select * from cst_int8) +select * from (cst_int2 join int8_cte as cte_1 using(a)) + join (int8_cte as cte_2 join cst_int4 using(a)) using(a); + a +---- + 10 +(1 row) + +explain (verbose, costs off) +with int8_cte as (select * from cst_int8) +select * from (cst_int2 join int8_cte as cte_1 using(a)) + join (cst_int4 join int8_cte as cte_2 using(a)) using(a); + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: share0_ref3.a + -> Sequence + Output: share0_ref3.a + -> Shared Scan (share slice:id 1:0) + Output: share0_ref1.a + -> Materialize + Output: cst_int8.a + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + -> Hash Join + Output: share0_ref3.a + Hash Cond: ((share0_ref3.a = (cst_int2.a)::bigint) AND (share0_ref2.a = (cst_int4.a)::bigint) AND (share0_ref3.a = (cst_int4.a)::bigint) AND (share0_ref2.a = (cst_int2.a)::bigint)) + -> Hash Join + Output: share0_ref3.a, share0_ref2.a + Hash Cond: (share0_ref3.a = share0_ref2.a) + -> Shared Scan (share slice:id 1:0) + Output: share0_ref3.a + -> Hash + Output: share0_ref2.a + -> Shared Scan (share slice:id 1:0) + Output: share0_ref2.a + -> Hash + Output: cst_int2.a, cst_int4.a + -> Hash Join + Output: cst_int2.a, cst_int4.a + Hash Cond: (cst_int4.a = (cst_int2.a)::integer) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(35 rows) + +with int8_cte as (select * from cst_int8) +select * from (cst_int2 join int8_cte as cte_1 using(a)) + join (cst_int4 join int8_cte as cte_2 using(a)) using(a); + a +---- + 10 +(1 row) + +-- Test distribution by multiple keys +explain (verbose, costs off) +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.a and t1.b = t2.b); + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int2_int4.a, cst_int2_int4.b, cst_int4_int8.a, cst_int4_int8.b + -> Hash Join + Output: cst_int2_int4.a, cst_int2_int4.b, cst_int4_int8.a, cst_int4_int8.b + Hash Cond: ((cst_int4_int8.a = (cst_int2_int4.a)::integer) AND (cst_int4_int8.b = (cst_int2_int4.b)::bigint)) + -> Seq Scan on public.cst_int4_int8 + Output: cst_int4_int8.a, cst_int4_int8.b + -> Hash + Output: cst_int2_int4.a, cst_int2_int4.b + -> Seq Scan on public.cst_int2_int4 + Output: cst_int2_int4.a, cst_int2_int4.b + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(13 rows) + +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.a and t1.b = t2.b); + a | b | a | b +----+----+----+---- + 2 | 2 | 2 | 2 + 3 | 3 | 3 | 3 + 4 | 4 | 4 | 4 + 5 | 5 | 5 | 5 + 7 | 7 | 7 | 7 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 + 1 | 1 | 1 | 1 + 6 | 6 | 6 | 6 + 8 | 8 | 8 | 8 +(10 rows) + +explain (verbose, costs off) +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.b and t1.b = t2.a); + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice2; segments: 3) + Output: cst_int2_int4.a, cst_int2_int4.b, cst_int4_int8.a, cst_int4_int8.b + -> Hash Join + Output: cst_int2_int4.a, cst_int2_int4.b, cst_int4_int8.a, cst_int4_int8.b + Hash Cond: ((cst_int4_int8.b = (cst_int2_int4.a)::bigint) AND (cst_int4_int8.a = cst_int2_int4.b)) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Output: cst_int4_int8.a, cst_int4_int8.b + Hash Key: cst_int4_int8.b, cst_int4_int8.a + -> Seq Scan on public.cst_int4_int8 + Output: cst_int4_int8.a, cst_int4_int8.b + -> Hash + Output: cst_int2_int4.a, cst_int2_int4.b + -> Seq Scan on public.cst_int2_int4 + Output: cst_int2_int4.a, cst_int2_int4.b + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(16 rows) + +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.b and t1.b = t2.a); + a | b | a | b +----+----+----+---- + 2 | 2 | 2 | 2 + 3 | 3 | 3 | 3 + 4 | 4 | 4 | 4 + 5 | 5 | 5 | 5 + 7 | 7 | 7 | 7 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 + 1 | 1 | 1 | 1 + 6 | 6 | 6 | 6 + 8 | 8 | 8 | 8 +(10 rows) + +explain (verbose, costs off) +select * from cst_int2_int4 as t1 join cst_int2 as t2 on (t1.a = t2.a); + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: cst_int2_int4.a, cst_int2_int4.b, cst_int2.a + -> Hash Join + Output: cst_int2_int4.a, cst_int2_int4.b, cst_int2.a + Hash Cond: (cst_int2_int4.a = cst_int2.a) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Output: cst_int2_int4.a, cst_int2_int4.b + Hash Key: cst_int2_int4.a + -> Seq Scan on public.cst_int2_int4 + Output: cst_int2_int4.a, cst_int2_int4.b + -> Hash + Output: cst_int2.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_nestloop_factor=102400 +(16 rows) + +select * from cst_int2_int4 as t1 join cst_int2 as t2 on (t1.a = t2.a); + a | b | a +----+----+---- + 1 | 1 | 1 + 8 | 8 | 8 + 2 | 2 | 2 + 3 | 3 | 3 + 4 | 4 | 4 + 7 | 7 | 7 + 9 | 9 | 9 + 10 | 10 | 10 + 5 | 5 | 5 + 6 | 6 | 6 +(10 rows) + +set optimizer_join_order = query; +explain (verbose, costs off) +with cst_int2_int4_copy as (select * from cst_int2_int4) +select * from cst_int2_int4 + natural join cst_int4_int8 + natural join cst_int2_int4_copy; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4_int8.a, cst_int4_int8.b + -> Hash Join + Output: cst_int4_int8.a, cst_int4_int8.b + Hash Cond: ((cst_int4_int8.a = (cst_int2_int4_1.a)::integer) AND (cst_int4_int8.b = (cst_int2_int4_1.b)::bigint)) + -> Hash Join + Output: cst_int4_int8.a, cst_int4_int8.b + Hash Cond: (((cst_int2_int4.a)::integer = cst_int4_int8.a) AND ((cst_int2_int4.b)::bigint = cst_int4_int8.b)) + -> Seq Scan on public.cst_int2_int4 + Output: cst_int2_int4.a, cst_int2_int4.b + -> Hash + Output: cst_int4_int8.a, cst_int4_int8.b + -> Seq Scan on public.cst_int4_int8 + Output: cst_int4_int8.a, cst_int4_int8.b + -> Hash + Output: cst_int2_int4_1.a, cst_int2_int4_1.b + -> Seq Scan on public.cst_int2_int4 cst_int2_int4_1 + Output: cst_int2_int4_1.a, cst_int2_int4_1.b + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_mergejoin=off, enable_nestloop=off, optimizer_join_order=query, optimizer_nestloop_factor=102400 +(20 rows) + +with cst_int2_int4_copy as (select * from cst_int2_int4) +select * from cst_int2_int4 + natural join cst_int4_int8 + natural join cst_int2_int4_copy; + a | b +----+---- + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 7 | 7 + 9 | 9 + 10 | 10 + 1 | 1 + 6 | 6 + 8 | 8 +(10 rows) + +-- Test several queries with nested-loop join +reset optimizer_nestloop_factor; +set enable_nestloop = true; +set optimizer_enable_hashjoin = false; +set enable_hashjoin = false; +explain (verbose, costs off) select * from cst_int2 join cst_int4 using(a); + QUERY PLAN +----------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int4.a + -> Nested Loop + Output: cst_int4.a + Join Filter: (cst_int2.a = cst_int4.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_hashjoin=off, enable_mergejoin=off, enable_nestloop=on, optimizer_join_order=query +(11 rows) + +select * from cst_int2 join cst_int4 using(a); + a +---- + 7 + 8 + 5 + 6 + 9 + 10 +(6 rows) + +-- Subtle behavior ahead: in ORCA, nested loop joins don't support equivalent expressions +-- like hash joins do. +-- So, when join order is fixed, we need to be careful with the join condition, +-- otherwise we might get a broadcast motion. +explain (verbose, costs off) +select * from cst_int2 + join cst_int4 on cst_int2.a = cst_int4.a + join cst_int8 on cst_int4.a = cst_int8.a; + QUERY PLAN +----------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: cst_int2.a, cst_int4.a, cst_int8.a + -> Nested Loop + Output: cst_int2.a, cst_int4.a, cst_int8.a + Join Filter: (cst_int4.a = cst_int8.a) + -> Nested Loop + Output: cst_int2.a, cst_int4.a + Join Filter: (cst_int2.a = cst_int4.a) + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Materialize + Output: cst_int8.a + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: cst_int8.a + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_hashjoin=off, enable_mergejoin=off, enable_nestloop=on, optimizer_join_order=query +(20 rows) + +select * from cst_int2 + join cst_int4 on cst_int2.a = cst_int4.a + join cst_int8 on cst_int4.a = cst_int8.a; + a | a | a +----+----+---- + 10 | 10 | 10 +(1 row) + +-- Luckily, when join order is not fixed, optimizer finds a join path that +-- gets rid of the broadcast. +reset optimizer_join_order; +explain (verbose, costs off) +select * from cst_int2 + join cst_int4 on cst_int2.a = cst_int4.a + join cst_int8 on cst_int4.a = cst_int8.a; + QUERY PLAN +------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int2.a, cst_int4.a, cst_int8.a + -> Nested Loop + Output: cst_int2.a, cst_int4.a, cst_int8.a + Join Filter: (cst_int4.a = cst_int8.a) + -> Seq Scan on public.cst_int8 + Output: cst_int8.a + -> Nested Loop + Output: cst_int2.a, cst_int4.a + Join Filter: (cst_int2.a = cst_int4.a) + -> Seq Scan on public.cst_int4 + Output: cst_int4.a + -> Seq Scan on public.cst_int2 + Output: cst_int2.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_hashjoin=off, enable_mergejoin=off, enable_nestloop=on +(16 rows) + +select * from cst_int2 + join cst_int4 on cst_int2.a = cst_int4.a + join cst_int8 on cst_int4.a = cst_int8.a; + a | a | a +----+----+---- + 10 | 10 | 10 +(1 row) + +-- Test very specific logic for a join on several keys with an index in ORCA +create index cst_int4_int8_idx on cst_int4_int8 (b); +explain (verbose, costs off) +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.a and t1.b = t2.b); + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_int2_int4.a, cst_int2_int4.b, cst_int4_int8.a, cst_int4_int8.b + -> Nested Loop + Output: cst_int2_int4.a, cst_int2_int4.b, cst_int4_int8.a, cst_int4_int8.b + Join Filter: true + -> Seq Scan on public.cst_int2_int4 + Output: cst_int2_int4.a, cst_int2_int4.b + -> Index Scan using cst_int4_int8_idx on public.cst_int4_int8 + Output: cst_int4_int8.a, cst_int4_int8.b + Index Cond: (cst_int4_int8.b = cst_int2_int4.b) + Filter: (cst_int2_int4.a = cst_int4_int8.a) + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_hashjoin=off, enable_mergejoin=off, enable_nestloop=on +(13 rows) + +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.a and t1.b = t2.b); + a | b | a | b +----+----+----+---- + 2 | 2 | 2 | 2 + 3 | 3 | 3 | 3 + 4 | 4 | 4 | 4 + 5 | 5 | 5 | 5 + 7 | 7 | 7 | 7 + 9 | 9 | 9 | 9 + 10 | 10 | 10 | 10 + 1 | 1 | 1 | 1 + 6 | 6 | 6 | 6 + 8 | 8 | 8 | 8 +(10 rows) + +drop index cst_int4_int8_idx; +-- Binary coercible casts should be ruled out too +explain (verbose, costs off) select * from cst_varchar as foo join cst_varchar as bar using(a); + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_varchar_1.a + -> Nested Loop + Output: cst_varchar_1.a + Join Filter: ((cst_varchar_1.a)::text = (cst_varchar.a)::text) + -> Seq Scan on public.cst_varchar cst_varchar_1 + Output: cst_varchar_1.a + -> Seq Scan on public.cst_varchar + Output: cst_varchar.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_hashjoin=off, enable_mergejoin=off, enable_nestloop=on +(11 rows) + +select * from cst_varchar as foo join cst_varchar as bar using(a); + a +---- + 7 + 5 + 6 + 8 + 15 + 9 + 10 + 11 + 12 + 13 + 14 +(11 rows) + +explain (verbose, costs off) select * from cst_varchar join cst_text using(a); + QUERY PLAN +------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: cst_varchar.a + -> Nested Loop + Output: cst_varchar.a + Join Filter: ((cst_varchar.a)::text = cst_text.a) + -> Seq Scan on public.cst_varchar + Output: cst_varchar.a + -> Seq Scan on public.cst_text + Output: cst_text.a + Optimizer: Pivotal Optimizer (GPORCA) + Settings: enable_hashjoin=off, enable_mergejoin=off, enable_nestloop=on +(11 rows) + +select * from cst_varchar join cst_text using(a); + a +---- + 7 + 5 + 6 + 8 + 15 + 9 + 10 + 11 + 12 + 13 + 14 +(11 rows) + +drop table cst_int2; +drop table cst_int4; +drop table cst_int8; +drop table cst_float4; +drop table cst_float8; +drop table cst_text; +drop table cst_varchar; +drop table cst_int2_int4; +drop table cst_int4_int8; +reset optimizer_trace_fallback; +reset enable_hashjoin; +reset enable_nestloop; +reset enable_mergejoin; +reset optimizer_enable_hashjoin; +reset optimizer_nestloop_factor; +reset optimizer_enable_mergejoin; diff --git a/src/test/regress/expected/gporca_optimizer.out b/src/test/regress/expected/gporca_optimizer.out index 052ee4cf351c..5bc3ac9ce5a5 100644 --- a/src/test/regress/expected/gporca_optimizer.out +++ b/src/test/regress/expected/gporca_optimizer.out @@ -13439,21 +13439,23 @@ from foo l1 where b in (select ab -- 16 group by columns are not a superset of the distribution columns - no index scan explain (costs off) select * from foo join (select b, count(*) as cnt from tbtree group by b) grby on foo.a=grby.cnt; - QUERY PLAN ------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------ Gather Motion 3:1 (slice3; segments: 3) -> Nested Loop Join Filter: (foo.a = (count())) - -> Broadcast Motion 3:3 (slice2; segments: 3) - -> Seq Scan on foo + -> Seq Scan on foo -> Materialize - -> HashAggregate - Group Key: tbtree.b - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: tbtree.b - -> Seq Scan on tbtree + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: (count()) + -> Result + -> HashAggregate + Group Key: tbtree.b + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: tbtree.b + -> Seq Scan on tbtree Optimizer: Pivotal Optimizer (GPORCA) -(12 rows) +(14 rows) -- 17 group by columns don't intersect - no index scan explain (costs off) diff --git a/src/test/regress/expected/guc_gp.out b/src/test/regress/expected/guc_gp.out index 1152b795f136..fb94ad20d65a 100644 --- a/src/test/regress/expected/guc_gp.out +++ b/src/test/regress/expected/guc_gp.out @@ -661,3 +661,73 @@ RESET search_path; SET statement_mem = '4000MB'; ERROR: Invalid input for statement_mem, must be less than max_statement_mem (2048000 kB) RESET statement_mem; +CREATE TABLE guc_gp_t1(i int) DISTRIBUTED BY (i); +INSERT INTO guc_gp_t1 VALUES(1),(2); +-- generate an idle redaer gang by the following query +SELECT count(*) FROM guc_gp_t1, guc_gp_t1 t; + count +------- + 4 +(1 row) + +-- test create role and set role in the same transaction +BEGIN; +DROP ROLE IF EXISTS guc_gp_test_role1; +NOTICE: role "guc_gp_test_role1" does not exist, skipping +CREATE ROLE guc_gp_test_role1; +NOTICE: resource queue required -- using default resource queue "pg_default" +SET ROLE guc_gp_test_role1; +RESET ROLE; +END; +-- generate an idle redaer gang by the following query +SELECT count(*) FROM guc_gp_t1, guc_gp_t1 t; + count +------- + 4 +(1 row) + +BEGIN ISOLATION LEVEL REPEATABLE READ; +DROP ROLE IF EXISTS guc_gp_test_role2; +NOTICE: role "guc_gp_test_role2" does not exist, skipping +CREATE ROLE guc_gp_test_role2; +NOTICE: resource queue required -- using default resource queue "pg_default" +SET ROLE guc_gp_test_role2; +RESET ROLE; +END; +-- test cursor case +-- cursors are also reader gangs, but they are not idle, thus will not be +-- destroyed by utility statement. +BEGIN; +DECLARE c1 CURSOR FOR SELECT * FROM guc_gp_t1 a, guc_gp_t1 b order by a.i, b.i; +DECLARE c2 CURSOR FOR SELECT * FROM guc_gp_t1 a, guc_gp_t1 b order by a.i, b.i; +FETCH c1; + i | i +---+--- + 1 | 1 +(1 row) + +DROP ROLE IF EXISTS guc_gp_test_role1; +CREATE ROLE guc_gp_test_role1; +NOTICE: resource queue required -- using default resource queue "pg_default" +SET ROLE guc_gp_test_role1; +RESET ROLE; +FETCH c2; + i | i +---+--- + 1 | 1 +(1 row) + +FETCH c1; + i | i +---+--- + 1 | 2 +(1 row) + +FETCH c2; + i | i +---+--- + 1 | 2 +(1 row) + +END; +DROP TABLE guc_gp_t1; diff --git a/src/test/regress/expected/join_optimizer.out b/src/test/regress/expected/join_optimizer.out index 26089b4e78c5..ff7b63846985 100755 --- a/src/test/regress/expected/join_optimizer.out +++ b/src/test/regress/expected/join_optimizer.out @@ -3409,32 +3409,32 @@ select count(*) from tenk1 a join tenk1 b on a.unique1 = b.unique2 left join tenk1 c on a.unique2 = b.unique1 and c.thousand = a.thousand join int4_tbl on b.thousand = f1; - QUERY PLAN ------------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------ Aggregate -> Gather Motion 3:1 (slice5; segments: 3) -> Aggregate - -> Hash Left Join - Hash Cond: (tenk1.thousand = tenk1_2.thousand) - Join Filter: (tenk1.unique2 = tenk1_1.unique1) - -> Redistribute Motion 3:3 (slice3; segments: 3) + -> Hash Right Join + Hash Cond: (tenk1.thousand = tenk1_1.thousand) + Join Filter: (tenk1_1.unique2 = tenk1_2.unique1) + -> Redistribute Motion 3:3 (slice1; segments: 3) Hash Key: tenk1.thousand - -> Hash Join - Hash Cond: (tenk1_1.thousand = int4_tbl.f1) - -> Hash Join - Hash Cond: (tenk1.unique1 = tenk1_1.unique2) - -> Seq Scan on tenk1 - -> Hash - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: tenk1_1.unique2 - -> Seq Scan on tenk1 tenk1_1 - -> Hash - -> Broadcast Motion 3:3 (slice2; segments: 3) - -> Seq Scan on int4_tbl + -> Seq Scan on tenk1 -> Hash -> Redistribute Motion 3:3 (slice4; segments: 3) - Hash Key: tenk1_2.thousand - -> Seq Scan on tenk1 tenk1_2 + Hash Key: tenk1_1.thousand + -> Hash Join + Hash Cond: (tenk1_2.thousand = int4_tbl.f1) + -> Hash Join + Hash Cond: (tenk1_1.unique1 = tenk1_2.unique2) + -> Seq Scan on tenk1 tenk1_1 + -> Hash + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: tenk1_2.unique2 + -> Seq Scan on tenk1 tenk1_2 + -> Hash + -> Broadcast Motion 3:3 (slice3; segments: 3) + -> Seq Scan on int4_tbl Optimizer: Pivotal Optimizer (GPORCA) (25 rows) @@ -3454,37 +3454,37 @@ select b.unique1 from join int4_tbl i1 on b.thousand = f1 right join int4_tbl i2 on i2.f1 = b.tenthous order by 1; - QUERY PLAN ------------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------ Gather Motion 3:1 (slice6; segments: 3) - Merge Key: tenk1.unique1 + Merge Key: tenk1_1.unique1 -> Sort - Sort Key: tenk1.unique1 + Sort Key: tenk1_1.unique1 -> Hash Right Join - Hash Cond: (tenk1.tenthous = int4_tbl_1.f1) + Hash Cond: (tenk1_1.tenthous = int4_tbl_1.f1) -> Redistribute Motion 3:3 (slice5; segments: 3) - Hash Key: tenk1.tenthous - -> Hash Left Join - Hash Cond: (tenk1_1.thousand = tenk1_2.thousand) - Join Filter: (tenk1.unique1 = 42) - -> Redistribute Motion 3:3 (slice3; segments: 3) - Hash Key: tenk1_1.thousand - -> Hash Join - Hash Cond: (tenk1.thousand = int4_tbl.f1) - -> Hash Join - Hash Cond: (tenk1.unique2 = tenk1_1.unique1) - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: tenk1.unique2 - -> Seq Scan on tenk1 - -> Hash - -> Seq Scan on tenk1 tenk1_1 - -> Hash - -> Broadcast Motion 3:3 (slice2; segments: 3) - -> Seq Scan on int4_tbl + Hash Key: tenk1_1.tenthous + -> Hash Right Join + Hash Cond: (tenk1.thousand = tenk1_2.thousand) + Join Filter: (tenk1_1.unique1 = 42) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: tenk1.thousand + -> Seq Scan on tenk1 -> Hash -> Redistribute Motion 3:3 (slice4; segments: 3) Hash Key: tenk1_2.thousand - -> Seq Scan on tenk1 tenk1_2 + -> Hash Join + Hash Cond: (tenk1_1.thousand = int4_tbl.f1) + -> Hash Join + Hash Cond: (tenk1_1.unique2 = tenk1_2.unique1) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: tenk1_1.unique2 + -> Seq Scan on tenk1 tenk1_1 + -> Hash + -> Seq Scan on tenk1 tenk1_2 + -> Hash + -> Broadcast Motion 3:3 (slice3; segments: 3) + -> Seq Scan on int4_tbl -> Hash -> Seq Scan on int4_tbl int4_tbl_1 Optimizer: Pivotal Optimizer (GPORCA) @@ -3914,14 +3914,14 @@ select t1.* from on (t1.f1 = b1.d1) left join int4_tbl i4 on (i8.q2 = i4.f1); - QUERY PLAN ------------------------------------------------------------------------------------------------------- - Gather Motion 3:1 (slice8; segments: 3) + QUERY PLAN +------------------------------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice6; segments: 3) Output: text_tbl.f1 -> Hash Left Join Output: text_tbl.f1 Hash Cond: (int8_tbl.q2 = (int4_tbl_1.f1)::bigint) - -> Redistribute Motion 1:3 (slice6) + -> Redistribute Motion 1:3 (slice4) Output: text_tbl.f1, int8_tbl.q2 -> Hash Right Join Output: text_tbl.f1, int8_tbl.q2 @@ -3929,27 +3929,23 @@ select t1.* from -> Hash Right Join Output: "outer".d1, int8_tbl.q2 Hash Cond: (("outer".d2)::bigint = int8_tbl_2.q2) - -> Hash Left Join + -> Gather Motion 3:1 (slice1; segments: 3) Output: int8_tbl.q2, "outer".d2 - Hash Cond: (int8_tbl.q1 = int8_tbl_1.q1) - -> Gather Motion 3:1 (slice1; segments: 3) - Output: int8_tbl.q1, int8_tbl.q2 + -> Hash Left Join + Output: int8_tbl.q2, "outer".d2 + Hash Cond: (int8_tbl.q1 = int8_tbl_1.q1) -> Seq Scan on public.int8_tbl Output: int8_tbl.q1, int8_tbl.q2 - -> Hash - Output: "outer".d2, int8_tbl_1.q1 - -> Result - Output: NULL::integer, int8_tbl_1.q1 - -> Hash Join - Output: int8_tbl_1.q1 - Hash Cond: (int8_tbl_1.q1 = (int4_tbl.f1)::bigint) - -> Gather Motion 3:1 (slice2; segments: 3) + -> Hash + Output: "outer".d2, int8_tbl_1.q1 + -> Result + Output: NULL::integer, int8_tbl_1.q1 + -> Hash Join Output: int8_tbl_1.q1 + Hash Cond: (int8_tbl_1.q1 = (int4_tbl.f1)::bigint) -> Seq Scan on public.int8_tbl int8_tbl_1 Output: int8_tbl_1.q1 - -> Hash - Output: int4_tbl.f1 - -> Gather Motion 3:1 (slice3; segments: 3) + -> Hash Output: int4_tbl.f1 -> Seq Scan on public.int4_tbl Output: int4_tbl.f1 @@ -3957,25 +3953,25 @@ select t1.* from Output: "outer".d1, int8_tbl_2.q2 -> Result Output: '***'::text, int8_tbl_2.q2 - -> Gather Motion 3:1 (slice4; segments: 3) + -> Gather Motion 3:1 (slice2; segments: 3) Output: int8_tbl_2.q2 -> Seq Scan on public.int8_tbl int8_tbl_2 Output: int8_tbl_2.q2 -> Hash Output: text_tbl.f1 - -> Gather Motion 3:1 (slice5; segments: 3) + -> Gather Motion 3:1 (slice3; segments: 3) Output: text_tbl.f1 -> Seq Scan on public.text_tbl Output: text_tbl.f1 -> Hash Output: int4_tbl_1.f1 - -> Broadcast Motion 3:3 (slice7; segments: 3) + -> Broadcast Motion 3:3 (slice5; segments: 3) Output: int4_tbl_1.f1 -> Seq Scan on public.int4_tbl int4_tbl_1 Output: int4_tbl_1.f1 Optimizer: Pivotal Optimizer (GPORCA) Settings: enable_seqscan=on, optimizer=on -(59 rows) +(55 rows) select t1.* from text_tbl t1 @@ -4372,25 +4368,25 @@ explain (costs off) SELECT b.* FROM b LEFT JOIN c ON b.c_id = c.id; explain (costs off) SELECT a.* FROM a LEFT JOIN (b left join c on b.c_id = c.id) ON (a.b_id = b.id); - QUERY PLAN ------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------ Gather Motion 3:1 (slice4; segments: 3) - -> Hash Left Join - Hash Cond: (a.b_id = b.id) - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: a.b_id - -> Seq Scan on a + -> Hash Right Join + Hash Cond: (b.id = a.b_id) + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: b.id + -> Nested Loop Left Join + Join Filter: true + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: b.c_id + -> Seq Scan on b + -> Index Scan using c_pkey on c + Index Cond: (id = b.c_id) -> Hash -> Redistribute Motion 3:3 (slice3; segments: 3) - Hash Key: b.id - -> Nested Loop Left Join - Join Filter: true - -> Redistribute Motion 3:3 (slice2; segments: 3) - Hash Key: b.c_id - -> Seq Scan on b - -> Index Scan using c_pkey on c - Index Cond: (id = b.c_id) - Optimizer: Pivotal Optimizer (GPORCA) version 2.64.0 + Hash Key: a.b_id + -> Seq Scan on a + Optimizer: Pivotal Optimizer (GPORCA) (17 rows) -- check optimization of outer join within another special join diff --git a/src/test/regress/expected/notin_optimizer.out b/src/test/regress/expected/notin_optimizer.out index 572675c90836..c5d4a2b91c27 100644 --- a/src/test/regress/expected/notin_optimizer.out +++ b/src/test/regress/expected/notin_optimizer.out @@ -232,12 +232,12 @@ explain select c1 from t1, Hash Cond: (t2.c2 = t3.c3) -> Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..862.00 rows=1 width=8) -> Hash Join (cost=0.00..862.00 rows=1 width=8) - Hash Cond: (t2.c2 = t1.c1) - -> Seq Scan on t2 (cost=0.00..431.00 rows=1 width=4) - Filter: (c2 > 4) - -> Hash (cost=431.00..431.00 rows=2 width=4) - -> Seq Scan on t1 (cost=0.00..431.00 rows=2 width=4) - Filter: (c1 > 4) + Hash Cond: (t1.c1 = t2.c2) + -> Seq Scan on t1 (cost=0.00..431.00 rows=2 width=4) + Filter: (c1 > 4) + -> Hash (cost=431.00..431.00 rows=1 width=4) + -> Seq Scan on t2 (cost=0.00..431.00 rows=1 width=4) + Filter: (c2 > 4) -> Hash (cost=431.00..431.00 rows=1 width=4) -> Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..431.00 rows=3 width=4) -> Seq Scan on t3 (cost=0.00..431.00 rows=1 width=4) diff --git a/src/test/regress/expected/qp_correlated_query.out b/src/test/regress/expected/qp_correlated_query.out index 1b4eb1d3078e..669d67a71063 100644 --- a/src/test/regress/expected/qp_correlated_query.out +++ b/src/test/regress/expected/qp_correlated_query.out @@ -3911,6 +3911,126 @@ DROP TABLE skip_correlated_t4; reset optimizer_join_order; reset optimizer_trace_fallback; -------------------------------------------------------------------------------- +-- ORCA should be able to plan and execute correctly skip-level queries, but not +-- with master-only. Postgres Legacy planner should give an error to skip-level +-- query involving distributed or replicated tables. +-------------------------------------------------------------------------------- +CREATE TABLE skip_correlated_distributed ( + a INT +) DISTRIBUTED BY (a); +INSERT INTO skip_correlated_distributed VALUES (1), (2), (3); +CREATE TABLE skip_correlated_random ( + b INT +) DISTRIBUTED RANDOMLY; +INSERT INTO skip_correlated_random VALUES (1), (2), (3); +CREATE TABLE skip_correlated_replicated ( + c INT +) DISTRIBUTED REPLICATED; +INSERT INTO skip_correlated_replicated VALUES(1), (2), (3); +-- easy cases +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c + ) +) FROM skip_correlated_replicated; +ERROR: correlated subquery with skip-level correlations is not supported +SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c + ) +) FROM skip_correlated_replicated ORDER BY a; +ERROR: correlated subquery with skip-level correlations is not supported +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT b FROM skip_correlated_random WHERE b = a + ) +) FROM skip_correlated_distributed; +ERROR: correlated subquery with skip-level correlations is not supported +SELECT ( + SELECT ( + SELECT b FROM skip_correlated_random WHERE b = a + ) +) FROM skip_correlated_distributed ORDER BY b; +ERROR: correlated subquery with skip-level correlations is not supported +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT c FROM skip_correlated_replicated WHERE c = a + ) +) FROM skip_correlated_distributed; +ERROR: correlated subquery with skip-level correlations is not supported +SELECT ( + SELECT ( + SELECT c FROM skip_correlated_replicated WHERE c = a + ) +) FROM skip_correlated_distributed ORDER BY c; +ERROR: correlated subquery with skip-level correlations is not supported +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT dbid FROM gp_segment_configuration WHERE dbid = a + ) +) FROM skip_correlated_distributed; +ERROR: correlated subquery with skip-level correlations is not supported +-- hard cases +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c + ) + ) +) AS l1 FROM skip_correlated_replicated ORDER BY l1; +ERROR: correlated subquery with skip-level correlations is not supported +SELECT ( + SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c + ) + ) +) AS l1 FROM skip_correlated_replicated ORDER BY l1; +ERROR: correlated subquery with skip-level correlations is not supported +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c and a = b + ) as l3 FROM skip_correlated_random ORDER BY l3 LIMIT 1 + ) +) AS l1 FROM skip_correlated_replicated ORDER BY l1; +ERROR: correlated subquery with skip-level correlations is not supported +SELECT ( + SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c and a = b + ) as l3 FROM skip_correlated_random ORDER BY l3 LIMIT 1 + ) +) AS l1 FROM skip_correlated_replicated ORDER BY l1; +ERROR: correlated subquery with skip-level correlations is not supported +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT dbid FROM gp_segment_configuration WHERE dbid = numsegments LIMIT 1 + ) +) FROM gp_distribution_policy; + QUERY PLAN +----------------------------------------------------------------------------- + Seq Scan on gp_distribution_policy + SubPlan 2 + -> Result + InitPlan 1 (returns $1) + -> Limit + -> Seq Scan on gp_segment_configuration + Filter: (dbid = gp_distribution_policy.numsegments) + Optimizer: Postgres query optimizer +(8 rows) + +DROP TABLE skip_correlated_distributed; +DROP TABLE skip_correlated_random; +DROP TABLE skip_correlated_replicated; +-------------------------------------------------------------------------------- -- Ensure ORCA generates the correct plan with the exists clause -- for the partitioned table. -------------------------------------------------------------------------------- @@ -4017,6 +4137,47 @@ SELECT id FROM offers WHERE EXISTS ( RESET optimizer_enforce_subplans; DROP TABLE offers; DROP TABLE contacts; +-------------------------------------------------------------------------------- +-- Test: ORCA-specific behavior related to distribution requests. +-- If a join condition has an 'AND' clause and multiple subexpressions that have +-- the same right-hand side, distribution requests to the outer table +-- can be lost, making it erroneously require a redistribute motion. +-- For more info, please refer to the comments inside +-- CPhysicalJoin::PdshashedMatching +-------------------------------------------------------------------------------- +EXPLAIN +SELECT * +FROM a +WHERE NOT EXISTS ( + SELECT * + FROM B + WHERE (a.j = b.i AND a.i = b.i) +); + QUERY PLAN +---------------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) (cost=3.15..5.26 rows=4 width=8) + -> Hash Anti Join (cost=3.15..5.26 rows=2 width=8) + Hash Cond: ((a.j = b.i) AND (a.i = b.i)) + -> Seq Scan on a (cost=0.00..2.05 rows=2 width=8) + -> Hash (cost=3.06..3.06 rows=2 width=4) + -> Seq Scan on b (cost=0.00..3.06 rows=2 width=4) + Optimizer: Postgres query optimizer +(7 rows) + +SELECT * +FROM a +WHERE NOT EXISTS ( + SELECT * + FROM B + WHERE (a.j = b.i AND a.i = b.i) +); + i | j +----+---- + 19 | 5 + 78 | -1 + 99 | 62 +(3 rows) + -- ---------------------------------------------------------------------- -- Test: teardown.sql -- ---------------------------------------------------------------------- diff --git a/src/test/regress/expected/qp_correlated_query_optimizer.out b/src/test/regress/expected/qp_correlated_query_optimizer.out index 201eae3b1e6c..a85df6c6b37b 100644 --- a/src/test/regress/expected/qp_correlated_query_optimizer.out +++ b/src/test/regress/expected/qp_correlated_query_optimizer.out @@ -509,23 +509,28 @@ select A.j from A, B, C where A.j = (select C.j from C where C.j = A.j and C.i n explain select A.i from A where A.j = (select C.j from C where C.j = A.j and C.i = any (select B.i from B where C.i = B.i and B.i !=10)); QUERY PLAN ----------------------------------------------------------------------------------------------------------------- - Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..1765379.74 rows=5 width=4) - -> Result (cost=0.00..1765379.74 rows=2 width=4) - -> Seq Scan on a (cost=0.00..1765379.74 rows=2 width=4) + Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..1765380.20 rows=5 width=4) + -> Result (cost=0.00..1765380.20 rows=2 width=4) + -> Seq Scan on a (cost=0.00..1765380.20 rows=2 width=4) Filter: (j = (SubPlan 1)) SubPlan 1 (slice2; segments: 3) -> Result (cost=0.00..862.00 rows=1 width=4) Filter: (c.j = a.j) -> Materialize (cost=0.00..862.00 rows=6 width=4) -> Broadcast Motion 3:3 (slice1; segments: 3) (cost=0.00..862.00 rows=6 width=4) - -> Hash Semi Join (cost=0.00..862.00 rows=2 width=4) + -> Hash Join (cost=0.00..862.00 rows=2 width=4) Hash Cond: ((c.i = b.i) AND (c.i = b.i)) -> Seq Scan on c (cost=0.00..431.00 rows=3 width=8) + Filter: ((i < 10) OR (i > 10)) -> Hash (cost=431.00..431.00 rows=2 width=4) - -> Seq Scan on b (cost=0.00..431.00 rows=2 width=4) - Filter: (i <> 10) - Optimizer: PQO version 3.27.0 -(16 rows) + -> GroupAggregate (cost=0.00..431.00 rows=2 width=4) + Group Key: b.i + -> Sort (cost=0.00..431.00 rows=2 width=4) + Sort Key: b.i + -> Seq Scan on b (cost=0.00..431.00 rows=2 width=4) + Filter: ((i <> 10) AND ((i < 10) OR (i > 10))) + Optimizer: Pivotal Optimizer (GPORCA) +(21 rows) select A.i from A where A.j = (select C.j from C where C.j = A.j and C.i = any (select B.i from B where C.i = B.i and B.i !=10)); i @@ -627,39 +632,44 @@ select * from A,B where A.j = any (select C.j from C where C.j = A.j and B.i = a (4 rows) explain select A.i, B.i, C.j from A, B, C where A.j = (select C.j from C where C.j = A.j and C.i = any (select B.i from B where C.i = B.i and B.i !=10)) order by A.i, B.i, C.j limit 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------ - Limit (cost=0.00..1852039752658.48 rows=4 width=12) - -> Gather Motion 3:1 (slice4; segments: 3) (cost=0.00..1852039752658.48 rows=10 width=12) + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------------------- + Limit (cost=0.00..1852040061841.32 rows=4 width=12) + -> Gather Motion 3:1 (slice4; segments: 3) (cost=0.00..1852040061841.32 rows=10 width=12) Merge Key: a.i, b.i, c.j - -> Limit (cost=0.00..1852039752658.48 rows=4 width=12) - -> Sort (cost=0.00..1852039752658.48 rows=90 width=12) + -> Limit (cost=0.00..1852040061841.32 rows=4 width=12) + -> Sort (cost=0.00..1852040061841.32 rows=90 width=12) Sort Key: a.i, b.i, c.j - -> Nested Loop (cost=0.00..1852039752658.44 rows=90 width=12) + -> Nested Loop (cost=0.00..1852040061841.28 rows=90 width=12) Join Filter: true - -> Nested Loop (cost=0.00..1808631708.95 rows=10 width=8) + -> Nested Loop (cost=0.00..1808632010.89 rows=10 width=8) Join Filter: true - -> Broadcast Motion 3:3 (slice3; segments: 3) (cost=0.00..1765379.90 rows=5 width=4) - -> Result (cost=0.00..1765379.90 rows=2 width=4) - -> Seq Scan on a (cost=0.00..1765379.90 rows=2 width=4) + -> Broadcast Motion 3:3 (slice3; segments: 3) (cost=0.00..1765380.20 rows=5 width=4) + -> Result (cost=0.00..1765380.20 rows=2 width=4) + -> Seq Scan on a (cost=0.00..1765380.20 rows=2 width=4) Filter: (j = (SubPlan 1)) SubPlan 1 (slice3; segments: 3) -> Result (cost=0.00..862.00 rows=1 width=4) Filter: (c_1.j = a.j) -> Materialize (cost=0.00..862.00 rows=6 width=4) -> Broadcast Motion 3:3 (slice2; segments: 3) (cost=0.00..862.00 rows=6 width=4) - -> Hash Semi Join (cost=0.00..862.00 rows=2 width=4) + -> Hash Join (cost=0.00..862.00 rows=2 width=4) Hash Cond: ((c_1.i = b_1.i) AND (c_1.i = b_1.i)) -> Seq Scan on c c_1 (cost=0.00..431.00 rows=3 width=8) + Filter: ((i < 10) OR (i > 10)) -> Hash (cost=431.00..431.00 rows=2 width=4) - -> Seq Scan on b b_1 (cost=0.00..431.00 rows=2 width=4) - Filter: (i <> 10) + -> GroupAggregate (cost=0.00..431.00 rows=2 width=4) + Group Key: b_1.i + -> Sort (cost=0.00..431.00 rows=2 width=4) + Sort Key: b_1.i + -> Seq Scan on b b_1 (cost=0.00..431.00 rows=2 width=4) + Filter: ((i <> 10) AND ((i < 10) OR (i > 10))) -> Seq Scan on b (cost=0.00..431.00 rows=2 width=4) -> Materialize (cost=0.00..431.00 rows=9 width=4) -> Broadcast Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=9 width=4) -> Seq Scan on c (cost=0.00..431.00 rows=3 width=4) Optimizer: Pivotal Optimizer (GPORCA) -(30 rows) +(35 rows) select A.i, B.i, C.j from A, B, C where A.j = (select C.j from C where C.j = A.j and C.i = any (select B.i from B where C.i = B.i and B.i !=10)) order by A.i, B.i, C.j limit 10; i | i | j @@ -731,36 +741,36 @@ select A.i, B.i, C.j from A, B, C where A.j = any ( select C.j from C where not (10 rows) explain select A.i, B.i, C.j from A, B, C where A.j = any (select C.j from C where C.j = A.j and not exists (select sum(B.i) from B where C.i = B.i and C.i !=10)) order by A.i, B.i, C.j limit 10; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------- - Limit (cost=0.00..1356692465.22 rows=4 width=12) - -> Gather Motion 3:1 (slice4; segments: 3) (cost=0.00..1356692465.22 rows=10 width=12) + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------- + Limit (cost=0.00..1356692610.57 rows=4 width=12) + -> Gather Motion 3:1 (slice4; segments: 3) (cost=0.00..1356692610.57 rows=10 width=12) Merge Key: a.i, b.i, c.j - -> Limit (cost=0.00..1356692465.22 rows=4 width=12) - -> Sort (cost=0.00..1356692465.22 rows=18 width=12) + -> Limit (cost=0.00..1356692610.57 rows=4 width=12) + -> Sort (cost=0.00..1356692610.57 rows=18 width=12) Sort Key: a.i, b.i, c.j - -> Nested Loop (cost=0.00..1356692465.22 rows=18 width=12) - Join Filter: true - -> Nested Loop (cost=0.00..1324032.98 rows=2 width=8) - Join Filter: true - -> Broadcast Motion 3:3 (slice3; segments: 3) (cost=0.00..431.00 rows=1 width=4) - -> Hash Join (cost=0.00..431.00 rows=1 width=4) - Hash Cond: "outer".j = a.j - -> Result (cost=0.00..0.00 rows=0 width=4) - -> HashAggregate (cost=0.00..0.00 rows=0 width=4) - Group By: NULL::integer - -> Result (cost=0.00..0.00 rows=0 width=4) - One-Time Filter: false - -> Hash (cost=431.00..431.00 rows=2 width=8) - -> Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..431.00 rows=2 width=8) - Hash Key: a.j - -> Seq Scan on a (cost=0.00..431.00 rows=2 width=8) - -> Seq Scan on b (cost=0.00..431.00 rows=2 width=4) - -> Materialize (cost=0.00..431.00 rows=9 width=4) - -> Broadcast Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=9 width=4) - -> Seq Scan on c (cost=0.00..431.00 rows=3 width=4) - Settings: optimizer=on - Optimizer status: Pivotal Optimizer (GPORCA) version 2.34.0 + -> Hash Join (cost=0.00..1356692610.56 rows=18 width=12) + Hash Cond: ("outer".j = a.j) + -> Result (cost=0.00..0.00 rows=0 width=4) + -> HashAggregate (cost=0.00..0.00 rows=0 width=4) + Group Key: NULL::integer + -> Result (cost=0.00..0.00 rows=0 width=4) + One-Time Filter: false + -> Hash (cost=1356692610.51..1356692610.51 rows=90 width=16) + -> Redistribute Motion 3:3 (slice3; segments: 3) (cost=0.00..1356692610.51 rows=90 width=16) + Hash Key: a.j + -> Nested Loop (cost=0.00..1356692610.50 rows=90 width=16) + Join Filter: true + -> Nested Loop (cost=0.00..1324033.12 rows=10 width=12) + Join Filter: true + -> Seq Scan on a (cost=0.00..431.00 rows=2 width=8) + -> Materialize (cost=0.00..431.00 rows=6 width=4) + -> Broadcast Motion 3:3 (slice2; segments: 3) (cost=0.00..431.00 rows=6 width=4) + -> Seq Scan on b (cost=0.00..431.00 rows=2 width=4) + -> Materialize (cost=0.00..431.00 rows=9 width=4) + -> Broadcast Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=9 width=4) + -> Seq Scan on c (cost=0.00..431.00 rows=3 width=4) + Optimizer: Pivotal Optimizer (GPORCA) (28 rows) select A.i, B.i, C.j from A, B, C where A.j = any (select C.j from C where C.j = A.j and not exists (select sum(B.i) from B where C.i = B.i and C.i !=10)) order by A.i, B.i, C.j limit 10; @@ -1460,29 +1470,25 @@ select A.i from A where not exists (select B.i from B where B.i in (select C.i f (3 rows) explain select * from B where not exists (select * from C,A where C.i in (select C.i from C where C.i = A.i and C.i != 10) AND B.i = C.i); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------- - Gather Motion 3:1 (slice4; segments: 3) (cost=0.00..1324895.10 rows=1 width=8) + QUERY PLAN +--------------------------------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..1324895.10 rows=1 width=8) -> Hash Anti Join (cost=0.00..1324895.10 rows=1 width=8) - Hash Cond: b.i = c.i + Hash Cond: (b.i = c.i) -> Seq Scan on b (cost=0.00..431.00 rows=2 width=8) - -> Hash (cost=1324464.10..1324464.10 rows=13 width=4) - -> Redistribute Motion 3:3 (slice3; segments: 3) (cost=0.00..1324464.10 rows=13 width=4) - Hash Key: c.i - -> Hash Semi Join (cost=0.00..1324464.10 rows=13 width=4) - Hash Cond: a.i = c_1.i AND c.i = c_1.i - -> Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..1324033.09 rows=15 width=8) - Hash Key: a.i - -> Nested Loop (cost=0.00..1324033.09 rows=15 width=8) - Join Filter: true - -> Broadcast Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=5 width=4) - -> Seq Scan on a (cost=0.00..431.00 rows=2 width=4) - -> Seq Scan on c (cost=0.00..431.00 rows=3 width=4) - -> Hash (cost=431.00..431.00 rows=3 width=4) - -> Seq Scan on c c_1 (cost=0.00..431.00 rows=3 width=4) - Filter: i <> 10 - Optimizer: Pivotal Optimizer (GPORCA) version 2.74.0 -(20 rows) + -> Hash (cost=1324464.10..1324464.10 rows=3 width=4) + -> Hash Semi Join (cost=0.00..1324464.10 rows=3 width=4) + Hash Cond: ((a.i = c_1.i) AND (c.i = c_1.i)) + -> Nested Loop (cost=0.00..1324033.09 rows=15 width=8) + Join Filter: true + -> Broadcast Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=5 width=4) + -> Seq Scan on a (cost=0.00..431.00 rows=2 width=4) + -> Seq Scan on c (cost=0.00..431.00 rows=3 width=4) + -> Hash (cost=431.00..431.00 rows=3 width=4) + -> Seq Scan on c c_1 (cost=0.00..431.00 rows=3 width=4) + Filter: ((i <> 10) AND ((i < 10) OR (i > 10))) + Optimizer: Pivotal Optimizer (GPORCA) +(16 rows) select * from B where not exists (select * from C,A where C.i in (select C.i from C where C.i = A.i and C.i != 10) AND B.i = C.i); i | j @@ -1494,35 +1500,35 @@ select * from B where not exists (select * from C,A where C.i in (select C.i fro (4 rows) explain select * from A where A.i in (select C.j from C,B where B.i in (select i from C)); - QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +--------------------------------------------------------------------------------------------------------------------------------------------- Gather Motion 3:1 (slice4; segments: 3) (cost=0.00..1324895.30 rows=5 width=8) -> Hash Join (cost=0.00..1324895.30 rows=2 width=8) - Hash Cond: a.i = c.j - -> Seq Scan on a (cost=0.00..431.00 rows=2 width=8) - -> Hash (cost=1324464.30..1324464.30 rows=3 width=4) - -> GroupAggregate (cost=0.00..1324464.30 rows=3 width=4) - Group Key: c.j - -> Sort (cost=0.00..1324464.30 rows=3 width=4) - Sort Key: c.j - -> Redistribute Motion 3:3 (slice3; segments: 3) (cost=0.00..1324464.30 rows=3 width=4) - Hash Key: c.j - -> GroupAggregate (cost=0.00..1324464.30 rows=3 width=4) - Group Key: c.j - -> Sort (cost=0.00..1324464.30 rows=18 width=4) - Sort Key: c.j - -> Hash Semi Join (cost=0.00..1324464.30 rows=18 width=4) - Hash Cond: b.i = c_1.i - -> Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..1324033.29 rows=18 width=8) - Hash Key: b.i - -> Nested Loop (cost=0.00..1324033.29 rows=18 width=8) - Join Filter: true - -> Broadcast Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=6 width=4) - -> Seq Scan on b (cost=0.00..431.00 rows=2 width=4) - -> Seq Scan on c (cost=0.00..431.00 rows=3 width=4) - -> Hash (cost=431.00..431.00 rows=3 width=4) - -> Seq Scan on c c_1 (cost=0.00..431.00 rows=3 width=4) - Optimizer: Pivotal Optimizer (GPORCA) version 2.74.0 + Hash Cond: (c.j = a.i) + -> GroupAggregate (cost=0.00..1324464.30 rows=3 width=4) + Group Key: c.j + -> Sort (cost=0.00..1324464.30 rows=3 width=4) + Sort Key: c.j + -> Redistribute Motion 3:3 (slice3; segments: 3) (cost=0.00..1324464.30 rows=3 width=4) + Hash Key: c.j + -> GroupAggregate (cost=0.00..1324464.30 rows=3 width=4) + Group Key: c.j + -> Sort (cost=0.00..1324464.30 rows=18 width=4) + Sort Key: c.j + -> Hash Semi Join (cost=0.00..1324464.30 rows=18 width=4) + Hash Cond: (b.i = c_1.i) + -> Redistribute Motion 3:3 (slice2; segments: 3) (cost=0.00..1324033.29 rows=18 width=8) + Hash Key: b.i + -> Nested Loop (cost=0.00..1324033.29 rows=18 width=8) + Join Filter: true + -> Broadcast Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=6 width=4) + -> Seq Scan on b (cost=0.00..431.00 rows=2 width=4) + -> Seq Scan on c (cost=0.00..431.00 rows=3 width=4) + -> Hash (cost=431.00..431.00 rows=3 width=4) + -> Seq Scan on c c_1 (cost=0.00..431.00 rows=3 width=4) + -> Hash (cost=431.00..431.00 rows=2 width=8) + -> Seq Scan on a (cost=0.00..431.00 rows=2 width=8) + Optimizer: Pivotal Optimizer (GPORCA) (27 rows) select * from A where A.i in (select C.j from C,B where B.i in (select i from C)); @@ -4051,6 +4057,230 @@ DROP TABLE skip_correlated_t4; reset optimizer_join_order; reset optimizer_trace_fallback; -------------------------------------------------------------------------------- +-- ORCA should be able to plan and execute correctly skip-level queries, but not +-- with master-only. Postgres Legacy planner should give an error to skip-level +-- query involving distributed or replicated tables. +-------------------------------------------------------------------------------- +CREATE TABLE skip_correlated_distributed ( + a INT +) DISTRIBUTED BY (a); +INSERT INTO skip_correlated_distributed VALUES (1), (2), (3); +CREATE TABLE skip_correlated_random ( + b INT +) DISTRIBUTED RANDOMLY; +INSERT INTO skip_correlated_random VALUES (1), (2), (3); +CREATE TABLE skip_correlated_replicated ( + c INT +) DISTRIBUTED REPLICATED; +INSERT INTO skip_correlated_replicated VALUES(1), (2), (3); +-- easy cases +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c + ) +) FROM skip_correlated_replicated; + QUERY PLAN +---------------------------------------------------------------------------------- + Result + -> Gather Motion 1:1 (slice1; segments: 1) + -> Seq Scan on skip_correlated_replicated + SubPlan 1 (slice0) + -> Result + Filter: (skip_correlated_distributed.a = skip_correlated_replicated.c) + -> Materialize + -> Gather Motion 3:1 (slice2; segments: 3) + -> Seq Scan on skip_correlated_distributed + Optimizer: Pivotal Optimizer (GPORCA) +(10 rows) + +SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c + ) +) FROM skip_correlated_replicated ORDER BY a; + a +--- + 1 + 2 + 3 +(3 rows) + +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT b FROM skip_correlated_random WHERE b = a + ) +) FROM skip_correlated_distributed; + QUERY PLAN +------------------------------------------------------------------------------------ + Gather Motion 3:1 (slice2; segments: 3) + -> Result + -> Seq Scan on skip_correlated_distributed + SubPlan 1 (slice2; segments: 3) + -> Result + Filter: (skip_correlated_random.b = skip_correlated_distributed.a) + -> Materialize + -> Broadcast Motion 3:3 (slice1; segments: 3) + -> Seq Scan on skip_correlated_random + Optimizer: Pivotal Optimizer (GPORCA) +(10 rows) + +SELECT ( + SELECT ( + SELECT b FROM skip_correlated_random WHERE b = a + ) +) FROM skip_correlated_distributed ORDER BY b; + b +--- + 1 + 2 + 3 +(3 rows) + +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT c FROM skip_correlated_replicated WHERE c = a + ) +) FROM skip_correlated_distributed; + QUERY PLAN +------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + -> Result + -> Seq Scan on skip_correlated_distributed + SubPlan 1 (slice1; segments: 3) + -> Seq Scan on skip_correlated_replicated + Filter: (c = skip_correlated_distributed.a) + Optimizer: Pivotal Optimizer (GPORCA) +(7 rows) + +SELECT ( + SELECT ( + SELECT c FROM skip_correlated_replicated WHERE c = a + ) +) FROM skip_correlated_distributed ORDER BY c; + c +--- + 1 + 2 + 3 +(3 rows) + +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT dbid FROM gp_segment_configuration WHERE dbid = a + ) +) FROM skip_correlated_distributed; +ERROR: correlated subquery with skip-level correlations is not supported +-- hard cases +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c + ) + ) +) AS l1 FROM skip_correlated_replicated ORDER BY l1; + QUERY PLAN +---------------------------------------------------------------------------------------- + Sort + Sort Key: ((SubPlan 1)) + -> Result + -> Gather Motion 1:1 (slice1; segments: 1) + -> Seq Scan on skip_correlated_replicated + SubPlan 1 (slice0) + -> Result + Filter: (skip_correlated_distributed.a = skip_correlated_replicated.c) + -> Materialize + -> Gather Motion 3:1 (slice2; segments: 3) + -> Seq Scan on skip_correlated_distributed + Optimizer: Pivotal Optimizer (GPORCA) +(12 rows) + +SELECT ( + SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c + ) + ) +) AS l1 FROM skip_correlated_replicated ORDER BY l1; + l1 +---- + 1 + 2 + 3 +(3 rows) + +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c and a = b + ) as l3 FROM skip_correlated_random ORDER BY l3 LIMIT 1 + ) +) AS l1 FROM skip_correlated_replicated ORDER BY l1; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Sort Key: ((SubPlan 2)) + -> Result + -> Gather Motion 1:1 (slice1; segments: 1) + -> Seq Scan on skip_correlated_replicated + SubPlan 2 (slice0) + -> Limit + -> Sort + Sort Key: ((SubPlan 1)) + -> Result + -> Materialize + -> Gather Motion 3:1 (slice2; segments: 3) + -> Seq Scan on skip_correlated_random + SubPlan 1 (slice0) + -> Result + Filter: ((skip_correlated_distributed.a = skip_correlated_replicated.c) AND (skip_correlated_distributed.a = skip_correlated_random.b)) + -> Materialize + -> Gather Motion 3:1 (slice3; segments: 3) + -> Seq Scan on skip_correlated_distributed + Optimizer: Pivotal Optimizer (GPORCA) +(20 rows) + +SELECT ( + SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c and a = b + ) as l3 FROM skip_correlated_random ORDER BY l3 LIMIT 1 + ) +) AS l1 FROM skip_correlated_replicated ORDER BY l1; + l1 +---- + 1 + 2 + 3 +(3 rows) + +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT dbid FROM gp_segment_configuration WHERE dbid = numsegments LIMIT 1 + ) +) FROM gp_distribution_policy; + QUERY PLAN +----------------------------------------------------------------------------- + Seq Scan on gp_distribution_policy + SubPlan 2 + -> Result + InitPlan 1 (returns $1) + -> Limit + -> Seq Scan on gp_segment_configuration + Filter: (dbid = gp_distribution_policy.numsegments) + Optimizer: Postgres query optimizer +(8 rows) + +DROP TABLE skip_correlated_distributed; +DROP TABLE skip_correlated_random; +DROP TABLE skip_correlated_replicated; +-------------------------------------------------------------------------------- -- Ensure ORCA generates the correct plan with the exists clause -- for the partitioned table. -------------------------------------------------------------------------------- @@ -4168,6 +4398,47 @@ SELECT id FROM offers WHERE EXISTS ( RESET optimizer_enforce_subplans; DROP TABLE offers; DROP TABLE contacts; +-------------------------------------------------------------------------------- +-- Test: ORCA-specific behavior related to distribution requests. +-- If a join condition has an 'AND' clause and multiple subexpressions that have +-- the same right-hand side, distribution requests to the outer table +-- can be lost, making it erroneously require a redistribute motion. +-- For more info, please refer to the comments inside +-- CPhysicalJoin::PdshashedMatching +-------------------------------------------------------------------------------- +EXPLAIN +SELECT * +FROM a +WHERE NOT EXISTS ( + SELECT * + FROM B + WHERE (a.j = b.i AND a.i = b.i) +); + QUERY PLAN +------------------------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..862.00 rows=2 width=8) + -> Hash Anti Join (cost=0.00..862.00 rows=1 width=8) + Hash Cond: ((a.j = b.i) AND (a.i = b.i)) + -> Seq Scan on a (cost=0.00..431.00 rows=2 width=8) + -> Hash (cost=431.00..431.00 rows=2 width=4) + -> Seq Scan on b (cost=0.00..431.00 rows=2 width=4) + Optimizer: Pivotal Optimizer (GPORCA) +(7 rows) + +SELECT * +FROM a +WHERE NOT EXISTS ( + SELECT * + FROM B + WHERE (a.j = b.i AND a.i = b.i) +); + i | j +----+---- + 19 | 5 + 78 | -1 + 99 | 62 +(3 rows) + -- ---------------------------------------------------------------------- -- Test: teardown.sql -- ---------------------------------------------------------------------- diff --git a/src/test/regress/expected/qp_functions_in_select.out b/src/test/regress/expected/qp_functions_in_select.out index 98595a51ed96..ee479f454b00 100644 --- a/src/test/regress/expected/qp_functions_in_select.out +++ b/src/test/regress/expected/qp_functions_in_select.out @@ -7673,3 +7673,15 @@ ERROR: UPDATE is not allowed in a non-volatile function CONTEXT: SQL statement "UPDATE bar SET d = d+1 WHERE c = $1" PL/pgSQL function func2_mod_int_stb(integer) line 3 at SQL statement rollback; +-- Test motions are not allowed on QE +create table d(i int) distributed by (i); +insert into d select 1; +create function f() returns int as $$ + select 1 from gp_dist_random('pg_group') union all select 1 from pg_group; +$$ language sql; +-- error when execute such function on QE +select f() from d; +ERROR: cannot create Motion on QE slice (seg1 slice1 172.18.0.7:6003 pid=37574) +CONTEXT: SQL function "f" during startup +drop table d; +drop function f(); diff --git a/src/test/regress/expected/qp_orca_fallback.out b/src/test/regress/expected/qp_orca_fallback.out index bf6f835de957..897d0f8e7206 100644 --- a/src/test/regress/expected/qp_orca_fallback.out +++ b/src/test/regress/expected/qp_orca_fallback.out @@ -330,3 +330,27 @@ SELECT * FROM jsonb_array_elements('["b", "a"]'::jsonb) WITH ORDINALITY; "a" | 2 (2 rows) +-- Orca should fallback if a hash distribution expression does not have an opfamily. +-- (array types does not have legacy opfamilies) +-- create table with legacy hash distr. +SET gp_use_legacy_hashops=1; +CREATE TABLE t_legacy (i INT, arr INT[]) DISTRIBUTED BY (i); +EXPLAIN (COSTS OFF) SELECT * FROM t_legacy INTERSECT ALL (SELECT * FROM t_legacy); + QUERY PLAN +------------------------------------------------------------------ + Gather Motion 3:1 (slice3; segments: 3) + -> HashSetOp Intersect All + -> Append + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: "*SELECT* 1".i, "*SELECT* 1".arr + -> Subquery Scan on "*SELECT* 1" + -> Seq Scan on t_legacy + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: "*SELECT* 2".i, "*SELECT* 2".arr + -> Subquery Scan on "*SELECT* 2" + -> Seq Scan on t_legacy t_legacy_1 + Optimizer: Postgres query optimizer +(12 rows) + +DROP TABLE t_legacy; +RESET gp_use_legacy_hashops; diff --git a/src/test/regress/expected/qp_orca_fallback_optimizer.out b/src/test/regress/expected/qp_orca_fallback_optimizer.out index 2c5854d71ef0..730f121e33ed 100644 --- a/src/test/regress/expected/qp_orca_fallback_optimizer.out +++ b/src/test/regress/expected/qp_orca_fallback_optimizer.out @@ -384,3 +384,29 @@ DETAIL: Feature not supported: WITH ORDINALITY "a" | 2 (2 rows) +-- Orca should fallback if a hash distribution expression does not have an opfamily. +-- (array types does not have legacy opfamilies) +-- create table with legacy hash distr. +SET gp_use_legacy_hashops=1; +CREATE TABLE t_legacy (i INT, arr INT[]) DISTRIBUTED BY (i); +EXPLAIN (COSTS OFF) SELECT * FROM t_legacy INTERSECT ALL (SELECT * FROM t_legacy); +INFO: GPORCA failed to produce a plan, falling back to planner +DETAIL: Unexpected Operator : opfamily must exist for each hash expr + QUERY PLAN +------------------------------------------------------------------ + Gather Motion 3:1 (slice3; segments: 3) + -> HashSetOp Intersect All + -> Append + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: "*SELECT* 1".i, "*SELECT* 1".arr + -> Subquery Scan on "*SELECT* 1" + -> Seq Scan on t_legacy + -> Redistribute Motion 3:3 (slice2; segments: 3) + Hash Key: "*SELECT* 2".i, "*SELECT* 2".arr + -> Subquery Scan on "*SELECT* 2" + -> Seq Scan on t_legacy t_legacy_1 + Optimizer: Postgres query optimizer +(12 rows) + +DROP TABLE t_legacy; +RESET gp_use_legacy_hashops; diff --git a/src/test/regress/expected/qp_query_execution.out b/src/test/regress/expected/qp_query_execution.out index 3ebf8d5fa8b4..1e21d6d5ede0 100644 --- a/src/test/regress/expected/qp_query_execution.out +++ b/src/test/regress/expected/qp_query_execution.out @@ -444,7 +444,7 @@ insert into b select i%7, i%10, i , i || 'SOME NUMBER', i % 4 from generate_seri insert into b select i%7, i%10, i , i || 'SOME NUMBER', i % 4 from generate_series(1, 1000) i; analyze abbp; analyze b; -select qx_count_operator('select abbp.k, abbp.t from abbp left outer join b on abbp.k = b.k where abbp.t is not null and abbp.p = 6;', 'Hash Right Join', 'Hash Left Join'); +select qx_count_operator('select abbp.k, abbp.t from abbp left outer join b on abbp.k = b.k where abbp.t is not null and abbp.p = 6;', 'Hash Right Join', 'Hash Right Join'); qx_count_operator ------------------- 1 diff --git a/src/test/regress/expected/rangefuncs.out b/src/test/regress/expected/rangefuncs.out index 3037e1217e12..7c318b01557c 100755 --- a/src/test/regress/expected/rangefuncs.out +++ b/src/test/regress/expected/rangefuncs.out @@ -273,16 +273,14 @@ HINT: likely caused by a function that reads or modifies data in a distributed CONTEXT: SQL function "foot" statement 1 -- function in subselect select * from foo2 where f2 in (select f2 from foot(foo2.fooid) z where z.fooid = foo2.fooid) ORDER BY 1,2; -ERROR: function cannot execute on a QE slice because it accesses relation "public.foo2" -CONTEXT: SQL function "foot" during startup +ERROR: cannot materialize function with correlated parameters -- function in subselect select * from foo2 where f2 in (select f2 from foot(1) z where z.fooid = foo2.fooid) ORDER BY 1,2; ERROR: function cannot execute on a QE slice because it accesses relation "public.foo2" CONTEXT: SQL function "foot" during startup -- function in subselect select * from foo2 where f2 in (select f2 from foot(foo2.fooid) z where z.fooid = 1) ORDER BY 1,2; -ERROR: function cannot execute on a QE slice because it accesses relation "public.foo2" -CONTEXT: SQL function "foot" during startup +ERROR: cannot materialize function with correlated parameters -- nested functions select foot.fooid, foot.f2 from foot(sin(pi()/2)::int) ORDER BY 1,2; fooid | f2 diff --git a/src/test/regress/expected/rangefuncs_cdb.out b/src/test/regress/expected/rangefuncs_cdb.out index 4483337a9dd5..761c871f6a8b 100644 --- a/src/test/regress/expected/rangefuncs_cdb.out +++ b/src/test/regress/expected/rangefuncs_cdb.out @@ -47,7 +47,7 @@ BEGIN RETURN NEXT r; RETURN; END -$$ language plpgsql; +$$ language plpgsql IMMUTABLE; -- function in select clause select foost(1); foost @@ -169,7 +169,7 @@ BEGIN RETURN NEXT rec; return; END -$$ LANGUAGE plpgsql; +$$ LANGUAGE plpgsql IMMUTABLE; -- function in select clause -- Fails: plpgsql does not support SFRM_Materialize select foor(1); @@ -278,7 +278,7 @@ BEGIN RETURN NEXT; RETURN; END; -$$ LANGUAGE plpgsql; +$$ LANGUAGE plpgsql IMMUTABLE; -- function in select clause select fooro(1); fooro @@ -386,7 +386,7 @@ BEGIN RETURN NEXT; RETURN; END -$$ language plpgsql; +$$ language plpgsql IMMUTABLE; -- function in select clause select foot(1); foot diff --git a/src/test/regress/expected/rpt_optimizer.out b/src/test/regress/expected/rpt_optimizer.out index 17a5406dc34f..26d324831edf 100644 --- a/src/test/regress/expected/rpt_optimizer.out +++ b/src/test/regress/expected/rpt_optimizer.out @@ -1217,20 +1217,21 @@ select d from rand_tab where d in (select distinct c from rep_tab); -- -- join derives EdtHashed explain select c from rep_tab where c in (select distinct a from dist_tab); - QUERY PLAN ----------------------------------------------------------------------------------- + QUERY PLAN +---------------------------------------------------------------------------------------- Gather Motion 3:1 (slice1; segments: 3) (cost=0.00..862.00 rows=2 width=4) - -> Hash Join (cost=0.00..862.00 rows=1 width=4) - Hash Cond: (dist_tab.a = rep_tab.c) - -> GroupAggregate (cost=0.00..431.00 rows=1 width=4) - Group Key: dist_tab.a - -> Sort (cost=0.00..431.00 rows=2 width=4) - Sort Key: dist_tab.a - -> Seq Scan on dist_tab (cost=0.00..431.00 rows=2 width=4) - -> Hash (cost=431.00..431.00 rows=2 width=4) + -> Hash Semi Join (cost=0.00..862.00 rows=1 width=4) + Hash Cond: (rep_tab.c = dist_tab.a) + -> Result (cost=0.00..431.00 rows=1 width=4) -> Seq Scan on rep_tab (cost=0.00..431.00 rows=2 width=4) + -> Hash (cost=431.00..431.00 rows=1 width=4) + -> GroupAggregate (cost=0.00..431.00 rows=1 width=4) + Group Key: dist_tab.a + -> Sort (cost=0.00..431.00 rows=2 width=4) + Sort Key: dist_tab.a + -> Seq Scan on dist_tab (cost=0.00..431.00 rows=2 width=4) Optimizer: Pivotal Optimizer (GPORCA) -(11 rows) +(12 rows) select c from rep_tab where c in (select distinct a from dist_tab); c @@ -1245,22 +1246,19 @@ select c from rep_tab where c in (select distinct a from dist_tab); -- -- join derives EdtHashed explain select c from rep_tab where c in (select distinct d from rand_tab); - QUERY PLAN ------------------------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------ Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..862.00 rows=2 width=4) - -> Hash Join (cost=0.00..862.00 rows=1 width=4) - Hash Cond: (rand_tab.d = rep_tab.c) - -> GroupAggregate (cost=0.00..431.00 rows=1 width=4) - Group Key: rand_tab.d - -> Sort (cost=0.00..431.00 rows=1 width=4) - Sort Key: rand_tab.d - -> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=4) - Hash Key: rand_tab.d - -> Seq Scan on rand_tab (cost=0.00..431.00 rows=1 width=4) - -> Hash (cost=431.00..431.00 rows=2 width=4) + -> Hash Semi Join (cost=0.00..862.00 rows=1 width=4) + Hash Cond: (rep_tab.c = rand_tab.d) + -> Result (cost=0.00..431.00 rows=1 width=4) -> Seq Scan on rep_tab (cost=0.00..431.00 rows=2 width=4) + -> Hash (cost=431.00..431.00 rows=1 width=4) + -> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=1 width=4) + Hash Key: rand_tab.d + -> Seq Scan on rand_tab (cost=0.00..431.00 rows=1 width=4) Optimizer: Pivotal Optimizer (GPORCA) -(13 rows) +(10 rows) select c from rep_tab where c in (select distinct d from rand_tab); c diff --git a/src/test/regress/expected/subselect_gp.out b/src/test/regress/expected/subselect_gp.out index e0cdb9666fdb..2b8a3d2adaf9 100644 --- a/src/test/regress/expected/subselect_gp.out +++ b/src/test/regress/expected/subselect_gp.out @@ -1,3 +1,7 @@ +-- start_matchsubs +-- m/ \(subselect\.c:\d+\)/ +-- s/ \(subselect\.c:\d+\)// +-- end_matchsubs set optimizer_enable_master_only_queries = on; set optimizer_segments = 3; set optimizer_nestloop_factor = 1.0; @@ -3804,3 +3808,3433 @@ drop table t3; drop table t_repl; drop table t2; drop table t1; +-- Test subplan with correlated functions or master-only tables +create table d(d int) distributed by (d); +insert into d select g from generate_series(0, 9) g; +analyze d; +create table p(p int) distributed replicated; +insert into p select g from generate_series(0, 9) g; +analyze p; +create table r(r int) distributed randomly; +insert into r select g from generate_series(0, 9) g; +analyze r; +create view g as select g from generate_series(0, 9) g; +create view c as select dbid c from gp_segment_configuration c; +explain (verbose, costs off) +select (select c from c limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select c from c where c = g) from g; + QUERY PLAN +----------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid + Filter: (c.dbid = g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select c from c where c = g limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid + Filter: (c.dbid = g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select g from g limit 1 offset c) from c; + QUERY PLAN +------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select g from g where g = c) from c; + QUERY PLAN +------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = c.dbid) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select g from g where g = c limit 1 offset c) from c; + QUERY PLAN +------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = c.dbid) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select d from d limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select d from d where d = g) from g; + QUERY PLAN +-------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Result + Output: d.d + Filter: (d.d = g.g) + -> Materialize + Output: d.d, d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select d from d where d = g limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + Filter: (d.d = g.g) + -> Materialize + Output: d.d, d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select g from g limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select g from g where g = d) from d; + QUERY PLAN +------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = d.d) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select g from g where g = d limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = d.d) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(13 rows) + +explain (verbose, costs off) +select (select p from p limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: p.p + -> Result + Output: p.p + -> Materialize + Output: p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select p from p where p = g) from g; + QUERY PLAN +-------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Result + Output: p.p + Filter: (p.p = g.g) + -> Materialize + Output: p.p, p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select p from p where p = g limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: p.p + -> Result + Output: p.p + Filter: (p.p = g.g) + -> Materialize + Output: p.p, p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(17 rows) + +explain (verbose, costs off) +select (select g from g limit 1 offset p) from p; + QUERY PLAN +------------------------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select g from g where g = p) from p; + QUERY PLAN +------------------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = p.p) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select g from g where g = p limit 1 offset p) from p; + QUERY PLAN +------------------------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = p.p) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(13 rows) + +explain (verbose, costs off) +select (select r from r limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select r from r where r = g) from g; + QUERY PLAN +-------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Result + Output: r.r + Filter: (r.r = g.g) + -> Materialize + Output: r.r, r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select r from r where r = g limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + Filter: (r.r = g.g) + -> Materialize + Output: r.r, r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select g from g limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select g from g where g = r) from r; + QUERY PLAN +------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = r.r) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select g from g where g = r limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = r.r) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(13 rows) + +explain (verbose, costs off) +select (select c from c limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: c.dbid + -> Result + Output: c.dbid + -> Materialize + Output: c.dbid + -> Broadcast Motion 1:3 (slice1) + Output: c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(17 rows) + +explain (verbose, costs off) +select (select c from c where c = d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Result + Output: c.dbid + Filter: (c.dbid = d.d) + -> Materialize + Output: c.dbid, c.dbid + -> Broadcast Motion 1:3 (slice1) + Output: c.dbid, c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid, c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select c from c where c = d limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: c.dbid + -> Result + Output: c.dbid + Filter: (c.dbid = d.d) + -> Materialize + Output: c.dbid, c.dbid + -> Broadcast Motion 1:3 (slice1) + Output: c.dbid, c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid, c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select d from d limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(17 rows) + +explain (verbose, costs off) +select (select d from d where d = c) from c; + QUERY PLAN +-------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Result + Output: d.d + Filter: (d.d = c.dbid) + -> Materialize + Output: d.d, d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select d from d where d = c limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + Filter: (d.d = c.dbid) + -> Materialize + Output: d.d, d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select c from c limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: c.dbid + -> Result + Output: c.dbid + -> Materialize + Output: c.dbid + -> Broadcast Motion 1:1 (slice1) + Output: c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(17 rows) + +explain (verbose, costs off) +select (select c from c where c = p) from p; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Result + Output: c.dbid + Filter: (c.dbid = p.p) + -> Materialize + Output: c.dbid, c.dbid + -> Broadcast Motion 1:1 (slice1) + Output: c.dbid, c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid, c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select c from c where c = p limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: c.dbid + -> Result + Output: c.dbid + Filter: (c.dbid = p.p) + -> Materialize + Output: c.dbid, c.dbid + -> Broadcast Motion 1:1 (slice1) + Output: c.dbid, c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid, c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select p from p limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: p.p + -> Result + Output: p.p + -> Materialize + Output: p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select p from p where p = c) from c; + QUERY PLAN +-------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Result + Output: p.p + Filter: (p.p = c.dbid) + -> Materialize + Output: p.p, p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select p from p where p = c limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: p.p + -> Result + Output: p.p + Filter: (p.p = c.dbid) + -> Materialize + Output: p.p, p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select c from c limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: c.dbid + -> Result + Output: c.dbid + -> Materialize + Output: c.dbid + -> Broadcast Motion 1:3 (slice1) + Output: c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(17 rows) + +explain (verbose, costs off) +select (select c from c where c = r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Result + Output: c.dbid + Filter: (c.dbid = r.r) + -> Materialize + Output: c.dbid, c.dbid + -> Broadcast Motion 1:3 (slice1) + Output: c.dbid, c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid, c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select c from c where c = r limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: c.dbid + -> Result + Output: c.dbid + Filter: (c.dbid = r.r) + -> Materialize + Output: c.dbid, c.dbid + -> Broadcast Motion 1:3 (slice1) + Output: c.dbid, c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid, c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select r from r limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(17 rows) + +explain (verbose, costs off) +select (select r from r where r = c) from c; + QUERY PLAN +-------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Result + Output: r.r + Filter: (r.r = c.dbid) + -> Materialize + Output: r.r, r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select r from r where r = c limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + Filter: (r.r = c.dbid) + -> Materialize + Output: r.r, r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select d from d limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select d from d where d = p) from p; + QUERY PLAN +-------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Result + Output: d.d + Filter: (d.d = p.p) + -> Materialize + Output: d.d, d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select d from d where d = p limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + Filter: (d.d = p.p) + -> Materialize + Output: d.d, d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select p from p limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: p.p + -> Result + Output: p.p + -> Materialize + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select p from p where p = d) from d; + QUERY PLAN +------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Result + Output: p.p + Filter: (p.p = d.d) + -> Materialize + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select p from p where p = d limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: p.p + -> Result + Output: p.p + Filter: (p.p = d.d) + -> Materialize + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select d from d limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + -> Materialize + Output: d.d + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select d from d where d = r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Result + Output: d.d + Filter: (d.d = r.r) + -> Materialize + Output: d.d, d.d + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select d from d where d = r limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + Filter: (d.d = r.r) + -> Materialize + Output: d.d, d.d + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select r from r limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + -> Materialize + Output: r.r + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select r from r where r = d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Result + Output: r.r + Filter: (r.r = d.d) + -> Materialize + Output: r.r, r.r + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select r from r where r = d limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + Filter: (r.r = d.d) + -> Materialize + Output: r.r, r.r + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select p from p limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: p.p + -> Result + Output: p.p + -> Materialize + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select p from p where p = r) from r; + QUERY PLAN +------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Result + Output: p.p + Filter: (p.p = r.r) + -> Materialize + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select p from p where p = r limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: p.p + -> Result + Output: p.p + Filter: (p.p = r.r) + -> Materialize + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select r from r limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select r from r where r = p) from p; + QUERY PLAN +-------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Result + Output: r.r + Filter: (r.r = p.p) + -> Materialize + Output: r.r, r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select r from r where r = p limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + Filter: (r.r = p.p) + -> Materialize + Output: r.r, r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +create function i(i int) returns setof int language plpgsql immutable as $$ begin return query select i; end $$; +create function s(s int) returns setof int language plpgsql stable as $$ begin return query select s; end $$; +create function v(v int) returns setof int language plpgsql volatile as $$ begin return query select v; end $$; +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(8 rows) + +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select s from s(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(8 rows) + +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select v from v(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(8 rows) + +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select i from i(d)) from d; + QUERY PLAN +----------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(d.d) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(d.d) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:3 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:3 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select i from i(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select s from s(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select v from v(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select i from i(p)) from p; + QUERY PLAN +----------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(p.p) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(p.p) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:1 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:1 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select i from i(r)) from r; + QUERY PLAN +----------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(r.r) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(r.r) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:3 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:3 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +alter function i(i int) execute on all segments; +alter function s(s int) execute on all segments; +alter function v(v int) execute on all segments; +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Gather Motion 3:1 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select i from i(c)) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Gather Motion 3:1 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(c)) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Gather Motion 3:1 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(c)) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select i from i(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select s from s(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select v from v(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Gather Motion 3:1 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select i from i(g)) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Gather Motion 3:1 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select s from s(g)) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Gather Motion 3:1 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select v from v(g)) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Gather Motion 3:1 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select i from i(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Gather Motion 3:1 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select s from s(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Gather Motion 3:1 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select v from v(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select i from i(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select s from s(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select v from v(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +alter function i(i int) execute on master; +alter function s(s int) execute on master; +alter function v(v int) execute on master; +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(8 rows) + +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select s from s(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(8 rows) + +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select v from v(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(8 rows) + +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 1:3 (slice1) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select i from i(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:3 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:3 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select i from i(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select s from s(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select v from v(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 1:1 (slice1) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select i from i(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:1 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:1 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 1:3 (slice1) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select i from i(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:3 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:3 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +alter function i(i int) execute on initplan; +alter function s(s int) execute on initplan; +alter function v(v int) execute on initplan; +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 2) + SubPlan 2 + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select i from i(c)) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 2) + SubPlan 2 + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select s from s(c)) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 2) + SubPlan 2 + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select v from v(c)) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Result + Output: i_1.i + -> Materialize + Output: i_1.i + -> Broadcast Motion 1:3 (slice1) + Output: i_1.i + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select i from i(d)) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Result + Output: s_1.s + -> Materialize + Output: s_1.s + -> Broadcast Motion 1:3 (slice1) + Output: s_1.s + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select s from s(d)) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Result + Output: v_1.v + -> Materialize + Output: v_1.v + -> Broadcast Motion 1:3 (slice1) + Output: v_1.v + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select v from v(d)) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; + QUERY PLAN +--------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 2) + Function Call: generate_series(0, 9) + SubPlan 2 + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select i from i(g)) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; + QUERY PLAN +--------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 2) + Function Call: generate_series(0, 9) + SubPlan 2 + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select s from s(g)) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; + QUERY PLAN +--------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 2) + Function Call: generate_series(0, 9) + SubPlan 2 + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select v from v(g)) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 1) + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Result + Output: i_1.i + -> Materialize + Output: i_1.i + -> Broadcast Motion 1:1 (slice1) + Output: i_1.i + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select i from i(p)) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 1) + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Result + Output: s_1.s + -> Materialize + Output: s_1.s + -> Broadcast Motion 1:1 (slice1) + Output: s_1.s + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select s from s(p)) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 1) + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Result + Output: v_1.v + -> Materialize + Output: v_1.v + -> Broadcast Motion 1:1 (slice1) + Output: v_1.v + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select v from v(p)) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Result + Output: i_1.i + -> Materialize + Output: i_1.i + -> Broadcast Motion 1:3 (slice1) + Output: i_1.i + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select i from i(r)) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Result + Output: s_1.s + -> Materialize + Output: s_1.s + -> Broadcast Motion 1:3 (slice1) + Output: s_1.s + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select s from s(r)) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Result + Output: v_1.v + -> Materialize + Output: v_1.v + -> Broadcast Motion 1:3 (slice1) + Output: v_1.v + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select v from v(r)) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; +ERROR: plan should not reference subplan's variable +drop function i(a int); +drop function s(a int); +drop function v(a int); +drop table d; +drop table p; +drop table r; +drop view c; +drop view g; diff --git a/src/test/regress/expected/subselect_gp_1.out b/src/test/regress/expected/subselect_gp_1.out index 476392f11b59..cbf549463d1e 100644 --- a/src/test/regress/expected/subselect_gp_1.out +++ b/src/test/regress/expected/subselect_gp_1.out @@ -1,3 +1,7 @@ +-- start_matchsubs +-- m/ \(subselect\.c:\d+\)/ +-- s/ \(subselect\.c:\d+\)// +-- end_matchsubs set optimizer_enable_master_only_queries = on; set optimizer_segments = 3; set optimizer_nestloop_factor = 1.0; @@ -3804,3 +3808,3433 @@ drop table t3; drop table t_repl; drop table t2; drop table t1; +-- Test subplan with correlated functions or master-only tables +create table d(d int) distributed by (d); +insert into d select g from generate_series(0, 9) g; +analyze d; +create table p(p int) distributed replicated; +insert into p select g from generate_series(0, 9) g; +analyze p; +create table r(r int) distributed randomly; +insert into r select g from generate_series(0, 9) g; +analyze r; +create view g as select g from generate_series(0, 9) g; +create view c as select dbid c from gp_segment_configuration c; +explain (verbose, costs off) +select (select c from c limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select c from c where c = g) from g; + QUERY PLAN +----------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid + Filter: (c.dbid = g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select c from c where c = g limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid + Filter: (c.dbid = g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select g from g limit 1 offset c) from c; + QUERY PLAN +------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select g from g where g = c) from c; + QUERY PLAN +------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = c.dbid) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select g from g where g = c limit 1 offset c) from c; + QUERY PLAN +------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = c.dbid) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select d from d limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select d from d where d = g) from g; + QUERY PLAN +-------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Result + Output: d.d + Filter: (d.d = g.g) + -> Materialize + Output: d.d, d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select d from d where d = g limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + Filter: (d.d = g.g) + -> Materialize + Output: d.d, d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select g from g limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select g from g where g = d) from d; + QUERY PLAN +------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = d.d) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select g from g where g = d limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = d.d) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(13 rows) + +explain (verbose, costs off) +select (select p from p limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: p.p + -> Result + Output: p.p + -> Materialize + Output: p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select p from p where p = g) from g; + QUERY PLAN +-------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Result + Output: p.p + Filter: (p.p = g.g) + -> Materialize + Output: p.p, p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select p from p where p = g limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: p.p + -> Result + Output: p.p + Filter: (p.p = g.g) + -> Materialize + Output: p.p, p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(17 rows) + +explain (verbose, costs off) +select (select g from g limit 1 offset p) from p; + QUERY PLAN +------------------------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select g from g where g = p) from p; + QUERY PLAN +------------------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = p.p) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select g from g where g = p limit 1 offset p) from p; + QUERY PLAN +------------------------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = p.p) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(13 rows) + +explain (verbose, costs off) +select (select r from r limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select r from r where r = g) from g; + QUERY PLAN +-------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Result + Output: r.r + Filter: (r.r = g.g) + -> Materialize + Output: r.r, r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select r from r where r = g limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + Filter: (r.r = g.g) + -> Materialize + Output: r.r, r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select g from g limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select g from g where g = r) from r; + QUERY PLAN +------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = r.r) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select g from g where g = r limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: g.g + -> Function Scan on pg_catalog.generate_series g + Output: g.g + Function Call: generate_series(0, 9) + Filter: (g.g = r.r) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(13 rows) + +explain (verbose, costs off) +select (select c from c limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: c.dbid + -> Result + Output: c.dbid + -> Materialize + Output: c.dbid + -> Broadcast Motion 1:3 (slice1) + Output: c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(17 rows) + +explain (verbose, costs off) +select (select c from c where c = d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Result + Output: c.dbid + Filter: (c.dbid = d.d) + -> Materialize + Output: c.dbid, c.dbid + -> Broadcast Motion 1:3 (slice1) + Output: c.dbid, c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid, c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select c from c where c = d limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: c.dbid + -> Result + Output: c.dbid + Filter: (c.dbid = d.d) + -> Materialize + Output: c.dbid, c.dbid + -> Broadcast Motion 1:3 (slice1) + Output: c.dbid, c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid, c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select d from d limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(17 rows) + +explain (verbose, costs off) +select (select d from d where d = c) from c; + QUERY PLAN +-------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Result + Output: d.d + Filter: (d.d = c.dbid) + -> Materialize + Output: d.d, d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select d from d where d = c limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + Filter: (d.d = c.dbid) + -> Materialize + Output: d.d, d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select c from c limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: c.dbid + -> Result + Output: c.dbid + -> Materialize + Output: c.dbid + -> Broadcast Motion 1:1 (slice1) + Output: c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(17 rows) + +explain (verbose, costs off) +select (select c from c where c = p) from p; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Result + Output: c.dbid + Filter: (c.dbid = p.p) + -> Materialize + Output: c.dbid, c.dbid + -> Broadcast Motion 1:1 (slice1) + Output: c.dbid, c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid, c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select c from c where c = p limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: c.dbid + -> Result + Output: c.dbid + Filter: (c.dbid = p.p) + -> Materialize + Output: c.dbid, c.dbid + -> Broadcast Motion 1:1 (slice1) + Output: c.dbid, c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid, c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select p from p limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: p.p + -> Result + Output: p.p + -> Materialize + Output: p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select p from p where p = c) from c; + QUERY PLAN +-------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Result + Output: p.p + Filter: (p.p = c.dbid) + -> Materialize + Output: p.p, p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select p from p where p = c limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: p.p + -> Result + Output: p.p + Filter: (p.p = c.dbid) + -> Materialize + Output: p.p, p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select c from c limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: c.dbid + -> Result + Output: c.dbid + -> Materialize + Output: c.dbid + -> Broadcast Motion 1:3 (slice1) + Output: c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(17 rows) + +explain (verbose, costs off) +select (select c from c where c = r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Result + Output: c.dbid + Filter: (c.dbid = r.r) + -> Materialize + Output: c.dbid, c.dbid + -> Broadcast Motion 1:3 (slice1) + Output: c.dbid, c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid, c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select c from c where c = r limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: c.dbid + -> Result + Output: c.dbid + Filter: (c.dbid = r.r) + -> Materialize + Output: c.dbid, c.dbid + -> Broadcast Motion 1:3 (slice1) + Output: c.dbid, c.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration c + Output: c.dbid, c.dbid + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select r from r limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(17 rows) + +explain (verbose, costs off) +select (select r from r where r = c) from c; + QUERY PLAN +-------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Result + Output: r.r + Filter: (r.r = c.dbid) + -> Materialize + Output: r.r, r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select r from r where r = c limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + Filter: (r.r = c.dbid) + -> Materialize + Output: r.r, r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select d from d limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select d from d where d = p) from p; + QUERY PLAN +-------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Result + Output: d.d + Filter: (d.d = p.p) + -> Materialize + Output: d.d, d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select d from d where d = p limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + Filter: (d.d = p.p) + -> Materialize + Output: d.d, d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select p from p limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: p.p + -> Result + Output: p.p + -> Materialize + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select p from p where p = d) from d; + QUERY PLAN +------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Result + Output: p.p + Filter: (p.p = d.d) + -> Materialize + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select p from p where p = d limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: p.p + -> Result + Output: p.p + Filter: (p.p = d.d) + -> Materialize + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select d from d limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + -> Materialize + Output: d.d + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select d from d where d = r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Result + Output: d.d + Filter: (d.d = r.r) + -> Materialize + Output: d.d, d.d + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select d from d where d = r limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: d.d + -> Limit + Output: d.d + -> Result + Output: d.d + Filter: (d.d = r.r) + -> Materialize + Output: d.d, d.d + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: d.d, d.d + -> Seq Scan on subselect_gp.d + Output: d.d, d.d + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select r from r limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + -> Materialize + Output: r.r + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select r from r where r = d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Result + Output: r.r + Filter: (r.r = d.d) + -> Materialize + Output: r.r, r.r + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select r from r where r = d limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + Filter: (r.r = d.d) + -> Materialize + Output: r.r, r.r + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select p from p limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: p.p + -> Result + Output: p.p + -> Materialize + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select p from p where p = r) from r; + QUERY PLAN +------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Result + Output: p.p + Filter: (p.p = r.r) + -> Materialize + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select p from p where p = r limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: p.p + -> Result + Output: p.p + Filter: (p.p = r.r) + -> Materialize + Output: p.p, p.p + -> Seq Scan on subselect_gp.p + Output: p.p, p.p + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select r from r limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select r from r where r = p) from p; + QUERY PLAN +-------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Result + Output: r.r + Filter: (r.r = p.p) + -> Materialize + Output: r.r, r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(16 rows) + +explain (verbose, costs off) +select (select r from r where r = p limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: r.r + -> Limit + Output: r.r + -> Result + Output: r.r + Filter: (r.r = p.p) + -> Materialize + Output: r.r, r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r, r.r + -> Seq Scan on subselect_gp.r + Output: r.r, r.r + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +create function i(i int) returns setof int language plpgsql immutable as $$ begin return query select i; end $$; +create function s(s int) returns setof int language plpgsql stable as $$ begin return query select s; end $$; +create function v(v int) returns setof int language plpgsql volatile as $$ begin return query select v; end $$; +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(8 rows) + +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select s from s(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(8 rows) + +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select v from v(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(8 rows) + +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select i from i(d)) from d; + QUERY PLAN +----------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(d.d) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(d.d) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:3 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:3 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select i from i(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select s from s(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select v from v(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select i from i(p)) from p; + QUERY PLAN +----------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(p.p) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(p.p) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:1 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:1 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select i from i(r)) from r; + QUERY PLAN +----------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(r.r) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(r.r) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(12 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:3 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:3 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +alter function i(i int) execute on all segments; +alter function s(s int) execute on all segments; +alter function v(v int) execute on all segments; +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Gather Motion 3:1 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select i from i(c)) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Gather Motion 3:1 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(c)) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Gather Motion 3:1 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(c)) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select i from i(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select s from s(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select v from v(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Gather Motion 3:1 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select i from i(g)) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Gather Motion 3:1 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select s from s(g)) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Gather Motion 3:1 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(19 rows) + +explain (verbose, costs off) +select (select v from v(g)) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Gather Motion 3:1 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select i from i(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Gather Motion 3:1 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select s from s(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Gather Motion 3:1 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select v from v(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select i from i(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select s from s(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(20 rows) + +explain (verbose, costs off) +select (select v from v(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +alter function i(i int) execute on master; +alter function s(s int) execute on master; +alter function v(v int) execute on master; +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(8 rows) + +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select s from s(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(8 rows) + +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select v from v(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(8 rows) + +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v((c.dbid)::integer) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(10 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 1:3 (slice1) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select i from i(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:3 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:3 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select i from i(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select s from s(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select v from v(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(9 rows) + +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(g.g) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(11 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 1:1 (slice1) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select i from i(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:1 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:1 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 1:3 (slice1) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select i from i(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:3 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select s from s(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:3 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(18 rows) + +explain (verbose, costs off) +select (select v from v(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +alter function i(i int) execute on initplan; +alter function s(s int) execute on initplan; +alter function v(v int) execute on initplan; +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 2) + SubPlan 2 + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select i from i(c)) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 2) + SubPlan 2 + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select s from s(c)) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 2) + SubPlan 2 + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(14 rows) + +explain (verbose, costs off) +select (select v from v(c)) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Result + Output: i_1.i + -> Materialize + Output: i_1.i + -> Broadcast Motion 1:3 (slice1) + Output: i_1.i + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select i from i(d)) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Result + Output: s_1.s + -> Materialize + Output: s_1.s + -> Broadcast Motion 1:3 (slice1) + Output: s_1.s + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select s from s(d)) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Result + Output: v_1.v + -> Materialize + Output: v_1.v + -> Broadcast Motion 1:3 (slice1) + Output: v_1.v + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select v from v(d)) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; + QUERY PLAN +--------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 2) + Function Call: generate_series(0, 9) + SubPlan 2 + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select i from i(g)) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; + QUERY PLAN +--------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 2) + Function Call: generate_series(0, 9) + SubPlan 2 + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select s from s(g)) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; + QUERY PLAN +--------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 2) + Function Call: generate_series(0, 9) + SubPlan 2 + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(15 rows) + +explain (verbose, costs off) +select (select v from v(g)) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 1) + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Result + Output: i_1.i + -> Materialize + Output: i_1.i + -> Broadcast Motion 1:1 (slice1) + Output: i_1.i + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select i from i(p)) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 1) + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Result + Output: s_1.s + -> Materialize + Output: s_1.s + -> Broadcast Motion 1:1 (slice1) + Output: s_1.s + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select s from s(p)) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 1) + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Result + Output: v_1.v + -> Materialize + Output: v_1.v + -> Broadcast Motion 1:1 (slice1) + Output: v_1.v + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select v from v(p)) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Result + Output: i_1.i + -> Materialize + Output: i_1.i + -> Broadcast Motion 1:3 (slice1) + Output: i_1.i + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select i from i(r)) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Result + Output: s_1.s + -> Materialize + Output: s_1.s + -> Broadcast Motion 1:3 (slice1) + Output: s_1.s + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select s from s(r)) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Result + Output: v_1.v + -> Materialize + Output: v_1.v + -> Broadcast Motion 1:3 (slice1) + Output: v_1.v + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer + Settings: optimizer=off +(22 rows) + +explain (verbose, costs off) +select (select v from v(r)) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; +ERROR: plan should not reference subplan's variable +drop function i(a int); +drop function s(a int); +drop function v(a int); +drop table d; +drop table p; +drop table r; +drop view c; +drop view g; diff --git a/src/test/regress/expected/subselect_gp_optimizer.out b/src/test/regress/expected/subselect_gp_optimizer.out index f103ecc69161..e0f7f00bad27 100644 --- a/src/test/regress/expected/subselect_gp_optimizer.out +++ b/src/test/regress/expected/subselect_gp_optimizer.out @@ -1,3 +1,7 @@ +-- start_matchsubs +-- m/ \(subselect\.c:\d+\)/ +-- s/ \(subselect\.c:\d+\)// +-- end_matchsubs set optimizer_enable_master_only_queries = on; set optimizer_segments = 3; set optimizer_nestloop_factor = 1.0; @@ -1480,30 +1484,34 @@ EXPLAIN SELECT '' AS six, f1 AS "Uncorrelated Field" FROM SUBSELECT_TBL EXPLAIN SELECT '' AS six, f1 AS "Uncorrelated Field" FROM SUBSELECT_TBL WHERE f1 IN (SELECT f2 FROM SUBSELECT_TBL WHERE f2 IN (SELECT f1 FROM SUBSELECT_TBL)) ORDER BY 2; - QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------- Result (cost=0.00..1293.00 rows=2 width=12) - -> Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..1293.00 rows=5 width=4) + -> Gather Motion 3:1 (slice2; segments: 3) (cost=0.00..1293.00 rows=4 width=4) Merge Key: subselect_tbl.f1 -> Sort (cost=0.00..1293.00 rows=2 width=4) Sort Key: subselect_tbl.f1 -> Hash Join (cost=0.00..1293.00 rows=2 width=4) - Hash Cond: subselect_tbl.f1 = subselect_tbl_1.f2 + Hash Cond: (subselect_tbl.f1 = subselect_tbl_2.f2) -> Seq Scan on subselect_tbl (cost=0.00..431.00 rows=3 width=4) -> Hash (cost=862.00..862.00 rows=2 width=4) - -> GroupAggregate (cost=0.00..862.00 rows=2 width=4) - Group Key: subselect_tbl_1.f2 - -> Sort (cost=0.00..862.00 rows=3 width=4) - Sort Key: subselect_tbl_1.f2 - -> Hash Semi Join (cost=0.00..862.00 rows=3 width=4) - Hash Cond: subselect_tbl_1.f2 = subselect_tbl_2.f1 - -> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=3 width=4) - Hash Key: subselect_tbl_1.f2 - -> Seq Scan on subselect_tbl subselect_tbl_1 (cost=0.00..431.00 rows=3 width=4) - -> Hash (cost=431.00..431.00 rows=3 width=4) - -> Seq Scan on subselect_tbl subselect_tbl_2 (cost=0.00..431.00 rows=3 width=4) - Optimizer: Pivotal Optimizer (GPORCA) version 2.74.0 -(21 rows) + -> Hash Join (cost=0.00..862.00 rows=2 width=4) + Hash Cond: (subselect_tbl_1.f1 = subselect_tbl_2.f2) + -> GroupAggregate (cost=0.00..431.00 rows=3 width=4) + Group Key: subselect_tbl_1.f1 + -> Sort (cost=0.00..431.00 rows=3 width=4) + Sort Key: subselect_tbl_1.f1 + -> Seq Scan on subselect_tbl subselect_tbl_1 (cost=0.00..431.00 rows=3 width=4) + -> Hash (cost=431.00..431.00 rows=3 width=4) + -> GroupAggregate (cost=0.00..431.00 rows=3 width=4) + Group Key: subselect_tbl_2.f2 + -> Sort (cost=0.00..431.00 rows=3 width=4) + Sort Key: subselect_tbl_2.f2 + -> Redistribute Motion 3:3 (slice1; segments: 3) (cost=0.00..431.00 rows=3 width=4) + Hash Key: subselect_tbl_2.f2 + -> Seq Scan on subselect_tbl subselect_tbl_2 (cost=0.00..431.00 rows=3 width=4) + Optimizer: Pivotal Optimizer (GPORCA) +(25 rows) EXPLAIN SELECT '' AS three, f1, f2 FROM SUBSELECT_TBL @@ -3287,20 +3295,23 @@ analyze table_left; analyze table_right; -- two types of semi join tests explain (costs off) select * from table_left where exists (select 1 from table_right where l1 = r1); - QUERY PLAN ------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------ Gather Motion 3:1 (slice2; segments: 3) - -> Hash Semi Join - Hash Cond: (table_left.l1 = table_right.r1) - -> Seq Scan on table_left - Filter: (NOT (l1 IS NULL)) + -> Hash Join + Hash Cond: (table_right.r1 = table_left.l1) + -> HashAggregate + Group Key: table_right.r1 + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: table_right.r1 + -> Result + -> Result + -> Seq Scan on table_right -> Hash - -> Result - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: table_right.r1 - -> Seq Scan on table_right + -> Seq Scan on table_left + Filter: (NOT (l1 IS NULL)) Optimizer: Pivotal Optimizer (GPORCA) -(11 rows) +(14 rows) select * from table_left where exists (select 1 from table_right where l1 = r1); l1 | l2 @@ -3312,15 +3323,17 @@ explain (costs off) select * from table_left where l1 in (select r1 from table_r QUERY PLAN ------------------------------------------------------------------ Gather Motion 3:1 (slice2; segments: 3) - -> Hash Semi Join - Hash Cond: (table_left.l1 = table_right.r1) - -> Seq Scan on table_left - -> Hash + -> Hash Join + Hash Cond: (table_right.r1 = table_left.l1) + -> HashAggregate + Group Key: table_right.r1 -> Redistribute Motion 3:3 (slice1; segments: 3) Hash Key: table_right.r1 -> Seq Scan on table_right + -> Hash + -> Seq Scan on table_left Optimizer: Pivotal Optimizer (GPORCA) -(9 rows) +(11 rows) select * from table_left where exists (select 1 from table_right where l1 = r1); l1 | l2 @@ -3972,3 +3985,3534 @@ drop table t3; drop table t_repl; drop table t2; drop table t1; +-- Test subplan with correlated functions or master-only tables +create table d(d int) distributed by (d); +insert into d select g from generate_series(0, 9) g; +analyze d; +create table p(p int) distributed replicated; +insert into p select g from generate_series(0, 9) g; +analyze p; +create table r(r int) distributed randomly; +insert into r select g from generate_series(0, 9) g; +analyze r; +create view g as select g from generate_series(0, 9) g; +create view c as select dbid c from gp_segment_configuration c; +explain (verbose, costs off) +select (select c from c limit 1 offset g) from g; + QUERY PLAN +--------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: gp_segment_configuration.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select c from c where c = g) from g; + QUERY PLAN +------------------------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + Filter: (gp_segment_configuration.dbid = generate_series.generate_series) + Optimizer: Pivotal Optimizer (GPORCA) +(10 rows) + +explain (verbose, costs off) +select (select c from c where c = g limit 1 offset g) from g; + QUERY PLAN +------------------------------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: gp_segment_configuration.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + Filter: (gp_segment_configuration.dbid = generate_series.generate_series) + Optimizer: Pivotal Optimizer (GPORCA) +(12 rows) + +explain (verbose, costs off) +select (select g from g limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 + -> Limit + Output: generate_series.generate_series + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select g from g where g = c) from c; + QUERY PLAN +------------------------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 + -> Result + Output: generate_series.generate_series + Filter: (generate_series.generate_series = gp_segment_configuration.dbid) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + Optimizer: Pivotal Optimizer (GPORCA) +(12 rows) + +explain (verbose, costs off) +select (select g from g where g = c limit 1 offset c) from c; + QUERY PLAN +------------------------------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 + -> Limit + Output: generate_series.generate_series + -> Result + Output: generate_series.generate_series + Filter: (generate_series.generate_series = gp_segment_configuration.dbid) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + Optimizer: Pivotal Optimizer (GPORCA) +(14 rows) + +explain (verbose, costs off) +select (select d from d limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Pivotal Optimizer (GPORCA) +(15 rows) + +explain (verbose, costs off) +select (select d from d where d = g) from g; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Result + Output: d.d + Filter: (d.d = generate_series.generate_series) + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Pivotal Optimizer (GPORCA) +(16 rows) + +explain (verbose, costs off) +select (select d from d where d = g limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Result + Output: d.d + Filter: (d.d = generate_series.generate_series) + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Pivotal Optimizer (GPORCA) +(18 rows) + +explain (verbose, costs off) +select (select g from g limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice1; segments: 3) + -> Limit + Output: generate_series.generate_series + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select g from g where g = d) from d; + QUERY PLAN +----------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice1; segments: 3) + -> Result + Output: generate_series.generate_series + Filter: (generate_series.generate_series = d.d) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + Optimizer: Pivotal Optimizer (GPORCA) +(14 rows) + +explain (verbose, costs off) +select (select g from g where g = d limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice1; segments: 3) + -> Limit + Output: generate_series.generate_series + -> Result + Output: generate_series.generate_series + Filter: (generate_series.generate_series = d.d) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + Optimizer: Pivotal Optimizer (GPORCA) +(16 rows) + +explain (verbose, costs off) +select (select p from p limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: p.p + -> Materialize + Output: p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Pivotal Optimizer (GPORCA) +(15 rows) + +explain (verbose, costs off) +select (select p from p where p = g) from g; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Result + Output: p.p + Filter: (p.p = generate_series.generate_series) + -> Materialize + Output: p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Pivotal Optimizer (GPORCA) +(16 rows) + +explain (verbose, costs off) +select (select p from p where p = g limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: p.p + -> Result + Output: p.p + Filter: (p.p = generate_series.generate_series) + -> Materialize + Output: p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Pivotal Optimizer (GPORCA) +(18 rows) + +explain (verbose, costs off) +select (select g from g limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: generate_series.generate_series + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select g from g where g = p) from p; + QUERY PLAN +----------------------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice1; segments: 1) + -> Result + Output: generate_series.generate_series + Filter: (generate_series.generate_series = p.p) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + Optimizer: Pivotal Optimizer (GPORCA) +(14 rows) + +explain (verbose, costs off) +select (select g from g where g = p limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: generate_series.generate_series + -> Result + Output: generate_series.generate_series + Filter: (generate_series.generate_series = p.p) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + Optimizer: Pivotal Optimizer (GPORCA) +(16 rows) + +explain (verbose, costs off) +select (select r from r limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Pivotal Optimizer (GPORCA) +(15 rows) + +explain (verbose, costs off) +select (select r from r where r = g) from g; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Result + Output: r.r + Filter: (r.r = generate_series.generate_series) + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Pivotal Optimizer (GPORCA) +(16 rows) + +explain (verbose, costs off) +select (select r from r where r = g limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Result + Output: r.r + Filter: (r.r = generate_series.generate_series) + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Pivotal Optimizer (GPORCA) +(18 rows) + +explain (verbose, costs off) +select (select g from g limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice1; segments: 3) + -> Limit + Output: generate_series.generate_series + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select g from g where g = r) from r; + QUERY PLAN +----------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice1; segments: 3) + -> Result + Output: generate_series.generate_series + Filter: (generate_series.generate_series = r.r) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + Optimizer: Pivotal Optimizer (GPORCA) +(14 rows) + +explain (verbose, costs off) +select (select g from g where g = r limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice1; segments: 3) + -> Limit + Output: generate_series.generate_series + -> Result + Output: generate_series.generate_series + Filter: (generate_series.generate_series = r.r) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + Optimizer: Pivotal Optimizer (GPORCA) +(16 rows) + +explain (verbose, costs off) +select (select c from c limit 1 offset d) from d; + QUERY PLAN +--------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: gp_segment_configuration.dbid + -> Materialize + Output: gp_segment_configuration.dbid + -> Broadcast Motion 1:3 (slice1) + Output: gp_segment_configuration.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + Optimizer: Pivotal Optimizer (GPORCA) +(16 rows) + +explain (verbose, costs off) +select (select c from c where c = d) from d; + QUERY PLAN +--------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice2; segments: 3) + -> Result + Output: gp_segment_configuration.dbid + Filter: (gp_segment_configuration.dbid = d.d) + -> Materialize + Output: gp_segment_configuration.dbid + -> Broadcast Motion 1:3 (slice1) + Output: gp_segment_configuration.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + Optimizer: Pivotal Optimizer (GPORCA) +(17 rows) + +explain (verbose, costs off) +select (select c from c where c = d limit 1 offset d) from d; + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: gp_segment_configuration.dbid + -> Result + Output: gp_segment_configuration.dbid + Filter: (gp_segment_configuration.dbid = d.d) + -> Materialize + Output: gp_segment_configuration.dbid + -> Broadcast Motion 1:3 (slice1) + Output: gp_segment_configuration.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + Optimizer: Pivotal Optimizer (GPORCA) +(19 rows) + +explain (verbose, costs off) +select (select d from d limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Pivotal Optimizer (GPORCA) +(14 rows) + +explain (verbose, costs off) +select (select d from d where d = c) from c; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 (slice0) + -> Result + Output: d.d + Filter: (d.d = gp_segment_configuration.dbid) + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Pivotal Optimizer (GPORCA) +(15 rows) + +explain (verbose, costs off) +select (select d from d where d = c limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Result + Output: d.d + Filter: (d.d = gp_segment_configuration.dbid) + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Pivotal Optimizer (GPORCA) +(17 rows) + +explain (verbose, costs off) +select (select c from c limit 1 offset p) from p; + QUERY PLAN +--------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Limit + Output: gp_segment_configuration.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + Optimizer: Pivotal Optimizer (GPORCA) + Settings: optimizer=on +(13 rows) + +explain (verbose, costs off) +select (select c from c where c = p) from p; + QUERY PLAN +--------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + Filter: (gp_segment_configuration.dbid = p.p) + Optimizer: Pivotal Optimizer (GPORCA) + Settings: optimizer=on +(12 rows) + +explain (verbose, costs off) +select (select c from c where c = p limit 1 offset p) from p; + QUERY PLAN +--------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Limit + Output: gp_segment_configuration.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + Filter: (gp_segment_configuration.dbid = p.p) + Optimizer: Pivotal Optimizer (GPORCA) + Settings: optimizer=on +(14 rows) + +explain (verbose, costs off) +select (select p from p limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 (slice0) + -> Limit + Output: p.p + -> Materialize + Output: p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Pivotal Optimizer (GPORCA) +(14 rows) + +explain (verbose, costs off) +select (select p from p where p = c) from c; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 (slice0) + -> Result + Output: p.p + Filter: (p.p = gp_segment_configuration.dbid) + -> Materialize + Output: p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Pivotal Optimizer (GPORCA) +(15 rows) + +explain (verbose, costs off) +select (select p from p where p = c limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 (slice0) + -> Limit + Output: p.p + -> Result + Output: p.p + Filter: (p.p = gp_segment_configuration.dbid) + -> Materialize + Output: p.p + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Pivotal Optimizer (GPORCA) +(17 rows) + +explain (verbose, costs off) +select (select c from c limit 1 offset r) from r; + QUERY PLAN +--------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: gp_segment_configuration.dbid + -> Materialize + Output: gp_segment_configuration.dbid + -> Broadcast Motion 1:3 (slice1) + Output: gp_segment_configuration.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + Optimizer: Pivotal Optimizer (GPORCA) +(16 rows) + +explain (verbose, costs off) +select (select c from c where c = r) from r; + QUERY PLAN +--------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice2; segments: 3) + -> Result + Output: gp_segment_configuration.dbid + Filter: (gp_segment_configuration.dbid = r.r) + -> Materialize + Output: gp_segment_configuration.dbid + -> Broadcast Motion 1:3 (slice1) + Output: gp_segment_configuration.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + Optimizer: Pivotal Optimizer (GPORCA) +(17 rows) + +explain (verbose, costs off) +select (select c from c where c = r limit 1 offset r) from r; + QUERY PLAN +--------------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: gp_segment_configuration.dbid + -> Result + Output: gp_segment_configuration.dbid + Filter: (gp_segment_configuration.dbid = r.r) + -> Materialize + Output: gp_segment_configuration.dbid + -> Broadcast Motion 1:3 (slice1) + Output: gp_segment_configuration.dbid + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + Optimizer: Pivotal Optimizer (GPORCA) +(19 rows) + +explain (verbose, costs off) +select (select r from r limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Pivotal Optimizer (GPORCA) +(14 rows) + +explain (verbose, costs off) +select (select r from r where r = c) from c; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 (slice0) + -> Result + Output: r.r + Filter: (r.r = gp_segment_configuration.dbid) + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Pivotal Optimizer (GPORCA) +(15 rows) + +explain (verbose, costs off) +select (select r from r where r = c limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Result + Output: r.r + Filter: (r.r = gp_segment_configuration.dbid) + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Pivotal Optimizer (GPORCA) +(17 rows) + +explain (verbose, costs off) +select (select d from d limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice2; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Pivotal Optimizer (GPORCA) +(16 rows) + +explain (verbose, costs off) +select (select d from d where d = p) from p; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Result + Output: d.d + Filter: (d.d = p.p) + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice2; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Pivotal Optimizer (GPORCA) +(17 rows) + +explain (verbose, costs off) +select (select d from d where d = p limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Limit + Output: d.d + -> Result + Output: d.d + Filter: (d.d = p.p) + -> Materialize + Output: d.d + -> Gather Motion 3:1 (slice2; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Pivotal Optimizer (GPORCA) +(19 rows) + +explain (verbose, costs off) +select (select p from p limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice1; segments: 3) + -> Limit + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Pivotal Optimizer (GPORCA) +(12 rows) + +explain (verbose, costs off) +select (select p from p where p = d) from d; + QUERY PLAN +------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice1; segments: 3) + -> Seq Scan on subselect_gp.p + Output: p.p + Filter: (p.p = d.d) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select p from p where p = d limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice1; segments: 3) + -> Limit + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Filter: (p.p = d.d) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select d from d limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: d.d + -> Materialize + Output: d.d + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Pivotal Optimizer (GPORCA) +(16 rows) + +explain (verbose, costs off) +select (select d from d where d = r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice2; segments: 3) + -> Result + Output: d.d + Filter: (d.d = r.r) + -> Materialize + Output: d.d + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Pivotal Optimizer (GPORCA) +(17 rows) + +explain (verbose, costs off) +select (select d from d where d = r limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: d.d + -> Result + Output: d.d + Filter: (d.d = r.r) + -> Materialize + Output: d.d + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + Optimizer: Pivotal Optimizer (GPORCA) +(19 rows) + +explain (verbose, costs off) +select (select r from r limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: r.r + -> Materialize + Output: r.r + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Pivotal Optimizer (GPORCA) +(16 rows) + +explain (verbose, costs off) +select (select r from r where r = d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice2; segments: 3) + -> Result + Output: r.r + Filter: (r.r = d.d) + -> Materialize + Output: r.r + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Pivotal Optimizer (GPORCA) +(17 rows) + +explain (verbose, costs off) +select (select r from r where r = d limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: r.r + -> Result + Output: r.r + Filter: (r.r = d.d) + -> Materialize + Output: r.r + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Pivotal Optimizer (GPORCA) +(19 rows) + +explain (verbose, costs off) +select (select p from p limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice1; segments: 3) + -> Limit + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Optimizer: Pivotal Optimizer (GPORCA) +(12 rows) + +explain (verbose, costs off) +select (select p from p where p = r) from r; + QUERY PLAN +------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice1; segments: 3) + -> Seq Scan on subselect_gp.p + Output: p.p + Filter: (p.p = r.r) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select p from p where p = r limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------ + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice1; segments: 3) + -> Limit + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + Filter: (p.p = r.r) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select r from r limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice2; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Pivotal Optimizer (GPORCA) +(16 rows) + +explain (verbose, costs off) +select (select r from r where r = p) from p; + QUERY PLAN +-------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Result + Output: r.r + Filter: (r.r = p.p) + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice2; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Pivotal Optimizer (GPORCA) +(17 rows) + +explain (verbose, costs off) +select (select r from r where r = p limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Limit + Output: r.r + -> Result + Output: r.r + Filter: (r.r = p.p) + -> Materialize + Output: r.r + -> Gather Motion 3:1 (slice2; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + Optimizer: Pivotal Optimizer (GPORCA) +(19 rows) + +create function i(i int) returns setof int language plpgsql immutable as $$ begin return query select i; end $$; +create function s(s int) returns setof int language plpgsql stable as $$ begin return query select s; end $$; +create function v(v int) returns setof int language plpgsql volatile as $$ begin return query select v; end $$; +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; + QUERY PLAN +------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select i from i(c)) from c; + QUERY PLAN +---------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i((gp_segment_configuration.dbid)::integer) + Optimizer: Pivotal Optimizer (GPORCA) +(9 rows) + +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; + QUERY PLAN +---------------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i((gp_segment_configuration.dbid)::integer) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; + QUERY PLAN +------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select s from s(c)) from c; + QUERY PLAN +---------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s((gp_segment_configuration.dbid)::integer) + Optimizer: Pivotal Optimizer (GPORCA) +(9 rows) + +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; + QUERY PLAN +---------------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s((gp_segment_configuration.dbid)::integer) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; + QUERY PLAN +------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select v from v(c)) from c; + QUERY PLAN +---------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v((gp_segment_configuration.dbid)::integer) + Optimizer: Pivotal Optimizer (GPORCA) +(9 rows) + +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; + QUERY PLAN +---------------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Seq Scan on pg_catalog.gp_segment_configuration + Output: gp_segment_configuration.dbid + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v((gp_segment_configuration.dbid)::integer) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice1; segments: 3) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select i from i(d)) from d; + QUERY PLAN +----------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice1; segments: 3) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(d.d) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice1; segments: 3) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(d.d) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice0) + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select s from s(d)) from d; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice0) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(d.d) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice0) + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(d.d) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice0) + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select v from v(d)) from d; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice0) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(d.d) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: d.d + -> Seq Scan on subselect_gp.d + Output: d.d + SubPlan 1 (slice0) + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(d.d) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; + QUERY PLAN +--------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Pivotal Optimizer (GPORCA) +(12 rows) + +explain (verbose, costs off) +select (select i from i(g)) from g; + QUERY PLAN +------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(generate_series.generate_series) + Optimizer: Pivotal Optimizer (GPORCA) +(10 rows) + +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; + QUERY PLAN +------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(generate_series.generate_series) + Optimizer: Pivotal Optimizer (GPORCA) +(12 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; + QUERY PLAN +--------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Pivotal Optimizer (GPORCA) +(12 rows) + +explain (verbose, costs off) +select (select s from s(g)) from g; + QUERY PLAN +------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(generate_series.generate_series) + Optimizer: Pivotal Optimizer (GPORCA) +(10 rows) + +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; + QUERY PLAN +------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(generate_series.generate_series) + Optimizer: Pivotal Optimizer (GPORCA) +(12 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; + QUERY PLAN +--------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Pivotal Optimizer (GPORCA) +(12 rows) + +explain (verbose, costs off) +select (select v from v(g)) from g; + QUERY PLAN +------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(generate_series.generate_series) + Optimizer: Pivotal Optimizer (GPORCA) +(10 rows) + +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; + QUERY PLAN +------------------------------------------------------------------- + Result + Output: (SubPlan 1) + -> Function Scan on pg_catalog.generate_series + Output: generate_series.generate_series + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(generate_series.generate_series) + Optimizer: Pivotal Optimizer (GPORCA) +(12 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select i from i(p)) from p; + QUERY PLAN +----------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice1; segments: 1) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(p.p) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------- + Gather Motion 1:1 (slice1; segments: 1) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice1; segments: 1) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(p.p) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select s from s(p)) from p; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(p.p) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(p.p) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select v from v(p)) from p; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(p.p) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 1:1 (slice1; segments: 1) + Output: p.p + -> Seq Scan on subselect_gp.p + Output: p.p + SubPlan 1 (slice0) + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(p.p) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice1; segments: 3) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select i from i(r)) from r; + QUERY PLAN +----------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice1; segments: 3) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(r.r) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------- + Gather Motion 3:1 (slice1; segments: 3) + Output: ((SubPlan 1)) + -> Result + Output: (SubPlan 1) + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice1; segments: 3) + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(r.r) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice0) + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select s from s(r)) from r; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice0) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(r.r) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice0) + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(r.r) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice0) + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +explain (verbose, costs off) +select (select v from v(r)) from r; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice0) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(r.r) + Optimizer: Pivotal Optimizer (GPORCA) +(11 rows) + +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; + QUERY PLAN +------------------------------------------------ + Result + Output: (SubPlan 1) + -> Gather Motion 3:1 (slice1; segments: 3) + Output: r.r + -> Seq Scan on subselect_gp.r + Output: r.r + SubPlan 1 (slice0) + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(r.r) + Optimizer: Pivotal Optimizer (GPORCA) +(13 rows) + +alter function i(i int) execute on all segments; +alter function s(s int) execute on all segments; +alter function v(v int) execute on all segments; +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Gather Motion 3:1 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(17 rows) + +explain (verbose, costs off) +select (select i from i(c)) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Gather Motion 3:1 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(17 rows) + +explain (verbose, costs off) +select (select s from s(c)) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; + QUERY PLAN +-------------------------------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 (slice0) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Gather Motion 3:1 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(17 rows) + +explain (verbose, costs off) +select (select v from v(c)) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(19 rows) + +explain (verbose, costs off) +select (select i from i(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(19 rows) + +explain (verbose, costs off) +select (select s from s(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(19 rows) + +explain (verbose, costs off) +select (select v from v(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Gather Motion 3:1 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(18 rows) + +explain (verbose, costs off) +select (select i from i(g)) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Gather Motion 3:1 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(18 rows) + +explain (verbose, costs off) +select (select s from s(g)) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; + QUERY PLAN +-------------------------------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 (slice0) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Gather Motion 3:1 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(18 rows) + +explain (verbose, costs off) +select (select v from v(g)) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Gather Motion 3:1 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(19 rows) + +explain (verbose, costs off) +select (select i from i(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Gather Motion 3:1 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(19 rows) + +explain (verbose, costs off) +select (select s from s(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; + QUERY PLAN +-------------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Gather Motion 3:1 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(19 rows) + +explain (verbose, costs off) +select (select v from v(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: i.i + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(19 rows) + +explain (verbose, costs off) +select (select i from i(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(19 rows) + +explain (verbose, costs off) +select (select s from s(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 3:3 (slice1; segments: 3) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(19 rows) + +explain (verbose, costs off) +select (select v from v(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +alter function i(i int) execute on master; +alter function s(s int) execute on master; +alter function v(v int) execute on master; +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(9 rows) + +explain (verbose, costs off) +select (select i from i(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i((c.dbid)::integer) + Optimizer: Postgres query optimizer +(7 rows) + +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i((c.dbid)::integer) + Optimizer: Postgres query optimizer +(9 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(9 rows) + +explain (verbose, costs off) +select (select s from s(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s((c.dbid)::integer) + Optimizer: Postgres query optimizer +(7 rows) + +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s((c.dbid)::integer) + Optimizer: Postgres query optimizer +(9 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(9 rows) + +explain (verbose, costs off) +select (select v from v(c)) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v((c.dbid)::integer) + Optimizer: Postgres query optimizer +(7 rows) + +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; + QUERY PLAN +----------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 1) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v((c.dbid)::integer) + Optimizer: Postgres query optimizer +(9 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 1:3 (slice1) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(17 rows) + +explain (verbose, costs off) +select (select i from i(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:3 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(17 rows) + +explain (verbose, costs off) +select (select s from s(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:3 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(17 rows) + +explain (verbose, costs off) +select (select v from v(d)) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(10 rows) + +explain (verbose, costs off) +select (select i from i(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(g.g) + Optimizer: Postgres query optimizer +(8 rows) + +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(g.g) + Optimizer: Postgres query optimizer +(10 rows) + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(10 rows) + +explain (verbose, costs off) +select (select s from s(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(g.g) + Optimizer: Postgres query optimizer +(8 rows) + +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(g.g) + Optimizer: Postgres query optimizer +(10 rows) + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(10 rows) + +explain (verbose, costs off) +select (select v from v(g)) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(g.g) + Optimizer: Postgres query optimizer +(8 rows) + +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; + QUERY PLAN +----------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 1) + Function Call: generate_series(0, 9) + SubPlan 1 + -> Limit + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(g.g) + Optimizer: Postgres query optimizer +(10 rows) + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 1:1 (slice1) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(17 rows) + +explain (verbose, costs off) +select (select i from i(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:1 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(17 rows) + +explain (verbose, costs off) +select (select s from s(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 1) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:1 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(17 rows) + +explain (verbose, costs off) +select (select v from v(p)) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: i.i + -> Result + Output: i.i + -> Materialize + Output: i.i + -> Broadcast Motion 1:3 (slice1) + Output: i.i + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(17 rows) + +explain (verbose, costs off) +select (select i from i(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: s.s + -> Result + Output: s.s + -> Materialize + Output: s.s + -> Broadcast Motion 1:3 (slice1) + Output: s.s + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(17 rows) + +explain (verbose, costs off) +select (select s from s(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; + QUERY PLAN +----------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 1)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 1) + SubPlan 1 (slice2; segments: 3) + -> Limit + Output: v.v + -> Result + Output: v.v + -> Materialize + Output: v.v + -> Broadcast Motion 1:3 (slice1) + Output: v.v + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(17 rows) + +explain (verbose, costs off) +select (select v from v(r)) from r; +ERROR: cannot materialize function with correlated parameters +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; +ERROR: cannot materialize function with correlated parameters +alter function i(i int) execute on initplan; +alter function s(s int) execute on initplan; +alter function v(v int) execute on initplan; +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 2) + SubPlan 2 + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(13 rows) + +explain (verbose, costs off) +select (select i from i(c)) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 2) + SubPlan 2 + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(13 rows) + +explain (verbose, costs off) +select (select s from s(c)) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; + QUERY PLAN +--------------------------------------------------- + Seq Scan on pg_catalog.gp_segment_configuration c + Output: (SubPlan 2) + SubPlan 2 + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(13 rows) + +explain (verbose, costs off) +select (select v from v(c)) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Result + Output: i_1.i + -> Materialize + Output: i_1.i + -> Broadcast Motion 1:3 (slice1) + Output: i_1.i + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(21 rows) + +explain (verbose, costs off) +select (select i from i(d)) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Result + Output: s_1.s + -> Materialize + Output: s_1.s + -> Broadcast Motion 1:3 (slice1) + Output: s_1.s + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(21 rows) + +explain (verbose, costs off) +select (select s from s(d)) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.d + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Result + Output: v_1.v + -> Materialize + Output: v_1.v + -> Broadcast Motion 1:3 (slice1) + Output: v_1.v + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(21 rows) + +explain (verbose, costs off) +select (select v from v(d)) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; + QUERY PLAN +--------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 2) + Function Call: generate_series(0, 9) + SubPlan 2 + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(14 rows) + +explain (verbose, costs off) +select (select i from i(g)) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; + QUERY PLAN +--------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 2) + Function Call: generate_series(0, 9) + SubPlan 2 + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(14 rows) + +explain (verbose, costs off) +select (select s from s(g)) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; + QUERY PLAN +--------------------------------------------------- + Function Scan on pg_catalog.generate_series g + Output: (SubPlan 2) + Function Call: generate_series(0, 9) + SubPlan 2 + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(14 rows) + +explain (verbose, costs off) +select (select v from v(g)) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 1) + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Result + Output: i_1.i + -> Materialize + Output: i_1.i + -> Broadcast Motion 1:1 (slice1) + Output: i_1.i + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(21 rows) + +explain (verbose, costs off) +select (select i from i(p)) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 1) + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Result + Output: s_1.s + -> Materialize + Output: s_1.s + -> Broadcast Motion 1:1 (slice1) + Output: s_1.s + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(21 rows) + +explain (verbose, costs off) +select (select s from s(p)) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 1:1 (slice2; segments: 1) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.p + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 1) + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Result + Output: v_1.v + -> Materialize + Output: v_1.v + -> Broadcast Motion 1:1 (slice1) + Output: v_1.v + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(21 rows) + +explain (verbose, costs off) +select (select v from v(p)) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: i_1.i + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.i + Output: i.i + Function Call: i(1) + -> Result + Output: i_1.i + -> Materialize + Output: i_1.i + -> Broadcast Motion 1:3 (slice1) + Output: i_1.i + -> Function Scan on subselect_gp.i i_1 + Output: i_1.i + Function Call: i(1) + Optimizer: Postgres query optimizer +(21 rows) + +explain (verbose, costs off) +select (select i from i(r)) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: s_1.s + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.s + Output: s.s + Function Call: s(1) + -> Result + Output: s_1.s + -> Materialize + Output: s_1.s + -> Broadcast Motion 1:3 (slice1) + Output: s_1.s + -> Function Scan on subselect_gp.s s_1 + Output: s_1.s + Function Call: s(1) + Optimizer: Postgres query optimizer +(21 rows) + +explain (verbose, costs off) +select (select s from s(r)) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; + QUERY PLAN +--------------------------------------------------------------------------- + Gather Motion 3:1 (slice2; segments: 3) + Output: ((SubPlan 2)) + -> Seq Scan on subselect_gp.r + Output: (SubPlan 2) + SubPlan 2 (slice2; segments: 3) + -> Limit + Output: v_1.v + InitPlan 1 (returns $1) (slice3) + -> Function Scan on subselect_gp.v + Output: v.v + Function Call: v(1) + -> Result + Output: v_1.v + -> Materialize + Output: v_1.v + -> Broadcast Motion 1:3 (slice1) + Output: v_1.v + -> Function Scan on subselect_gp.v v_1 + Output: v_1.v + Function Call: v(1) + Optimizer: Postgres query optimizer +(21 rows) + +explain (verbose, costs off) +select (select v from v(r)) from r; +ERROR: plan should not reference subplan's variable +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; +ERROR: plan should not reference subplan's variable +drop function i(a int); +drop function s(a int); +drop function v(a int); +drop table d; +drop table p; +drop table r; +drop view c; +drop view g; diff --git a/src/test/regress/expected/update_gp_optimizer.out b/src/test/regress/expected/update_gp_optimizer.out index 86552f3f2023..a13d74df979c 100644 --- a/src/test/regress/expected/update_gp_optimizer.out +++ b/src/test/regress/expected/update_gp_optimizer.out @@ -122,45 +122,49 @@ EXPLAIN (COSTS OFF) UPDATE keo1 SET user_vie_act_cntr_marg_cum = 234.682 FROM (SELECT min (keo4.keo_para_budget_date) FROM keo4))) ) t1 WHERE t1.user_vie_project_code_pk = keo1.user_vie_project_code_pk; - QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Update - -> Split - -> Result - -> Hash Join - Hash Cond: ((keo1_1.user_vie_project_code_pk)::text = (keo2.projects_pk)::text) + -> Explicit Redistribute Motion 3:3 (slice8; segments: 3) + -> Split + -> Result -> Hash Join - Hash Cond: ((keo1.user_vie_project_code_pk)::text = (keo1_1.user_vie_project_code_pk)::text) - -> Seq Scan on keo1 + Hash Cond: ((keo1_1.user_vie_project_code_pk)::text = (keo2.projects_pk)::text) + -> Redistribute Motion 3:3 (slice6; segments: 3) + Hash Key: keo1.user_vie_project_code_pk + -> Hash Join + Hash Cond: ((keo1.user_vie_project_code_pk)::text = (keo1_1.user_vie_project_code_pk)::text) + -> Seq Scan on keo1 + -> Hash + -> Broadcast Motion 1:3 (slice5; segments: 1) + -> Hash Join + Hash Cond: ((keo1_1.user_vie_fiscal_year_period_sk)::text = (max((keo3.sky_per)::text))) + -> Gather Motion 3:1 (slice1; segments: 3) + -> Seq Scan on keo1 keo1_1 + -> Hash + -> Aggregate + -> Hash Join + Hash Cond: ((keo3.bky_per)::text = (keo4.keo_para_required_period)::text) + -> Gather Motion 3:1 (slice2; segments: 3) + -> Seq Scan on keo3 + -> Hash + -> Assert + Assert Cond: ((row_number() OVER (?)) = 1) + -> WindowAgg + -> Hash Join + Hash Cond: ((keo4.keo_para_budget_date)::text = (min((keo4_1.keo_para_budget_date)::text))) + -> Gather Motion 3:1 (slice3; segments: 3) + -> Seq Scan on keo4 + -> Hash + -> Aggregate + -> Gather Motion 3:1 (slice4; segments: 3) + -> Seq Scan on keo4 keo4_1 -> Hash - -> Broadcast Motion 1:3 (slice5; segments: 1) - -> Hash Join - Hash Cond: ((keo1_1.user_vie_fiscal_year_period_sk)::text = (max((keo3.sky_per)::text))) - -> Gather Motion 3:1 (slice1; segments: 3) - -> Seq Scan on keo1 keo1_1 - -> Hash - -> Aggregate - -> Hash Join - Hash Cond: ((keo3.bky_per)::text = (keo4.keo_para_required_period)::text) - -> Gather Motion 3:1 (slice2; segments: 3) - -> Seq Scan on keo3 - -> Hash - -> Assert - Assert Cond: ((row_number() OVER (?)) = 1) - -> WindowAgg - -> Hash Join - Hash Cond: ((keo4.keo_para_budget_date)::text = (min((keo4_1.keo_para_budget_date)::text))) - -> Gather Motion 3:1 (slice3; segments: 3) - -> Seq Scan on keo4 - -> Hash - -> Aggregate - -> Gather Motion 3:1 (slice4; segments: 3) - -> Seq Scan on keo4 keo4_1 - -> Hash - -> Broadcast Motion 3:3 (slice6; segments: 3) - -> Seq Scan on keo2 + -> Redistribute Motion 3:3 (slice7; segments: 3) + Hash Key: keo2.projects_pk + -> Seq Scan on keo2 Optimizer: Pivotal Optimizer (GPORCA) -(36 rows) +(40 rows) UPDATE keo1 SET user_vie_act_cntr_marg_cum = 234.682 FROM ( SELECT a.user_vie_project_code_pk FROM keo1 a INNER JOIN keo2 b @@ -227,19 +231,19 @@ INSERT INTO t_strewn SELECT generate_series(1, 16); INSERT INTO t_strewn2 SELECT generate_series(2, 17); EXPLAIN (costs off) UPDATE t1 SET j = t_strewn.i FROM t_strewn WHERE t_strewn.i = t1.i; - QUERY PLAN ------------------------------------------------------------------------------- + QUERY PLAN +------------------------------------------------------------------------ Update -> Redistribute Motion 3:3 (slice2; segments: 3) Hash Key: t1.i -> Split -> Hash Join - Hash Cond: (t1.i = t_strewn.i) - -> Seq Scan on t1 + Hash Cond: (t_strewn.i = t1.i) + -> Redistribute Motion 3:3 (slice1; segments: 3) + Hash Key: t_strewn.i + -> Seq Scan on t_strewn -> Hash - -> Redistribute Motion 3:3 (slice1; segments: 3) - Hash Key: t_strewn.i - -> Seq Scan on t_strewn + -> Seq Scan on t1 Optimizer: Pivotal Optimizer (GPORCA) (12 rows) diff --git a/src/test/regress/expected/vacuum_full_ao.out b/src/test/regress/expected/vacuum_full_ao.out index a79b7222d2a2..7e70ddf11d83 100644 --- a/src/test/regress/expected/vacuum_full_ao.out +++ b/src/test/regress/expected/vacuum_full_ao.out @@ -33,3 +33,78 @@ select pg_relation_size((select segrelid from pg_appendonly where relid = 'vfao' 32768 (1 row) +-- Test that vacuum can process segment files created in an aborted transaction +create table table_ao_col (i int, j int, k int) with (appendonly='true', orientation="column"); +begin; +insert into table_ao_col select i, i + 1, i + 2 from generate_series(1, 20) i; +\! psql regression -c 'begin; insert into table_ao_col select i, i + 1, i + 2 from generate_series(1, 20) i; rollback;' +ROLLBACK +commit; +create or replace function getTableSegFiles(t regclass, out gp_contentid smallint, out filepath text) +as 'select current_setting(''gp_contentid'')::smallint, pg_relation_filepath(t)' +language sql +execute on all segments; +create or replace function cmdCheckSegmentFileSizes(table_name text) returns text as +$$ +declare + cmd text; +begin + select '\! (stat --format=''%s'' ' || string_agg(full_path_relfilenode, ' ') || ' 2>/dev/null || echo 0) | awk ''{sum += $1} END {print sum}''' + into cmd + from + (select d.datadir || '/' || f.filepath || '.*' as full_path_relfilenode from getTableSegFiles(table_name::regclass) f join gp_segment_configuration d + on f.gp_contentid = d.content where d.content <> -1 and d.role = 'p')t; + + return cmd; +end +$$ language plpgsql; +select cmdCheckSegmentFileSizes('table_ao_col') check_segfiles_size +\gset +delete from table_ao_col where true; +vacuum table_ao_col; +:check_segfiles_size +0 +drop table table_ao_col; +-- Test that vacuum can process segment files created for a new column in an aborted transaction (case 1) +create table table_ao_col_1 (i int, j int, k int) with (appendonly='true', orientation="column"); +insert into table_ao_col_1 select i, i + 1, i + 2 from generate_series(1, 20) i; +begin; +alter table table_ao_col_1 add column a int; +update table_ao_col_1 set a = 1 where true; +rollback; +select cmdCheckSegmentFileSizes('table_ao_col_1') check_segfiles_size_1 +\gset +delete from table_ao_col_1 where true; +vacuum table_ao_col_1; +:check_segfiles_size_1 +0 +drop table table_ao_col_1; +-- Test that vacuum can process segment files created for a new column in an aborted transaction (case 2) +create table table_ao_col_2 (i int, j int, k int) with (appendonly='true', orientation="column"); +begin; +insert into table_ao_col_2 select i, i + 1, i + 2 from generate_series(1, 20) i; +alter table table_ao_col_2 add column a int; +update table_ao_col_2 set a = 1 where true; +rollback; +select cmdCheckSegmentFileSizes('table_ao_col_2') check_segfiles_size_2 +\gset +vacuum table_ao_col_2; +:check_segfiles_size_2 +0 +drop table table_ao_col_2; +-- Test vacuum for a AORO table after adding column in an aborted transaction +create table table_ao_row (i int, j int, k int) with (appendonly='true', orientation="row"); +insert into table_ao_row select i, i + 1, i + 2 from generate_series(1, 20) i; +begin; +alter table table_ao_row add column a int; +update table_ao_row set a = 1 where true; +rollback; +select cmdCheckSegmentFileSizes('table_ao_row') check_segfiles_size_aoro +\gset +delete from table_ao_row where true; +vacuum table_ao_row; +:check_segfiles_size_aoro +0 +drop table table_ao_row; +drop function cmdCheckSegmentFileSizes(table_name text); +drop function getTableSegFiles(t regclass, out gp_contentid smallint, out filepath text); diff --git a/src/test/regress/greengage_schedule b/src/test/regress/greengage_schedule index 51d9e6f71ec2..08d6e20f2d1c 100755 --- a/src/test/regress/greengage_schedule +++ b/src/test/regress/greengage_schedule @@ -195,8 +195,9 @@ test: rpt rpt_joins rpt_tpch rpt_returning bfv_dml_rpt # other sessions. Therefore the other tests in this group mustn't create # temp tables test: bfv_cte bfv_joins bfv_planner bfv_subquery bfv_legacy bfv_temp bfv_dml +test: bfv_oom -test: qp_olap_mdqa qp_misc gp_recursive_cte qp_dml_joins qp_dml_oids trigger_sets_oid qp_skew qp_select +test: qp_olap_mdqa qp_misc gp_recursive_cte qp_dml_joins qp_dml_oids trigger_sets_oid qp_skew qp_select gp_cast test: qp_misc_jiras qp_with_clause qp_executor qp_olap_windowerr qp_olap_window qp_derived_table qp_bitmapscan qp_dropped_cols test: qp_with_functional_inlining qp_with_functional_noinlining diff --git a/src/test/regress/pg_regress.c b/src/test/regress/pg_regress.c index aaaa5066424f..9122f700fc0a 100644 --- a/src/test/regress/pg_regress.c +++ b/src/test/regress/pg_regress.c @@ -755,6 +755,7 @@ convert_sourcefiles_in(char *source_subdir, char *dest_dir, char *dest_subdir, c { char testtablespace[MAXPGPATH]; char indir[MAXPGPATH]; + char outdir[MAXPGPATH]; char cgroup_mnt_point[MAXPGPATH]; replacements repls; struct stat st; @@ -765,6 +766,7 @@ convert_sourcefiles_in(char *source_subdir, char *dest_dir, char *dest_subdir, c char *errstr; snprintf(indir, MAXPGPATH, "%s/%s", inputdir, source_subdir); + snprintf(outdir, MAXPGPATH, "%s/%s", dest_dir, dest_subdir); /* Check that indir actually exists and is a directory */ ret = stat(indir, &st); @@ -783,8 +785,8 @@ convert_sourcefiles_in(char *source_subdir, char *dest_dir, char *dest_subdir, c exit(2); /* also create the output directory if not present */ - if (!directory_exists(dest_subdir)) - make_directory(dest_subdir); + if (!directory_exists(outdir)) + make_directory(outdir); snprintf(testtablespace, MAXPGPATH, "%s/testtablespace", outputdir); @@ -2561,6 +2563,10 @@ open_result_files(void) char file[MAXPGPATH]; FILE *difffile; + /* create outputdir directory if not present */ + if (!directory_exists(outputdir)) + make_directory(outputdir); + /* create the log file (copy of running status output) */ snprintf(file, sizeof(file), "%s/regression.out", outputdir); logfilename = strdup(file); diff --git a/src/test/regress/regress_gp.c b/src/test/regress/regress_gp.c index 51d02238993a..8a6659060f72 100644 --- a/src/test/regress/regress_gp.c +++ b/src/test/regress/regress_gp.c @@ -2446,3 +2446,116 @@ gp_get_int_tuples(PG_FUNCTION_ARGS) SRF_RETURN_DONE(fctx); } + +typedef struct +{ + int cur_tuple_idx; + int cur_segment_idx; + int cur_segment_tuple_idx; + + int n_segments; + int n_tuples; + + Datum some_text; + struct pg_result **pg_results; +} gp_mock_cdbdispatchcommand_status; + +/* + * This test function mocks CdbDispatchCommand() with a customizable amount of + * tuples. + */ +PG_FUNCTION_INFO_V1(gp_mock_cdbdispatchcommand); +Datum +gp_mock_cdbdispatchcommand(PG_FUNCTION_ARGS) +{ + FuncCallContext *func_ctx; + gp_mock_cdbdispatchcommand_status *my_status; + + int arg_tuple_amount = PG_GETARG_INT32(0); + + if (arg_tuple_amount <= 0) + { + ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("gp_mock_cdbdispatchcommand() should only be " + "called with it's parameter greater than 0"))); + } + + if (SRF_IS_FIRSTCALL()) + { + func_ctx = SRF_FIRSTCALL_INIT(); + + MemoryContext oldcontext = + MemoryContextSwitchTo(func_ctx->multi_call_memory_ctx); + + my_status = palloc0(sizeof(gp_mock_cdbdispatchcommand_status)); + + /* Cache the return result. */ + my_status->some_text = CStringGetTextDatum("sometext"); + + /* Send the command to segments from QD. */ + if (Gp_role == GP_ROLE_DISPATCH) + { + char *query = + psprintf("SELECT * FROM gp_mock_cdbdispatchcommand(%d)", + arg_tuple_amount); + + CdbPgResults cdb_pgresults = {0}; + CdbDispatchCommand(query, DF_WITH_SNAPSHOT, &cdb_pgresults); + + pfree(query); + + Assert(cdb_pgresults.numResults > 0); + + for (int i = 0; i < cdb_pgresults.numResults; i++) + { + Assert(PQresultStatus(cdb_pgresults.pg_results[i]) == + PGRES_TUPLES_OK); + my_status->n_tuples += PQntuples(cdb_pgresults.pg_results[i]); + } + + my_status->n_segments = cdb_pgresults.numResults; + my_status->pg_results = cdb_pgresults.pg_results; + } + + func_ctx->user_fctx = my_status; + + MemoryContextSwitchTo(oldcontext); + } + + func_ctx = SRF_PERCALL_SETUP(); + my_status = func_ctx->user_fctx; + + /* Generate fake tuples from every segment. */ + if (my_status->cur_tuple_idx < arg_tuple_amount) + { + my_status->cur_tuple_idx++; + SRF_RETURN_NEXT(func_ctx, my_status->some_text); + } + + /* Receive tuples from the loop above on master. */ + if (Gp_role == GP_ROLE_DISPATCH) + { + while (my_status->cur_segment_idx < my_status->n_segments) + { + PGresult *res = my_status->pg_results[my_status->cur_segment_idx]; + + if (my_status->cur_segment_tuple_idx < PQntuples(res)) + { + Datum ret = CStringGetTextDatum( + PQgetvalue(res, my_status->cur_segment_tuple_idx, 0)); + + my_status->cur_segment_tuple_idx++; + SRF_RETURN_NEXT(func_ctx, ret); + } + + PQclear(res); + + my_status->cur_segment_idx++; + my_status->cur_segment_tuple_idx = 0; + } + + pfree(my_status->pg_results); + } + + SRF_RETURN_DONE(func_ctx); +} diff --git a/src/test/regress/sql/alter_table_aocs.sql b/src/test/regress/sql/alter_table_aocs.sql index 7856c4c61f27..f17a755a64e5 100644 --- a/src/test/regress/sql/alter_table_aocs.sql +++ b/src/test/regress/sql/alter_table_aocs.sql @@ -527,3 +527,18 @@ CREATE table aoco_insert_empty_row (a integer, b text, c integer) WITH (APPENDON INSERT INTO aoco_insert_empty_row SELECT 1,'a',1 FROM gp_id WHERE dbid=-999; -- assert non-empty seg entries SELECT * FROM gp_toolkit.__gp_aocsseg('aoco_insert_empty_row'::regclass); + +-- test case: Ensure that reads don't fail after aborting an add column + insert operation and we don't project the aborted column +CREATE TABLE aocs_addcol_abort(a int, b int) WITH (APPENDONLY=TRUE, ORIENTATION=COLUMN); +INSERT INTO aocs_addcol_abort SELECT i,i FROM generate_series(1,10)i; +BEGIN; +ALTER TABLE aocs_addcol_abort ADD COLUMN c int; +INSERT INTO aocs_addcol_abort SELECT i,i,i FROM generate_series(1,10)i; +-- check state of aocsseg for entries of add column + insert +SELECT * FROM gp_toolkit.__gp_aocsseg('aocs_addcol_abort') ORDER BY column_num; +SELECT * FROM aocs_addcol_abort; +ABORT; +-- check state of aocsseg if entries for new column are rolled back correctly +SELECT * FROM gp_toolkit.__gp_aocsseg('aocs_addcol_abort') ORDER BY column_num; +SELECT * FROM aocs_addcol_abort; +DROP TABLE aocs_addcol_abort; diff --git a/src/test/regress/sql/bfv_joins.sql b/src/test/regress/sql/bfv_joins.sql index 81b6d3558e33..4f3e0457cc25 100644 --- a/src/test/regress/sql/bfv_joins.sql +++ b/src/test/regress/sql/bfv_joins.sql @@ -575,6 +575,24 @@ set enable_seqscan=off; explain select * from r_table2 where ra2 in ( select a from l_table join r_table1 on b = rb1); select * from r_table2 where ra2 in ( select a from l_table join r_table1 on b = rb1); +-- Testcase for hash join rescan clearing batch files for outer subplan +truncate l_table; +truncate r_table1; +insert into l_table select i, i%100 from generate_series(1, 20000) i; +insert into r_table1 select i%100, i from generate_series(1, 10000) i; +insert into r_table1 select i%100, i from generate_series(1, 10000) i; +analyze l_table; +analyze r_table1; + +set statement_mem="1MB"; +explain analyze select * from r_table2 where ra2 in (select ra1 from l_table join r_table1 on b = rb1); +select * from r_table2 where ra2 in (select ra1 from l_table join r_table1 on b = rb1); + +set gp_workfile_compression=on; +select * from r_table2 where ra2 in (select ra1 from l_table join r_table1 on b = rb1); +reset gp_workfile_compression; +reset statement_mem; + reset optimizer; reset enable_nestloop; reset enable_bitmapscan; @@ -722,6 +740,18 @@ select from (values ('')) tmp(b) join lateral drop table t1; +-- test that empty table gets hashed instead of a bigger table +create table big_table(s smallint) distributed replicated; +create table empty_table(i int) distributed replicated; +insert into big_table select generate_series(1, 10000); +analyze big_table; +analyze empty_table; + +explain select * from big_table, empty_table where s = i; + +drop table big_table; +drop table empty_table; + -- Clean up. None of the objects we create are very interesting to keep around. reset search_path; set client_min_messages='warning'; diff --git a/src/test/regress/sql/bfv_oom.sql b/src/test/regress/sql/bfv_oom.sql new file mode 100644 index 000000000000..302b4f57f072 --- /dev/null +++ b/src/test/regress/sql/bfv_oom.sql @@ -0,0 +1,33 @@ +-- start_ignore +CREATE EXTENSION gp_inject_fault; +-- end_ignore + +-- start_matchsubs +-- m/WARNING:.*Any temporary tables for this session have been dropped because the gang was disconnected/ +-- s/session id \=\s*\d+/session id \= DUMMY/gm +-- end_matchsubs + +CREATE TEMP TABLE t1(); + +-- Emulate an OOM error and throw FATAL on any palloc() call. +SELECT gp_inject_fault('cdb_freelist_append_oom', 'skip', dbid), + gp_inject_fault('fatal_on_palloc_oom', 'skip', dbid) + FROM gp_segment_configuration + WHERE role = 'p' AND content = -1; + +-- We should gracefully recover instead of entering recursion, getting SIGSEGV, +-- or trying to allocate any more memory. +DO $$ + DECLARE + rec1 RECORD; + BEGIN + FOR rec1 IN SELECT * FROM t1 + LOOP + NULL; + END LOOP; + END; +$$; + +SELECT gp_inject_fault('all', 'reset', dbid) + FROM gp_segment_configuration + WHERE role = 'p' AND content = -1; diff --git a/src/test/regress/sql/function_extensions.sql b/src/test/regress/sql/function_extensions.sql index 30edbf43a62f..7cf33afd7f4c 100644 --- a/src/test/regress/sql/function_extensions.sql +++ b/src/test/regress/sql/function_extensions.sql @@ -417,3 +417,30 @@ insert into test_ao3 values(1,2),(2,3),(3,4); select count(*) from (select * from (select pg_catalog.gp_acquire_sample_rows('test_ao3'::regclass, 400, 'f')) ss limit 1) ss1; drop table test_ao3; + +-- Test initplan function referring the outer query. +-- The query below previously led to a SIGSEGV. +-- start_matchsubs +-- m/ \(subselect\.c:.*\)/ +-- s/ \(subselect\.c:.*\)// +-- end_matchsubs + +-- start_ignore +drop table if exists test_table; +drop function if exists test_function(param_in text); +-- end_ignore + +create table test_table(a text); + +create function test_function(param_in text) returns +table (param_out text) as +$function$ +select param_in; +$function$ +language sql execute on initplan; + +create table tnew as +select * from test_table l join test_function(l.a) r on l.a = r.param_out; + +drop function test_function(param_in text); +drop table test_table; diff --git a/src/test/regress/sql/gp_cast.sql b/src/test/regress/sql/gp_cast.sql new file mode 100644 index 000000000000..2ec9532a6175 --- /dev/null +++ b/src/test/regress/sql/gp_cast.sql @@ -0,0 +1,271 @@ +-- This file contains tests related to the casting behavior, primarily in joins. +-- Some of the tests performed here may already be present inside other files, +-- but it is nice to have a centralized place to observe and compare the behavior of the planners. +-- Tables here are prefixed with cst (which stands for 'cast') to avoid collisions. + +-- One of the tests below fails with an assertion, that prints its location in the source code. +-- Make sure that we don't need to update this file when its line changes. +-- start_matchsubs +-- m/DETAIL: CTranslatorQueryToDXL.cpp:\d+: Failed assertion/ +-- s/DETAIL: CTranslatorQueryToDXL.cpp:\d+: Failed assertion/DETAIL: CTranslatorQueryToDXL.cpp:###: Failed assertion/ +-- end_matchsubs + +set optimizer_enable_mergejoin = false; +-- We want to specifically test hashjoins for several queries below. +-- Nested loop joins are not constructed for these queries at the time, +-- and probably never will be, but let's make them additionally unlikely just in case. +set optimizer_nestloop_factor = 102400; +set enable_mergejoin = false; +set enable_nestloop = false; +set optimizer_trace_fallback = true; + +-- start_ignore +drop table if exists cst_int2; +drop table if exists cst_int4; +drop table if exists cst_int8; +drop table if exists cst_float4; +drop table if exists cst_float8; +drop table if exists cst_text; +drop table if exists cst_varchar; +drop table if exists cst_int2_int4; +drop table if exists cst_int4_int8; +-- end_ignore + +create table cst_int2 as (select a::int2 from generate_series(0, 10) as a) distributed by (a); +create table cst_int4 as (select a::int4 from generate_series(5, 15) as a) distributed by (a); +create table cst_int8 as (select a::int8 from generate_series(10, 20) as a) distributed by (a); +create table cst_float4 as (select a::float4 from generate_series(5, 15, 1) as a) distributed by (a); +create table cst_float8 as (select a::float8 from generate_series(5, 15, 1) as a) distributed by (a); +create table cst_text as (select a::text from generate_series(5, 15) as a) distributed by (a); +create table cst_varchar as (select a::varchar from generate_series(5, 15) as a) distributed by (a); +create table cst_int2_int4 as (select gen::int2 as a, gen::int4 as b from generate_series(1, 10) as gen) distributed by (a, b); +create table cst_int4_int8 as (select gen::int4 as a, gen::int8 as b from generate_series(1, 10) as gen) distributed by (a, b); + +-- Perform an inner join on all hash opfamilies containing more than one type. +-- We shouldn't see any redistributions, because: +-- The postgres-based planner has operators that work on different types. +-- ORCA doesn't support such operations, but it knows when a cast doesn't change a distribution. + +set optimizer_join_order = query; + +explain (verbose, costs off) select * from cst_int2 join cst_int4 using(a); +select * from cst_int2 join cst_int4 using(a); + +explain (verbose, costs off) select * from cst_int2 join cst_int8 using(a); +select * from cst_int2 join cst_int8 using(a); + +explain (verbose, costs off) select * from cst_int4 join cst_int8 using(a); +select * from cst_int4 join cst_int8 using(a); + +explain (verbose, costs off) select * from cst_float4 join cst_float8 using(a); +select * from cst_float4 join cst_float8 using(a); + +-- Same thing with the sides swapped +explain (verbose, costs off) select * from cst_int4 join cst_int2 using(a); +select * from cst_int4 join cst_int2 using(a); + +explain (verbose, costs off) select * from cst_int8 join cst_int2 using(a); +select * from cst_int8 join cst_int2 using(a); + +explain (verbose, costs off) select * from cst_int8 join cst_int4 using(a); +select * from cst_int8 join cst_int4 using(a); + +explain (verbose, costs off) select * from cst_float8 join cst_float4 using(a); +select * from cst_float8 join cst_float4 using(a); + +-- Confirm that casting logic works recursively +explain (verbose, costs off) +select * from cst_int2 + join cst_int8 using(a) + join cst_int4 using(a); + +select * from cst_int2 + join cst_int8 using(a) + join cst_int4 using(a); + +reset optimizer_join_order; + +-- BUG: this test is failing for ORCA. +-- It's the test that requires start_matchsubs. +explain (verbose, costs off) select * from cst_int2 left join cst_int4 using(a); +select * from cst_int2 left join cst_int4 using(a); + +explain (verbose, costs off) select * from cst_int2 right join cst_int4 using(a); +select * from cst_int2 right join cst_int4 using(a); + +explain (verbose, costs off) +select * from cst_int4 +where exists (select * + from cst_int2 + where cst_int4.a = cst_int2.a); + +select * from cst_int4 +where exists (select * + from cst_int2 + where cst_int4.a = cst_int2.a); + +explain (verbose, costs off) +select * from cst_int4 +where not exists (select * + from cst_int2 + where cst_int4.a = cst_int2.a); + +select * from cst_int4 +where not exists (select * + from cst_int2 + where cst_int4.a = cst_int2.a); + +explain (verbose, costs off) +select * from cst_int4 +where cst_int4.a not in (select * from cst_int2); + +select * from cst_int4 +where cst_int4.a not in (select * from cst_int2); + +explain (verbose, costs off) +select * from cst_int2 natural join cst_int4; +select * from cst_int2 natural join cst_int4; + + +-- Here, instead of an implicit cast, an explicit one is present. +-- The postgres-based planner should require a redistribution, because +-- distribution of the cst_int2 table is not directly equal to the left-hand side of the expression. +-- ORCA, on the other hand, can see that redistribution is unnecessary in this case. +explain (verbose, costs off) select * from cst_int2 join cst_int4 on cst_int2.a::int4 = cst_int4.a; +select * from cst_int2 join cst_int4 on cst_int2.a::int4 = cst_int4.a; + + +-- The same thing, but with multiple casts in a row. +-- Because the first cast tends to be converted directly to a conversion function, +-- ORCA shouldn't be able to detect the first coercion and should require a redistribution. +explain (verbose, costs off) select * from cst_float4 as cst_float4_f join cst_float4 as cst_float4_s on cst_float4_f.a::int::float4 = cst_float4_s.a; +select * from cst_float4 as cst_float4_f join cst_float4 as cst_float4_s on cst_float4_f.a::int::float4 = cst_float4_s.a; + +-- Check that binary coercible casts are ruled out +explain (verbose, costs off) select * from cst_varchar as foo join cst_varchar as bar using(a); +select * from cst_varchar as foo join cst_varchar as bar using(a); + +explain (verbose, costs off) select * from cst_varchar join cst_text using(a); +select * from cst_varchar join cst_text using(a); + +-- Сheck that we don't rule out necessary distributions. +-- Most basic cases: +explain (verbose, costs off) select * from cst_float4 join cst_int4 using(a); +select * from cst_float4 join cst_int4 using(a); + +explain (verbose, costs off) select * from cst_int4 join cst_text on cst_int4.a = cst_text.a::int4; +select * from cst_int4 join cst_text on cst_int4.a = cst_text.a::int4; + + +-- ORCA: in order for there queries to work, equivalent expressions should be matched correctly +explain (verbose, costs off) +with int8_cte as (select * from cst_int8) +select * from (cst_int2 join int8_cte as cte_1 using(a)) + join (int8_cte as cte_2 join cst_int4 using(a)) using(a); + +with int8_cte as (select * from cst_int8) +select * from (cst_int2 join int8_cte as cte_1 using(a)) + join (int8_cte as cte_2 join cst_int4 using(a)) using(a); + +explain (verbose, costs off) +with int8_cte as (select * from cst_int8) +select * from (cst_int2 join int8_cte as cte_1 using(a)) + join (cst_int4 join int8_cte as cte_2 using(a)) using(a); + +with int8_cte as (select * from cst_int8) +select * from (cst_int2 join int8_cte as cte_1 using(a)) + join (cst_int4 join int8_cte as cte_2 using(a)) using(a); + + +-- Test distribution by multiple keys +explain (verbose, costs off) +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.a and t1.b = t2.b); +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.a and t1.b = t2.b); + +explain (verbose, costs off) +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.b and t1.b = t2.a); +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.b and t1.b = t2.a); + +explain (verbose, costs off) +select * from cst_int2_int4 as t1 join cst_int2 as t2 on (t1.a = t2.a); +select * from cst_int2_int4 as t1 join cst_int2 as t2 on (t1.a = t2.a); + +set optimizer_join_order = query; +explain (verbose, costs off) +with cst_int2_int4_copy as (select * from cst_int2_int4) +select * from cst_int2_int4 + natural join cst_int4_int8 + natural join cst_int2_int4_copy; + +with cst_int2_int4_copy as (select * from cst_int2_int4) +select * from cst_int2_int4 + natural join cst_int4_int8 + natural join cst_int2_int4_copy; + + +-- Test several queries with nested-loop join +reset optimizer_nestloop_factor; +set enable_nestloop = true; +set optimizer_enable_hashjoin = false; +set enable_hashjoin = false; + +explain (verbose, costs off) select * from cst_int2 join cst_int4 using(a); +select * from cst_int2 join cst_int4 using(a); + +-- Subtle behavior ahead: in ORCA, nested loop joins don't support equivalent expressions +-- like hash joins do. +-- So, when join order is fixed, we need to be careful with the join condition, +-- otherwise we might get a broadcast motion. +explain (verbose, costs off) +select * from cst_int2 + join cst_int4 on cst_int2.a = cst_int4.a + join cst_int8 on cst_int4.a = cst_int8.a; + +select * from cst_int2 + join cst_int4 on cst_int2.a = cst_int4.a + join cst_int8 on cst_int4.a = cst_int8.a; + +-- Luckily, when join order is not fixed, optimizer finds a join path that +-- gets rid of the broadcast. +reset optimizer_join_order; +explain (verbose, costs off) +select * from cst_int2 + join cst_int4 on cst_int2.a = cst_int4.a + join cst_int8 on cst_int4.a = cst_int8.a; + +select * from cst_int2 + join cst_int4 on cst_int2.a = cst_int4.a + join cst_int8 on cst_int4.a = cst_int8.a; + +-- Test very specific logic for a join on several keys with an index in ORCA +create index cst_int4_int8_idx on cst_int4_int8 (b); +explain (verbose, costs off) +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.a and t1.b = t2.b); +select * from cst_int2_int4 as t1 join cst_int4_int8 as t2 on (t1.a = t2.a and t1.b = t2.b); +drop index cst_int4_int8_idx; + +-- Binary coercible casts should be ruled out too +explain (verbose, costs off) select * from cst_varchar as foo join cst_varchar as bar using(a); +select * from cst_varchar as foo join cst_varchar as bar using(a); + +explain (verbose, costs off) select * from cst_varchar join cst_text using(a); +select * from cst_varchar join cst_text using(a); + + +drop table cst_int2; +drop table cst_int4; +drop table cst_int8; +drop table cst_float4; +drop table cst_float8; +drop table cst_text; +drop table cst_varchar; +drop table cst_int2_int4; +drop table cst_int4_int8; + +reset optimizer_trace_fallback; +reset enable_hashjoin; +reset enable_nestloop; +reset enable_mergejoin; +reset optimizer_enable_hashjoin; +reset optimizer_nestloop_factor; +reset optimizer_enable_mergejoin; diff --git a/src/test/regress/sql/guc_gp.sql b/src/test/regress/sql/guc_gp.sql index 5333947c4322..6e178ed7ed89 100644 --- a/src/test/regress/sql/guc_gp.sql +++ b/src/test/regress/sql/guc_gp.sql @@ -400,3 +400,45 @@ RESET search_path; -- Try to set statement_mem > max_statement_mem SET statement_mem = '4000MB'; RESET statement_mem; + +CREATE TABLE guc_gp_t1(i int) DISTRIBUTED BY (i); +INSERT INTO guc_gp_t1 VALUES(1),(2); + +-- generate an idle redaer gang by the following query +SELECT count(*) FROM guc_gp_t1, guc_gp_t1 t; + +-- test create role and set role in the same transaction +BEGIN; +DROP ROLE IF EXISTS guc_gp_test_role1; +CREATE ROLE guc_gp_test_role1; +SET ROLE guc_gp_test_role1; +RESET ROLE; +END; + +-- generate an idle redaer gang by the following query +SELECT count(*) FROM guc_gp_t1, guc_gp_t1 t; + +BEGIN ISOLATION LEVEL REPEATABLE READ; +DROP ROLE IF EXISTS guc_gp_test_role2; +CREATE ROLE guc_gp_test_role2; +SET ROLE guc_gp_test_role2; +RESET ROLE; +END; + +-- test cursor case +-- cursors are also reader gangs, but they are not idle, thus will not be +-- destroyed by utility statement. +BEGIN; +DECLARE c1 CURSOR FOR SELECT * FROM guc_gp_t1 a, guc_gp_t1 b order by a.i, b.i; +DECLARE c2 CURSOR FOR SELECT * FROM guc_gp_t1 a, guc_gp_t1 b order by a.i, b.i; +FETCH c1; +DROP ROLE IF EXISTS guc_gp_test_role1; +CREATE ROLE guc_gp_test_role1; +SET ROLE guc_gp_test_role1; +RESET ROLE; +FETCH c2; +FETCH c1; +FETCH c2; +END; + +DROP TABLE guc_gp_t1; diff --git a/src/test/regress/sql/qp_correlated_query.sql b/src/test/regress/sql/qp_correlated_query.sql index b32528153583..fbb745751454 100644 --- a/src/test/regress/sql/qp_correlated_query.sql +++ b/src/test/regress/sql/qp_correlated_query.sql @@ -833,7 +833,118 @@ DROP TABLE skip_correlated_t3; DROP TABLE skip_correlated_t4; reset optimizer_join_order; reset optimizer_trace_fallback; +-------------------------------------------------------------------------------- +-- ORCA should be able to plan and execute correctly skip-level queries, but not +-- with master-only. Postgres Legacy planner should give an error to skip-level +-- query involving distributed or replicated tables. +-------------------------------------------------------------------------------- +--start_ignore +DROP TABLE IF EXISTS skip_correlated_distributed; +DROP TABLE IF EXISTS skip_correlated_random; +DROP TABLE IF EXISTS skip_correlated_replicated; +--end_ignore +CREATE TABLE skip_correlated_distributed ( + a INT +) DISTRIBUTED BY (a); +INSERT INTO skip_correlated_distributed VALUES (1), (2), (3); + +CREATE TABLE skip_correlated_random ( + b INT +) DISTRIBUTED RANDOMLY; +INSERT INTO skip_correlated_random VALUES (1), (2), (3); + +CREATE TABLE skip_correlated_replicated ( + c INT +) DISTRIBUTED REPLICATED; +INSERT INTO skip_correlated_replicated VALUES(1), (2), (3); + +-- easy cases +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c + ) +) FROM skip_correlated_replicated; +SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c + ) +) FROM skip_correlated_replicated ORDER BY a; +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT b FROM skip_correlated_random WHERE b = a + ) +) FROM skip_correlated_distributed; +SELECT ( + SELECT ( + SELECT b FROM skip_correlated_random WHERE b = a + ) +) FROM skip_correlated_distributed ORDER BY b; + +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT c FROM skip_correlated_replicated WHERE c = a + ) +) FROM skip_correlated_distributed; +SELECT ( + SELECT ( + SELECT c FROM skip_correlated_replicated WHERE c = a + ) +) FROM skip_correlated_distributed ORDER BY c; + +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT dbid FROM gp_segment_configuration WHERE dbid = a + ) +) FROM skip_correlated_distributed; + +-- hard cases +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c + ) + ) +) AS l1 FROM skip_correlated_replicated ORDER BY l1; +SELECT ( + SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c + ) + ) +) AS l1 FROM skip_correlated_replicated ORDER BY l1; + +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c and a = b + ) as l3 FROM skip_correlated_random ORDER BY l3 LIMIT 1 + ) +) AS l1 FROM skip_correlated_replicated ORDER BY l1; +SELECT ( + SELECT ( + SELECT ( + SELECT a FROM skip_correlated_distributed WHERE a = c and a = b + ) as l3 FROM skip_correlated_random ORDER BY l3 LIMIT 1 + ) +) AS l1 FROM skip_correlated_replicated ORDER BY l1; + +EXPLAIN (COSTS OFF) +SELECT ( + SELECT ( + SELECT dbid FROM gp_segment_configuration WHERE dbid = numsegments LIMIT 1 + ) +) FROM gp_distribution_policy; + +DROP TABLE skip_correlated_distributed; +DROP TABLE skip_correlated_random; +DROP TABLE skip_correlated_replicated; -------------------------------------------------------------------------------- -- Ensure ORCA generates the correct plan with the exists clause -- for the partitioned table. @@ -868,6 +979,32 @@ SELECT id FROM offers WHERE EXISTS ( RESET optimizer_enforce_subplans; DROP TABLE offers; DROP TABLE contacts; +-------------------------------------------------------------------------------- +-- Test: ORCA-specific behavior related to distribution requests. +-- If a join condition has an 'AND' clause and multiple subexpressions that have +-- the same right-hand side, distribution requests to the outer table +-- can be lost, making it erroneously require a redistribute motion. +-- For more info, please refer to the comments inside +-- CPhysicalJoin::PdshashedMatching +-------------------------------------------------------------------------------- +EXPLAIN +SELECT * +FROM a +WHERE NOT EXISTS ( + SELECT * + FROM B + WHERE (a.j = b.i AND a.i = b.i) +); + +SELECT * +FROM a +WHERE NOT EXISTS ( + SELECT * + FROM B + WHERE (a.j = b.i AND a.i = b.i) +); + + -- ---------------------------------------------------------------------- -- Test: teardown.sql -- ---------------------------------------------------------------------- diff --git a/src/test/regress/sql/qp_functions_in_select.sql b/src/test/regress/sql/qp_functions_in_select.sql index 19e657d06b9e..5c1af4581f24 100644 --- a/src/test/regress/sql/qp_functions_in_select.sql +++ b/src/test/regress/sql/qp_functions_in_select.sql @@ -2111,3 +2111,21 @@ rollback; begin; SELECT func1_mod_setint_stb(func2_mod_int_stb(5)) order by 1; rollback; + +-- Test motions are not allowed on QE +--start_ignore +drop table if exists d; +drop function if exists f(); +--end_ignore +create table d(i int) distributed by (i); +insert into d select 1; + +create function f() returns int as $$ + select 1 from gp_dist_random('pg_group') union all select 1 from pg_group; +$$ language sql; + +-- error when execute such function on QE +select f() from d; + +drop table d; +drop function f(); diff --git a/src/test/regress/sql/qp_orca_fallback.sql b/src/test/regress/sql/qp_orca_fallback.sql index f587cbbd3857..c684c8c3cfcc 100644 --- a/src/test/regress/sql/qp_orca_fallback.sql +++ b/src/test/regress/sql/qp_orca_fallback.sql @@ -126,3 +126,17 @@ INSERT INTO partition_key_dropped VALUES(3); -- Orca should fallback if a function in 'from' clause uses 'WITH ORDINALITY' SELECT * FROM jsonb_array_elements('["b", "a"]'::jsonb) WITH ORDINALITY; + +-- Orca should fallback if a hash distribution expression does not have an opfamily. +-- (array types does not have legacy opfamilies) +-- create table with legacy hash distr. +-- start_ignore +DROP TABLE IF EXISTS t_legacy; +-- end_ignore +SET gp_use_legacy_hashops=1; +CREATE TABLE t_legacy (i INT, arr INT[]) DISTRIBUTED BY (i); + +EXPLAIN (COSTS OFF) SELECT * FROM t_legacy INTERSECT ALL (SELECT * FROM t_legacy); + +DROP TABLE t_legacy; +RESET gp_use_legacy_hashops; diff --git a/src/test/regress/sql/qp_query_execution.sql b/src/test/regress/sql/qp_query_execution.sql index a0c5b41814b0..8fd6f0542f2d 100644 --- a/src/test/regress/sql/qp_query_execution.sql +++ b/src/test/regress/sql/qp_query_execution.sql @@ -249,7 +249,7 @@ insert into b select i%7, i%10, i , i || 'SOME NUMBER', i % 4 from generate_seri analyze abbp; analyze b; -select qx_count_operator('select abbp.k, abbp.t from abbp left outer join b on abbp.k = b.k where abbp.t is not null and abbp.p = 6;', 'Hash Right Join', 'Hash Left Join'); +select qx_count_operator('select abbp.k, abbp.t from abbp left outer join b on abbp.k = b.k where abbp.t is not null and abbp.p = 6;', 'Hash Right Join', 'Hash Right Join'); select abbp.k, abbp.t from abbp left outer join b on abbp.k = b.k where abbp.t is not null and abbp.p = 6 order by 1, 2 desc limit 10; select qx_count_operator('select abbp.b, abbp.t from abbp left outer join b on abbp.a = b.k where abbp.t is not null and abbp.a = 6;', 'Hash Right Join', 'Hash Left Join'); diff --git a/src/test/regress/sql/rangefuncs_cdb.sql b/src/test/regress/sql/rangefuncs_cdb.sql index fb37e3561154..816522143574 100644 --- a/src/test/regress/sql/rangefuncs_cdb.sql +++ b/src/test/regress/sql/rangefuncs_cdb.sql @@ -38,7 +38,7 @@ BEGIN RETURN NEXT r; RETURN; END -$$ language plpgsql; +$$ language plpgsql IMMUTABLE; -- function in select clause select foost(1); @@ -101,7 +101,7 @@ BEGIN RETURN NEXT rec; return; END -$$ LANGUAGE plpgsql; +$$ LANGUAGE plpgsql IMMUTABLE; -- function in select clause -- Fails: plpgsql does not support SFRM_Materialize @@ -173,7 +173,7 @@ BEGIN RETURN NEXT; RETURN; END; -$$ LANGUAGE plpgsql; +$$ LANGUAGE plpgsql IMMUTABLE; -- function in select clause select fooro(1); @@ -231,7 +231,7 @@ BEGIN RETURN NEXT; RETURN; END -$$ language plpgsql; +$$ language plpgsql IMMUTABLE; -- function in select clause select foot(1); diff --git a/src/test/regress/sql/subselect_gp.sql b/src/test/regress/sql/subselect_gp.sql index 1209cb03f0d6..ec03a833983d 100644 --- a/src/test/regress/sql/subselect_gp.sql +++ b/src/test/regress/sql/subselect_gp.sql @@ -1,3 +1,7 @@ +-- start_matchsubs +-- m/ \(subselect\.c:\d+\)/ +-- s/ \(subselect\.c:\d+\)// +-- end_matchsubs -- start_ignore create schema subselect_gp; set search_path to subselect_gp, public; @@ -1482,3 +1486,640 @@ drop table t3; drop table t_repl; drop table t2; drop table t1; + +-- Test subplan with correlated functions or master-only tables +--start_ignore +drop function if exists i(a int); +drop function if exists s(a int); +drop function if exists v(a int); +drop table if exists d; +drop table if exists p; +drop table if exists r; +drop view if exists c; +drop view if exists g; +--end_ignore +create table d(d int) distributed by (d); +insert into d select g from generate_series(0, 9) g; +analyze d; + +create table p(p int) distributed replicated; +insert into p select g from generate_series(0, 9) g; +analyze p; + +create table r(r int) distributed randomly; +insert into r select g from generate_series(0, 9) g; +analyze r; + +create view g as select g from generate_series(0, 9) g; +create view c as select dbid c from gp_segment_configuration c; + + +explain (verbose, costs off) +select (select c from c limit 1 offset g) from g; +explain (verbose, costs off) +select (select c from c where c = g) from g; +explain (verbose, costs off) +select (select c from c where c = g limit 1 offset g) from g; + +explain (verbose, costs off) +select (select g from g limit 1 offset c) from c; +explain (verbose, costs off) +select (select g from g where g = c) from c; +explain (verbose, costs off) +select (select g from g where g = c limit 1 offset c) from c; + +explain (verbose, costs off) +select (select d from d limit 1 offset g) from g; +explain (verbose, costs off) +select (select d from d where d = g) from g; +explain (verbose, costs off) +select (select d from d where d = g limit 1 offset g) from g; + +explain (verbose, costs off) +select (select g from g limit 1 offset d) from d; +explain (verbose, costs off) +select (select g from g where g = d) from d; +explain (verbose, costs off) +select (select g from g where g = d limit 1 offset d) from d; + +explain (verbose, costs off) +select (select p from p limit 1 offset g) from g; +explain (verbose, costs off) +select (select p from p where p = g) from g; +explain (verbose, costs off) +select (select p from p where p = g limit 1 offset g) from g; + +explain (verbose, costs off) +select (select g from g limit 1 offset p) from p; +explain (verbose, costs off) +select (select g from g where g = p) from p; +explain (verbose, costs off) +select (select g from g where g = p limit 1 offset p) from p; + +explain (verbose, costs off) +select (select r from r limit 1 offset g) from g; +explain (verbose, costs off) +select (select r from r where r = g) from g; +explain (verbose, costs off) +select (select r from r where r = g limit 1 offset g) from g; + +explain (verbose, costs off) +select (select g from g limit 1 offset r) from r; +explain (verbose, costs off) +select (select g from g where g = r) from r; +explain (verbose, costs off) +select (select g from g where g = r limit 1 offset r) from r; + +explain (verbose, costs off) +select (select c from c limit 1 offset d) from d; +explain (verbose, costs off) +select (select c from c where c = d) from d; +explain (verbose, costs off) +select (select c from c where c = d limit 1 offset d) from d; + +explain (verbose, costs off) +select (select d from d limit 1 offset c) from c; +explain (verbose, costs off) +select (select d from d where d = c) from c; +explain (verbose, costs off) +select (select d from d where d = c limit 1 offset c) from c; + +explain (verbose, costs off) +select (select c from c limit 1 offset p) from p; +explain (verbose, costs off) +select (select c from c where c = p) from p; +explain (verbose, costs off) +select (select c from c where c = p limit 1 offset p) from p; + +explain (verbose, costs off) +select (select p from p limit 1 offset c) from c; +explain (verbose, costs off) +select (select p from p where p = c) from c; +explain (verbose, costs off) +select (select p from p where p = c limit 1 offset c) from c; + +explain (verbose, costs off) +select (select c from c limit 1 offset r) from r; +explain (verbose, costs off) +select (select c from c where c = r) from r; +explain (verbose, costs off) +select (select c from c where c = r limit 1 offset r) from r; + +explain (verbose, costs off) +select (select r from r limit 1 offset c) from c; +explain (verbose, costs off) +select (select r from r where r = c) from c; +explain (verbose, costs off) +select (select r from r where r = c limit 1 offset c) from c; + +explain (verbose, costs off) +select (select d from d limit 1 offset p) from p; +explain (verbose, costs off) +select (select d from d where d = p) from p; +explain (verbose, costs off) +select (select d from d where d = p limit 1 offset p) from p; + +explain (verbose, costs off) +select (select p from p limit 1 offset d) from d; +explain (verbose, costs off) +select (select p from p where p = d) from d; +explain (verbose, costs off) +select (select p from p where p = d limit 1 offset d) from d; + +explain (verbose, costs off) +select (select d from d limit 1 offset r) from r; +explain (verbose, costs off) +select (select d from d where d = r) from r; +explain (verbose, costs off) +select (select d from d where d = r limit 1 offset r) from r; + +explain (verbose, costs off) +select (select r from r limit 1 offset d) from d; +explain (verbose, costs off) +select (select r from r where r = d) from d; +explain (verbose, costs off) +select (select r from r where r = d limit 1 offset d) from d; + +explain (verbose, costs off) +select (select p from p limit 1 offset r) from r; +explain (verbose, costs off) +select (select p from p where p = r) from r; +explain (verbose, costs off) +select (select p from p where p = r limit 1 offset r) from r; + +explain (verbose, costs off) +select (select r from r limit 1 offset p) from p; +explain (verbose, costs off) +select (select r from r where r = p) from p; +explain (verbose, costs off) +select (select r from r where r = p limit 1 offset p) from p; + + +create function i(i int) returns setof int language plpgsql immutable as $$ begin return query select i; end $$; +create function s(s int) returns setof int language plpgsql stable as $$ begin return query select s; end $$; +create function v(v int) returns setof int language plpgsql volatile as $$ begin return query select v; end $$; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; +explain (verbose, costs off) +select (select i from i(c)) from c; +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; +explain (verbose, costs off) +select (select s from s(c)) from c; +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; +explain (verbose, costs off) +select (select v from v(c)) from c; +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; +explain (verbose, costs off) +select (select i from i(d)) from d; +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; +explain (verbose, costs off) +select (select s from s(d)) from d; +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; +explain (verbose, costs off) +select (select v from v(d)) from d; +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; +explain (verbose, costs off) +select (select i from i(g)) from g; +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; +explain (verbose, costs off) +select (select s from s(g)) from g; +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; +explain (verbose, costs off) +select (select v from v(g)) from g; +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; +explain (verbose, costs off) +select (select i from i(p)) from p; +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; +explain (verbose, costs off) +select (select s from s(p)) from p; +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; +explain (verbose, costs off) +select (select v from v(p)) from p; +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; +explain (verbose, costs off) +select (select i from i(r)) from r; +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; +explain (verbose, costs off) +select (select s from s(r)) from r; +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; +explain (verbose, costs off) +select (select v from v(r)) from r; +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; + + +alter function i(i int) execute on all segments; +alter function s(s int) execute on all segments; +alter function v(v int) execute on all segments; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; +explain (verbose, costs off) +select (select i from i(c)) from c; +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; +explain (verbose, costs off) +select (select s from s(c)) from c; +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; +explain (verbose, costs off) +select (select v from v(c)) from c; +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; +explain (verbose, costs off) +select (select i from i(d)) from d; +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; +explain (verbose, costs off) +select (select s from s(d)) from d; +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; +explain (verbose, costs off) +select (select v from v(d)) from d; +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; +explain (verbose, costs off) +select (select i from i(g)) from g; +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; +explain (verbose, costs off) +select (select s from s(g)) from g; +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; +explain (verbose, costs off) +select (select v from v(g)) from g; +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; +explain (verbose, costs off) +select (select i from i(p)) from p; +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; +explain (verbose, costs off) +select (select s from s(p)) from p; +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; +explain (verbose, costs off) +select (select v from v(p)) from p; +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; +explain (verbose, costs off) +select (select i from i(r)) from r; +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; +explain (verbose, costs off) +select (select s from s(r)) from r; +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; +explain (verbose, costs off) +select (select v from v(r)) from r; +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; + + +alter function i(i int) execute on master; +alter function s(s int) execute on master; +alter function v(v int) execute on master; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; +explain (verbose, costs off) +select (select i from i(c)) from c; +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; +explain (verbose, costs off) +select (select s from s(c)) from c; +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; +explain (verbose, costs off) +select (select v from v(c)) from c; +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; +explain (verbose, costs off) +select (select i from i(d)) from d; +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; +explain (verbose, costs off) +select (select s from s(d)) from d; +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; +explain (verbose, costs off) +select (select v from v(d)) from d; +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; +explain (verbose, costs off) +select (select i from i(g)) from g; +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; +explain (verbose, costs off) +select (select s from s(g)) from g; +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; +explain (verbose, costs off) +select (select v from v(g)) from g; +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; +explain (verbose, costs off) +select (select i from i(p)) from p; +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; +explain (verbose, costs off) +select (select s from s(p)) from p; +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; +explain (verbose, costs off) +select (select v from v(p)) from p; +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; +explain (verbose, costs off) +select (select i from i(r)) from r; +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; +explain (verbose, costs off) +select (select s from s(r)) from r; +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; +explain (verbose, costs off) +select (select v from v(r)) from r; +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; + + +alter function i(i int) execute on initplan; +alter function s(s int) execute on initplan; +alter function v(v int) execute on initplan; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset c) from c; +explain (verbose, costs off) +select (select i from i(c)) from c; +explain (verbose, costs off) +select (select i from i(c) limit 1 offset c) from c; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset c) from c; +explain (verbose, costs off) +select (select s from s(c)) from c; +explain (verbose, costs off) +select (select s from s(c) limit 1 offset c) from c; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset c) from c; +explain (verbose, costs off) +select (select v from v(c)) from c; +explain (verbose, costs off) +select (select v from v(c) limit 1 offset c) from c; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset d) from d; +explain (verbose, costs off) +select (select i from i(d)) from d; +explain (verbose, costs off) +select (select i from i(d) limit 1 offset d) from d; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset d) from d; +explain (verbose, costs off) +select (select s from s(d)) from d; +explain (verbose, costs off) +select (select s from s(d) limit 1 offset d) from d; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset d) from d; +explain (verbose, costs off) +select (select v from v(d)) from d; +explain (verbose, costs off) +select (select v from v(d) limit 1 offset d) from d; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset g) from g; +explain (verbose, costs off) +select (select i from i(g)) from g; +explain (verbose, costs off) +select (select i from i(g) limit 1 offset g) from g; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset g) from g; +explain (verbose, costs off) +select (select s from s(g)) from g; +explain (verbose, costs off) +select (select s from s(g) limit 1 offset g) from g; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset g) from g; +explain (verbose, costs off) +select (select v from v(g)) from g; +explain (verbose, costs off) +select (select v from v(g) limit 1 offset g) from g; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset p) from p; +explain (verbose, costs off) +select (select i from i(p)) from p; +explain (verbose, costs off) +select (select i from i(p) limit 1 offset p) from p; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset p) from p; +explain (verbose, costs off) +select (select s from s(p)) from p; +explain (verbose, costs off) +select (select s from s(p) limit 1 offset p) from p; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset p) from p; +explain (verbose, costs off) +select (select v from v(p)) from p; +explain (verbose, costs off) +select (select v from v(p) limit 1 offset p) from p; + + +explain (verbose, costs off) +select (select i from i(1) limit 1 offset r) from r; +explain (verbose, costs off) +select (select i from i(r)) from r; +explain (verbose, costs off) +select (select i from i(r) limit 1 offset r) from r; + +explain (verbose, costs off) +select (select s from s(1) limit 1 offset r) from r; +explain (verbose, costs off) +select (select s from s(r)) from r; +explain (verbose, costs off) +select (select s from s(r) limit 1 offset r) from r; + +explain (verbose, costs off) +select (select v from v(1) limit 1 offset r) from r; +explain (verbose, costs off) +select (select v from v(r)) from r; +explain (verbose, costs off) +select (select v from v(r) limit 1 offset r) from r; + + +drop function i(a int); +drop function s(a int); +drop function v(a int); +drop table d; +drop table p; +drop table r; +drop view c; +drop view g; diff --git a/src/test/regress/sql/vacuum_full_ao.sql b/src/test/regress/sql/vacuum_full_ao.sql index e52595a77f1a..205195d3b3ba 100644 --- a/src/test/regress/sql/vacuum_full_ao.sql +++ b/src/test/regress/sql/vacuum_full_ao.sql @@ -22,3 +22,105 @@ select pg_relation_size((select segrelid from pg_appendonly where relid = 'vfao' vacuum full vfao; select pg_relation_size((select segrelid from pg_appendonly where relid = 'vfao'::regclass)) from gp_dist_random('gp_id') where gp_segment_id = 1; + +-- Test that vacuum can process segment files created in an aborted transaction +create table table_ao_col (i int, j int, k int) with (appendonly='true', orientation="column"); + +begin; +insert into table_ao_col select i, i + 1, i + 2 from generate_series(1, 20) i; + +\! psql regression -c 'begin; insert into table_ao_col select i, i + 1, i + 2 from generate_series(1, 20) i; rollback;' + +commit; + +create or replace function getTableSegFiles(t regclass, out gp_contentid smallint, out filepath text) +as 'select current_setting(''gp_contentid'')::smallint, pg_relation_filepath(t)' +language sql +execute on all segments; + +create or replace function cmdCheckSegmentFileSizes(table_name text) returns text as +$$ +declare + cmd text; +begin + select '\! (stat --format=''%s'' ' || string_agg(full_path_relfilenode, ' ') || ' 2>/dev/null || echo 0) | awk ''{sum += $1} END {print sum}''' + into cmd + from + (select d.datadir || '/' || f.filepath || '.*' as full_path_relfilenode from getTableSegFiles(table_name::regclass) f join gp_segment_configuration d + on f.gp_contentid = d.content where d.content <> -1 and d.role = 'p')t; + + return cmd; +end +$$ language plpgsql; + +select cmdCheckSegmentFileSizes('table_ao_col') check_segfiles_size +\gset + +delete from table_ao_col where true; + +vacuum table_ao_col; + +:check_segfiles_size + +drop table table_ao_col; + +-- Test that vacuum can process segment files created for a new column in an aborted transaction (case 1) +create table table_ao_col_1 (i int, j int, k int) with (appendonly='true', orientation="column"); +insert into table_ao_col_1 select i, i + 1, i + 2 from generate_series(1, 20) i; + +begin; +alter table table_ao_col_1 add column a int; +update table_ao_col_1 set a = 1 where true; +rollback; + +select cmdCheckSegmentFileSizes('table_ao_col_1') check_segfiles_size_1 +\gset + +delete from table_ao_col_1 where true; + +vacuum table_ao_col_1; + +:check_segfiles_size_1 + +drop table table_ao_col_1; + +-- Test that vacuum can process segment files created for a new column in an aborted transaction (case 2) +create table table_ao_col_2 (i int, j int, k int) with (appendonly='true', orientation="column"); + +begin; +insert into table_ao_col_2 select i, i + 1, i + 2 from generate_series(1, 20) i; +alter table table_ao_col_2 add column a int; +update table_ao_col_2 set a = 1 where true; +rollback; + +select cmdCheckSegmentFileSizes('table_ao_col_2') check_segfiles_size_2 +\gset + +vacuum table_ao_col_2; + +:check_segfiles_size_2 + +drop table table_ao_col_2; + +-- Test vacuum for a AORO table after adding column in an aborted transaction +create table table_ao_row (i int, j int, k int) with (appendonly='true', orientation="row"); +insert into table_ao_row select i, i + 1, i + 2 from generate_series(1, 20) i; + +begin; +alter table table_ao_row add column a int; +update table_ao_row set a = 1 where true; +rollback; + +select cmdCheckSegmentFileSizes('table_ao_row') check_segfiles_size_aoro +\gset + +delete from table_ao_row where true; + +vacuum table_ao_row; + +:check_segfiles_size_aoro + +drop table table_ao_row; + +drop function cmdCheckSegmentFileSizes(table_name text); +drop function getTableSegFiles(t regclass, out gp_contentid smallint, out filepath text);