Skip to content

Fixed Issue #3332 - #3354

Merged
Hydrocharged merged 1 commit into
mainfrom
daylon/more-fixes-8
Sep 16, 2026
Merged

Hydrocharged merged 1 commit into
mainfrom
daylon/more-fixes-8

Conversation

@Hydrocharged

@Hydrocharged Hydrocharged commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Named NOT NULL, DEFAULT, and UNIQUE column constraints are now accepted.

@Hydrocharged Hydrocharged mentioned this pull request Sep 11, 2026
@Hydrocharged
Hydrocharged added this pull request to stack #3358 September 11, 2026 23:07
@Hydrocharged
Hydrocharged requested a review from zachmu September 11, 2026 23:09
@itoqa

itoqa Bot commented Sep 11, 2026

Copy link
Copy Markdown

Ito QA test results
Commit: aa15105: 14 test cases ran, 14 passed ✅.

Summary

Coverage spans database schema changes and data integrity behavior, including creating and altering tables, named and unnamed uniqueness, primary keys, null handling, defaults, foreign-key checks, and rollback or retry scenarios. It includes normal workflows plus boundary and adversarial cases such as duplicate values, missing references, invalid defaults, failed changes, and concurrent retries, with healthy results throughout.

Safe to merge — the run found no regressions, new failures, or previously flagged failures attributable to this PR, and all exercised integrity and recovery behaviors passed. Any evidence limitations are not merge blockers.

Tests run by Ito

View full run

Result Severity Type Description
General Named and unnamed unique columns received the expected index names, while the primary key created only one index. Repeated values were rejected for every declaration.
General Named unique constraints remained present after table creation and column addition. The required column rejected NULL, while columns that allow NULL accepted it and kept the expected metadata.
General The database applied literal and function defaults during table creation and column addition, rejected an invalid default without leaving a table behind, and kept all named indexes.
General The named index was attached to the constrained column, duplicate constrained values were rejected, and duplicate unrelated values were accepted.
General A named unique column created in either way produced the right index on code, and duplicate values were rejected in both tables.
General A conflicting table change failed without leaving a partial column or index. A corrected retry created the column and one named unique index that enforced duplicate checks.
General Both table creation paths kept the primary key required while allowing multiple blank code values and rejecting repeated code values.
General Retrying the column change reported that the column already existed, and the named unique rule stayed active. A valid row was accepted and a duplicate value was rejected.
Constraint Creating the table and adding the column both worked. Defaults, named indexes, unique values, and required values behaved as expected.
Constraint Adding the column created the expected named index, and the database rejected a duplicate account code.
Constraint The table was created with a generated unique index name, and inserting the same code twice was rejected.
Constraint Creating a table with several named column rules worked. The default was applied, NULL was allowed where expected, and invalid required or duplicate values were rejected.
Default A valid child row received its default quantity, while invalid foreign keys, missing required values, and failed checks were rejected.
Foreign Adding a reference column to an existing table kept the named relationship active. A valid parent key was accepted, and a missing parent key was rejected.

Tip

Reply with @itoqa to send us feedback on this test run.

@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor
Main PR
Total 42090 42090
Successful 19860 19869
Failures 22230 22221
Partial Successes1 5440 5438
Main PR
Successful 47.1846% 47.2060%
Failures 52.8154% 52.7940%

${\color{lightgreen}Progressions (11)}$

alter_table

QUERY: /* End test case for bug #16242 */
/* Test case for bug #17409 */
create table attbl (p1 int constraint pk_attbl primary key);
QUERY: create table atref (c1 int references attbl(p1));
QUERY: drop table attbl, atref;
QUERY: create table attbl (p1 int constraint pk_attbl primary key);
QUERY: create table atref (c1 int references attbl(p1));
QUERY: drop table attbl, atref;

functional_deps

QUERY: CREATE TEMP TABLE articles (
    id int CONSTRAINT articles_pkey PRIMARY KEY,
    keywords text,
    title text UNIQUE NOT NULL,
    body text UNIQUE,
    created date
);
QUERY: SELECT id, keywords, title, body, created
FROM articles
GROUP BY id;
QUERY: SELECT a.id, a.keywords, a.title, a.body, a.created
FROM articles AS a JOIN articles_in_category AS aic ON a.id = aic.article_id
WHERE aic.category_id in (14,62,70,53,138)
GROUP BY a.id;
QUERY: SELECT aic.changed
FROM articles AS a JOIN articles_in_category AS aic ON a.id = aic.article_id
WHERE aic.category_id in (14,62,70,53,138)
GROUP BY aic.category_id, aic.article_id;

subselect

QUERY: select count(*) from tenk1 t
where (exists(select 1 from tenk1 k where k.unique1 = t.unique2) or ten < 0);

Footnotes

  1. These are tests that we're marking as Successful, however they do not match the expected output in some way. This is due to small differences, such as different wording on the error messages, or the column names being incorrect while the data itself is correct.

@coffeegoddd

coffeegoddd commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

@Hydrocharged DOLT

read_tests from_latency to_latency percent_change
covering_index_scan_postgres 2.43 2.43 0.0
groupby_scan_postgres 78.6 77.19 -1.79
index_join_postgres 2.26 2.26 0.0
index_join_scan_postgres 1.61 1.61 0.0
index_scan_postgres 467.3 458.96 -1.78
oltp_point_select 0.37 0.37 0.0
oltp_read_only 6.43 6.43 0.0
select_random_points 0.73 0.73 0.0
select_random_ranges 1.04 1.04 0.0
table_scan_postgres 467.3 458.96 -1.78
types_table_scan_postgres 1170.65 1170.65 0.0
write_tests from_latency to_latency percent_change
oltp_delete_insert_postgres 6.67 6.67 0.0
oltp_insert 3.36 3.36 0.0
oltp_read_write 13.46 13.46 0.0
oltp_update_index 3.62 3.62 0.0
oltp_update_non_index 3.3 3.3 0.0
oltp_write_only 7.04 7.04 0.0
types_delete_insert_postgres 7.17 7.17 0.0

@zachmu zachmu left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change is good, see comments

Comment thread testing/go/issues_test.go Outdated
Comment thread testing/go/issues_test.go Outdated
@itoqa

itoqa Bot commented Sep 16, 2026

Copy link
Copy Markdown

Ito QA test results

History reset (rebase or force-push detected). Starting test narrative over.

Commit: aea183c: 14 test cases ran, 1 failed ❌, 12 passed ✅, 1 additional finding ⚠️.

Summary

The run broadly exercises database schema changes, defaults, generated values, constraint metadata, and uniqueness enforcement across normal flows, boundary names, retries, concurrent operations, and duplicate-write cases. Most behavior is healthy, but the coverage exposes a serious integrity gap in one altered schema-change path.

Not safe to merge yet — this PR can create columns marked UNIQUE while still allowing duplicate values, making it a high-severity data-integrity issue with no practical application-level workaround. A separate pre-existing limitation prevents catalog readers from retrieving named default expressions and should be tracked as a caveat rather than a merge driver.

Tests run by Ito

View full run

Result Severity Type Description
High severity General The three columns were added and their names appeared in the database catalogs, but inserting a second row with the same value succeeded for each column. The unnamed column accepted a duplicate u1, the quoted mixed-case column accepted a duplicate m1, and the defaulted reserved-looking column accepted a duplicate edge-default.
General Unnamed, mixed-case, and punctuation-containing unique names were stored correctly, and duplicate values were rejected in every table.
General A conflicting index name failed without leaving the new column behind. Retrying with a new name created a usable column, and duplicate values were rejected.
General A failed column change left the table unchanged. Retrying with a new constraint name added the column and rejected duplicate values as expected.
General Both tables were created successfully with the same unique name. Each table kept its own index and constraint, and duplicate values were rejected separately.
General Two clients added the same named column without leaving duplicate or partial schema state. The column had the expected default and required value, and duplicate values were rejected.
Column The new column was added successfully, used 9 when its value was omitted, and appeared with the requested unique name in both catalogs.
Column The first row with code 42 was accepted, and the second row with the same code was rejected.
Columns The table was created and changed successfully. The timestamp and text defaults appeared, and the nullable note kept its NULL value.
Columns The generated column was created successfully, and the total for 2 plus 3 was returned as 5.
Constraint The table was created successfully. The omitted value became 7, an explicit NULL was accepted, and the named unique index and constraint appeared in the catalog.
Unique The table kept its named unique and primary key metadata. Duplicate code values and a missing primary key value were rejected.
Unique A table with a non-primary unique column accepted two rows with NULL in that column, as expected.
⚠️ Medium severity Rev The database records that the named column has a default, but catalog queries return an empty value instead of DEFAULT 9.
Additional Findings Details

These findings are unrelated to the current changes but were observed during testing.

🟡 Named defaults lose their catalog value
  • Severity: Medium Medium severity
  • Description: The database records that the named column has a default, but catalog queries return an empty value instead of DEFAULT 9.
  • Impact: Database tools that inspect a named column default may see that a default exists but cannot read its value. This can break schema inspection or migration workflows, although the stored default is still recorded.
  • Steps to Reproduce:
    1. Create a table with a column defined as integer CONSTRAINT named_default DEFAULT 9.
    2. Query pg_attribute and confirm that the column is marked as having a default.
    3. Query pg_attrdef and evaluate adbin with pg_get_expr for that column.
    4. Compare the returned expression with PostgreSQL, where the expression is 9.
  • Stub / mock content: No stubs, mocks, or bypasses were applied for this test in the recorded run.
  • Code Analysis: The runtime result matches an explicit production-code gap. In server/tables/pgcatalog/pg_attribute.go:120-132, atthasdef is set from col.Default != nil, so the column is reported as having a default. In server/tables/pgcatalog/pg_attrdef.go:103-118, pgAttrdefRowIter.Next always returns nil for adbin and documents that adbin is not implemented. In server/functions/pg_get_expr.go:32-40 and :44-52, both pg_get_expr overloads return an error because pg_node_tree support is not implemented. Consequently, a real DEFAULT 9 can produce atthasdef=true while pg_attrdef/pg_get_expr cannot expose its expression. The smallest practical fix is to preserve the parsed default expression in the catalog's column-default data and serialize it into adbin in the form expected by pg_get_expr, then implement the narrow pg_get_expr path for column defaults. The PR diff does not change any of these files; its server changes only remove the named-constraint rejection in server/ast/column_table_def.go and pass names to unique indexes in server/ast/table_def.go and server/ast/alter_table.go.
Evidence Package

Tip

Reply with @itoqa to send us feedback on this test run.

@Hydrocharged
Hydrocharged removed this pull request from stack #3358 September 16, 2026 07:22
@Hydrocharged
Hydrocharged changed the base branch from daylon/more-fixes-7 to main September 16, 2026 07:24
@itoqa

itoqa Bot commented Sep 16, 2026

Copy link
Copy Markdown

Ito QA test results

History reset (rebase or force-push detected). Starting test narrative over.

Commit: 824b2f9: 14 test cases ran, 14 passed ✅.

Summary

Coverage spans database schema changes and everyday data behavior, including required, optional, defaulted, and unique fields; naming and case handling; duplicate and invalid-value rejection; rollback and retry after failed changes; immediate enforcement after alterations; and concurrent table creation. Overall, both normal flows and boundary or adversarial cases behaved correctly.

Safe to merge — the run found no failures or regressions attributable to this PR, and all exercised schema, constraint, rollback, retry, and concurrency behaviors passed. No merge blocker is indicated.

Tests run by Ito

View full run

Result Severity Type Description
General The primary-key column is required, the ordinary unique column keeps its named index, and duplicate values are rejected for both columns.
General Unnamed and mixed-case unique definitions received usable catalog names and rejected duplicate values. Reusing one name caused the table creation to fail without leaving a table behind.
General The invalid default was rejected without adding a partial column. A valid retry added the column and filled its omitted value with 11.
General A conflicting index name caused the column change to fail without leaving a column or catalog row behind. Retrying with a new name created the named unique metadata and rejected duplicate values.
General The quoted unique name appeared the same way in the index and constraint catalogs, and the database rejected a duplicate value.
General The default value was filled in, the nullable field kept NULL, and an invalid NULL value was rejected for the required field.
General The new column used its default value right away, rejected an explicit NULL, and stored no invalid row.
General The first value was saved, the duplicate was rejected, and both catalog views showed the same named unique constraint.
General Two concurrent table creations completed successfully. Both tables kept the shared constraint name in their catalogs, and duplicate values were rejected in both tables.
Constraint The table was created, the row was stored, the omitted value became 5, and the nullable value stayed NULL.
Constraint The new column was added successfully, and a row that omitted it received the value 7.
Existing The table was created and altered successfully. The inserted row kept the integer and text columns usable, used 9 as the default, and stored NULL in both nullable columns.
Unique The named unique entry u_uni appears in both catalog views. The first email is accepted and a duplicate email is rejected.
Unique Adding the named unique column succeeded, its name appeared in the database metadata, and duplicate values were rejected.

Tip

Reply with @itoqa to send us feedback on this test run.

@Hydrocharged
Hydrocharged merged commit 1a7a80a into main Sep 16, 2026
25 checks passed
@Hydrocharged
Hydrocharged deleted the daylon/more-fixes-8 branch September 16, 2026 10:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants