Repository: risingwavelabs/risingwave (language: python)

Issue:
Sqlsmith: Sql feature generation
As we add more features, these should be tested via sqlsmith as well.

SQL Features:
- [ ] Generate other table functions: `generate_series`, `unnest`. See: https://github.com/singularity-data/risingwave/issues/4540
- [ ] Generate array_agg, jsonb_agg, jsonb_object_agg
- [ ] Generate select from System Tables
- [ ] Generate `NATURAL JOIN`
- [ ] Generate `JOIN` with `USING`
- [ ] Generate query w/o `GROUP BY`
- [ ] Randomly toggle session variables
- [ ] Generate `pow`/`exp`.
- [ ] Generate TopN by group: https://www.risingwave.dev/docs/current/sql-pattern-topn/
- [ ] Generate jsonb exprs, see: https://github.com/risingwavelabs/risingwave/issues/7714
- [ ] #7132
- [x] Generate order-by-clauses with `NULLS { FIRST | LAST }` (will be done in https://github.com/risingwavelabs/risingwave/pull/10864/commits/000cbc11cbc04f20abfd127b1bf4b3fd24e75c44)
- [ ] Generate `max`,`min`,`count` for `timestamptz`
- [ ] Generate `bit_and`, `bit_or` and `big_xor` in batch queries, and `bit_xor` in streaming queries.
- [ ] Generate array range access.
- [ ] https://github.com/risingwavelabs/risingwave/issues/10241
- [ ] Generate window functions other than `row_number`, `rank`.
- [ ] Generate `ALTER` DDL statements.\
- [ ] https://github.com/risingwavelabs/risingwave/issues/10516
- [ ] Generate temporal filter in sqlsmith


Discussion / hints:

Fix patch:
diff --git a/src/connector/src/source/iceberg/mod.rs b/src/connector/src/source/iceberg/mod.rs
index db9029a040d0..aa23425ee830 100644
--- a/src/connector/src/source/iceberg/mod.rs
+++ b/src/connector/src/source/iceberg/mod.rs
@@ -293,15 +293,12 @@ impl IcebergSplitEnumerator {
                 let snapshot = table
                     .metadata()
                     .snapshots()
-                    .map(|snapshot| snapshot.timestamp().map(|ts| ts.timestamp_millis()))
-                    .collect::<Result<Vec<_>, _>>()?
-                    .into_iter()
-                    .filter(|&snapshot_millis| snapshot_millis <= timestamp)
-                    .max_by_key(|&snapshot_millis| snapshot_millis);
+                    .filter(|snapshot| snapshot.timestamp_ms() <= timestamp)
+                    .max_by_key(|snapshot| snapshot.timestamp_ms());
                 match snapshot {
-                    Some(snapshot) => snapshot,
+                    Some(snapshot) => snapshot.snapshot_id(),
                     None => {
-                        // convert unix time to human readable time
+                        // convert unix time to human-readable time
                         let time = chrono::DateTime::from_timestamp_millis(timestamp);
                         if time.is_some() {
                             bail!("Cannot find a snapshot older than {}", time.unwrap());
diff --git a/src/frontend/src/planner/relation.rs b/src/frontend/src/planner/relation.rs
index bc694042df77..18a4cf0b7e5e 100644
--- a/src/frontend/src/planner/relation.rs
+++ b/src/frontend/src/planner/relation.rs
@@ -77,16 +77,6 @@ impl Planner {
 
     pub(super) fn plan_base_table(&mut self, base_table: &BoundBaseTable) -> Result<PlanRef> {
         let as_of = base_table.as_of.clone();
-        match as_of {
-            None
-            | Some(AsOf::ProcessTime)
-            | Some(AsOf::TimestampNum(_))
-            | Some(AsOf::TimestampString(_))
-            | Some(AsOf::ProcessTimeWithInterval(_)) => {}
-            Some(AsOf::VersionNum(_)) | Some(AsOf::VersionString(_)) => {
-                bail_not_implemented!("As Of Version is not supported yet.")
-            }
-        }
         let table_cardinality = base_table.table_catalog.cardinality;
         let scan = LogicalScan::create(
             base_table.table_catalog.name().to_string(),
@@ -102,8 +92,47 @@ impl Planner {
         );
 
         match (base_table.table_catalog.engine, self.plan_for()) {
-            (Engine::Hummock, _) | (Engine::Iceberg, PlanFor::Stream) => Ok(scan.into()),
+            (Engine::Hummock, PlanFor::Stream) | (Engine::Hummock, PlanFor::Batch) => {
+                match as_of {
+                    None
+                    | Some(AsOf::ProcessTime)
+                    | Some(AsOf::TimestampNum(_))
+                    | Some(AsOf::TimestampString(_))
+                    | Some(AsOf::ProcessTimeWithInterval(_)) => {}
+                    Some(AsOf::VersionNum(_)) | Some(AsOf::VersionString(_)) => {
+                        bail_not_implemented!("As Of Version is not supported yet.")
+                    }
+                };
+                Ok(scan.into())
+            }
+            (Engine::Iceberg, PlanFor::Stream) => {
+                match as_of {
+                    None
+                    | Some(AsOf::VersionNum(_))
+                    | Some(AsOf::TimestampString(_))
+                    | Some(AsOf::TimestampNum(_)) => {}
+                    Some(AsOf::ProcessTime) | Some(AsOf::ProcessTimeWithInterval(_)) => {
+                        bail_not_implemented!("As Of ProcessTime() is not supported yet.")
+                    }
+                    Some(AsOf::VersionString(_)) => {
+                        bail_not_implemented!("As Of Version is not supported yet.")
+                    }
+                }
+                Ok(scan.into())
+            }
             (Engine::Iceberg, PlanFor::Batch) => {
+                match as_of {
+                    None
+                    | Some(AsOf::VersionNum(_))
+                    | Some(AsOf::TimestampString(_))
+                    | Some(AsOf::TimestampNum(_)) => {}
+                    Some(AsOf::ProcessTime) | Some(AsOf::ProcessTimeWithInterval(_)) => {
+                        bail_not_implemented!("As Of ProcessTime() is not supported yet.")
+                    }
+                    Some(AsOf::VersionString(_)) => {
+                        bail_not_implemented!("As Of Version is not supported yet.")
+                    }
+                }
                 let opt_ctx = self.ctx();
                 let session = opt_ctx.session_ctx();
                 let db_name = session.database();


Test patch:
diff --git a/e2e_test/iceberg/test_case/iceberg_engine.slt b/e2e_test/iceberg/test_case/iceberg_engine.slt
index 0a97e4f224e8..55b23c6399ad 100644
--- a/e2e_test/iceberg/test_case/iceberg_engine.slt
+++ b/e2e_test/iceberg/test_case/iceberg_engine.slt
@@ -15,6 +15,11 @@ select * from t;
 ----
 1 xxx
 
+query ??
+select * from t for system_time as of '2222-12-10 11:48:06';
+----
+1 xxx
+
 statement ok
 DROP TABLE t;