LuciferYang opened a new pull request, #59545:
URL: https://github.com/apache/spark/pull/59545

   ### What changes were proposed in this pull request?
   
   `ALTER TABLE ... ADD CONSTRAINT ... CHECK` builds the V2 predicate it stores 
in the catalog from the optimized condition, so a function that the optimizer 
replaces with its current value is stored as its value at the time of the ALTER 
TABLE. This covers `current_timestamp()`, `now()`, `current_date()`, 
`localtimestamp()`, `current_database()`, `current_user()` and casts like 
`CAST('now' AS TIMESTAMP)` or `to_timestamp('now')`. Later writes check the 
stored predicate.
   
   This PR makes `CheckConstraint` keep its analyzed condition, as 
`DefaultValueExpression` and `GeneratedColumnExpression` do 
(`AnalysisAwareExpression`). When the condition reads such a value, the 
predicate is built from the analyzed condition, as CREATE TABLE builds it, so 
each write computes the value itself. For `current_timestamp()` that predicate 
has no V2 form and writes check `predicateSql`, as for the same constraint 
created by CREATE TABLE. Any other condition is built from the optimized 
condition as before.
   
   The analyzed condition is not used for every constraint: a 
`RuntimeReplaceable` such as `nullif` has no V2 form there, and writes would 
have to parse `predicateSql`, which does not resolve a column qualified by the 
table name (`tbl.id`) the way ALTER TABLE does.
   
   ### Why are the changes needed?
   
   ```sql
   CREATE TABLE t (id INT, ts TIMESTAMP);
   ALTER TABLE t ADD CONSTRAINT vt CHECK (ts <= current_timestamp());
   -- the stored predicate is ts <= <the time of the ALTER TABLE>
   INSERT INTO t VALUES (1, current_timestamp());
   -- [CHECK_CONSTRAINT_VIOLATION] CHECK constraint vt ts <= 
current_timestamp() violated ...
   ```
   
   ### Does this PR introduce _any_ user-facing change?
   
   Yes. A CHECK constraint added by ALTER TABLE that reads the current time, 
date, catalog, user and the like is checked against their values at the time of 
each write, as one created by CREATE TABLE is. A constraint added before this 
change keeps the predicate it was stored with.
   
   ### How was this patch tested?
   
   `CheckConstraintSuite`:
   - A constraint `creation_time <= <now>` added by ALTER TABLE, with 
`current_timestamp()`, `CAST('now' AS TIMESTAMP)` and `to_timestamp('now')` as 
`<now>`, accepts a row written with the current time and rejects one written 
with tomorrow. It fails without the change.
   - A constraint `nullif(tbl.id, 3) > 0` added by ALTER TABLE on a table with 
a struct column `tbl` checks the column `id` on later writes, the column ALTER 
TABLE resolved `tbl.id` to. It passes without the change and fails if every 
constraint is built from its analyzed condition.
   
   ### Was this patch authored or co-authored using generative AI tooling?
   
   Generated-by: Claude Opus 5
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to