Conversation
Apache Cloudberry is a PostgreSQL-derived MPP database, so the provider extends PostgresProvider and reuses PostgreSQL's expression generators and oracles. Cloudberry is a transparent MPP system: a single connection to the coordinator is enough, so there is no worker-node registration and no extension to create. createDatabase is inherited, wrapped only in a retry for an intermittent MPP-specific failure (see the comment on the override). The Cloudberry-specific parts are the distribution policy, assigned per table via ALTER TABLE ... SET DISTRIBUTED with a distribution key chosen to be a subset of any PRIMARY KEY or UNIQUE constraint, and leaf partitions for the declaratively partitioned tables the inherited generator emits. Storage formats (heap, ao_row, ao_column, pax) are exercised through the inherited USING clause. CloudberryCommon collects the errors Cloudberry returns for statements that are valid in PostgreSQL but violate an MPP restriction. CloudberryBugs follows the TiDBBugs pattern, gating each work-around for an unfixed target-DB bug behind a flag so it is easy to find and remove once the bug is fixed; each flag's comment records the scope that was actually verified against a live cluster. Two inherited actions are not generated. CREATE STATISTICS can crash the coordinator, which a whitelisted error message cannot handle. CREATE VIEW builds its body with PostgresRandomQueryGenerator, which readily emits DISTINCT ON or LIMIT with no matching ORDER BY; such a view is re-evaluated per reference, and on an MPP cluster the row it yields can legitimately differ between evaluations, which breaks every oracle that compares two evaluations of the same data. This PR covers database generation plus the three oracles that need no Cloudberry-specific oracle implementation: NoREC, TLPWhere and the fuzzer. The remaining oracles, and a CI job, follow in separate PRs. Verified against a 3-segment cluster built from Cloudberry main (3.0.0-devel): mvn verify -DskipTests=true is clean, and NoREC, TLPWhere and the fuzzer each ran 4 threads x 140-200s across seeds 0-10 with no thread deaths and no oracle reports.
|
@roseduan, thanks a lot for the PR. This looks great! I'm currently on vacation until September 27. I'll try to take a look asap. |
OK thanks a lot, I will give the continuous support if you have any comments about this issue. |
mrigger
left a comment
There was a problem hiding this comment.
Thanks a lot for the PR! This looks great! Sorry also that it took so long to review it. I first did not see the PR, was on a short vacation, and then catching up on other work. I have some minor nitpicks that I added as comments; it's up to you which ones you want to address.
What would be great, though, is if you could update the GitHub actions workflow to also execute Cloudberry's tests in the CI. This makes sure that we won't break anything (e.g., during a refactoring).
| } | ||
|
|
||
| private static boolean isHashDistributable(String dataType) { | ||
| // Types without a default hash operator class cannot be a Cloudberry distribution key. |
There was a problem hiding this comment.
I guess it's fine, but it would be more future-proof to encode this in an enum and make it fail when encountering an unknown (potentially new) data type.
| package sqlancer.cloudberry; | ||
|
|
||
| // do not make the fields final to avoid warnings | ||
| public final class CloudberryBugs { |
There was a problem hiding this comment.
For these, would it be possible to add a URL? This would make it easy for others or coding agents to disable them after the issue has been addressed.
| // because the partitions would be left carrying a constraint their parent no longer has. | ||
| errors.add("cannot remove constraint from only the partitioned table when partitions exist"); | ||
|
|
||
| // See CloudberryBugs for details on each of these known, still-open target-DB bugs. Each is gated behind |
There was a problem hiding this comment.
I guess some of these AI-generated comments could be removed, but I'm also fine with leaving them in.
| errors.add("could not devise a query plan"); | ||
| // Live wording is "could not devise a plan (cdbpath.c:...)" -- no "query" -- so the entry above never | ||
| // actually matches; keep both since it's unclear which build/error-path produces which variant. | ||
| errors.add("could not devise a plan"); |
There was a problem hiding this comment.
Could the "could not devise a plan" hint towards a bug?
| private CloudberryCommon() { | ||
| } | ||
|
|
||
| public static List<String> getCloudberryErrors() { |
There was a problem hiding this comment.
Advice for future changes: I think it would be nice to make the expected errors more fine-grained and to have separate instantiations for specific statements (e.g., DDL statements), expressions, etc., so that only those expected errors that can actually occur are added for a given SQL statement.
Apache Cloudberry is a PostgreSQL-derived MPP database, so the provider extends PostgresProvider and reuses PostgreSQL's expression generators and oracles. Cloudberry is a transparent MPP system: a single connection to the coordinator is enough, so there is no worker-node registration and no extension to create. createDatabase is inherited, wrapped only in a retry for an intermittent MPP-specific failure (see the comment on the override).
The Cloudberry-specific parts are the distribution policy, assigned per table via ALTER TABLE ... SET DISTRIBUTED with a distribution key chosen to be a subset of any PRIMARY KEY or UNIQUE constraint, and leaf partitions for the declaratively partitioned tables the inherited generator emits. Storage formats (heap, ao_row, ao_column, pax) are exercised through the inherited USING clause.
CloudberryCommon collects the errors Cloudberry returns for statements that are valid in PostgreSQL but violate an MPP restriction. CloudberryBugs follows the TiDBBugs pattern, gating each work-around for an unfixed target-DB bug behind a flag so it is easy to find and remove once the bug is fixed; each flag's comment records the scope that was actually verified against a live cluster.
Two inherited actions are not generated. CREATE STATISTICS can crash the coordinator, which a whitelisted error message cannot handle. CREATE VIEW builds its body with PostgresRandomQueryGenerator, which readily emits DISTINCT ON or LIMIT with no matching ORDER BY; such a view is re-evaluated per reference, and on an MPP cluster the row it yields can legitimately differ between evaluations, which breaks every oracle that compares two evaluations of the same data.
This PR covers database generation plus the three oracles that need no Cloudberry-specific oracle implementation: NoREC, TLPWhere and the fuzzer. The remaining oracles, and a CI job, follow in separate PRs.
Verified against a 3-segment cluster built from Cloudberry main (3.0.0-devel): mvn verify -DskipTests=true is clean, and NoREC, TLPWhere and the fuzzer each ran 4 threads x 140-200s across seeds 0-10 with no thread deaths and no oracle reports.