chore(toolchain): switch to stable Rust 1.96.1 and remove all nightly feature gates (#9303)

* chore(toolchain): switch to stable Rust 1.96.1 and remove all nightly feature gates

Move the workspace from the pinned nightly-2026-03-21 to stable
1.96.1 and drop all 23 '#![feature]' gates across 13 crates,
rewriting the still-unstable API usages with stable equivalents:

- try_blocks: closures / an async block (table, query, common-function, servers)
- duration_constructors: Duration::from_secs(n * 86400) / (n * 60)
- iterator_try_collect: collect::<Result<Vec<_>, _>>()
- box_patterns: as_deref() + matches! chains (sql)
- error_iter: error_chain_root() source-chain walker (common-error);
  sources() includes the error itself, so the walker never panics
- int_roundings: div_floor -> div_euclid (equal for positive divisors)
- iter_partition_in_place: stable sort_by_key partition helper (index)
- hash_set_entry: HashSet::insert bool / contains+insert
- trait_alias: lifetime-parameterized dyn FnOnce type aliases (puffin)
- string_from_utf8_lossy_owned: from_utf8_lossy(&v).into_owned()
- never_type: Infallible (common-recordbatch)
- debug_closure_helpers: closure-backed DebugFmt newtype (mito2)
- binary_heap_pop_if: peek().is_some_and() + pop()
- exclusive_wrapper: drop Exclusive; C: Send + Unpin already in bounds
- stmt_expr_attributes: stale gate, no usages

Also fix release-dev-builder-images.yaml, which parsed
rust-toolchain.toml with a date-only regex and would produce empty
image versions with a stable channel; it now extracts the full
channel token. Dev-builder images verified against stable 1.96.1
(image build, default-toolchain behavior, binstall/nextest, riscv64
and android targets, in-image cargo check).

Validated on 1.96.1: cargo check --workspace --all-targets, clippy
--workspace --all-targets --all-features -D warnings, cargo fmt
--check, and nextest on all 13 affected crates (4586 passed).

Part of #9289. Depends on #9298 (fuzz nightly quarantine) merging
first.

Signed-off-by: Ning Sun <sunning@greptime.com>

* chore: update flake checksum

* chore: use wild for linker in flake

---------

Signed-off-by: Ning Sun <sunning@greptime.com>
This commit is contained in:
Ning Sun
2026-09-24 08:37:43 +00:00
committed by GitHub
parent abedeb2bea
commit 20619273ee
50 changed files with 209 additions and 196 deletions
-2
View File
@@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and
// limitations under the License.
#![feature(box_patterns)]
pub mod ast;
pub mod dialect;
pub mod error;
+49 -46
View File
@@ -14,7 +14,7 @@
use serde::Serialize;
use sqlparser::ast::{
Insert as SpInsert, ObjectName, ObjectNamePart, Parens, Query, SetExpr, Statement, TableObject,
Insert as SpInsert, ObjectName, ObjectNamePart, Parens, SetExpr, Statement, TableObject,
UnaryOperator, ValueWithSpan, Values,
};
use sqlparser::parser::ParserError;
@@ -70,14 +70,18 @@ impl Insert {
/// Extracts the literal insert statement body if possible
pub fn values_body(&self) -> Result<Vec<Vec<Value>>> {
match &self.inner {
Statement::Insert(SpInsert {
source:
Some(box Query {
body: box SetExpr::Values(Values { rows, .. }),
..
}),
..
}) => sql_exprs_to_values(rows),
Statement::Insert(SpInsert { source, .. }) => {
let rows = source
.as_deref()
.and_then(|query| match query.body.as_ref() {
SetExpr::Values(Values { rows, .. }) => Some(rows),
_ => None,
});
match rows {
Some(rows) => sql_exprs_to_values(rows),
None => unreachable!(),
}
}
_ => unreachable!(),
}
}
@@ -86,36 +90,37 @@ impl Insert {
/// The rules is the same as function `values_body()`.
pub fn can_extract_values(&self) -> bool {
match &self.inner {
Statement::Insert(SpInsert {
source:
Some(box Query {
body: box SetExpr::Values(Values { rows, .. }),
..
}),
..
}) => rows.iter().all(|es| {
es.iter().all(|expr| match expr {
Expr::Value(_) => true,
Expr::Identifier(ident) => {
if ident.quote_style.is_none() {
ident.value.to_lowercase() == "default"
} else {
ident.quote_style == Some('"')
}
}
Expr::UnaryOp { op, expr } => {
matches!(op, UnaryOperator::Minus | UnaryOperator::Plus)
&& matches!(
&**expr,
Expr::Value(ValueWithSpan {
value: Value::Number(_, _),
..
})
)
}
_ => false,
Statement::Insert(SpInsert { source, .. }) => source
.as_deref()
.and_then(|query| match query.body.as_ref() {
SetExpr::Values(Values { rows, .. }) => Some(rows),
_ => None,
})
}),
.is_some_and(|rows| {
rows.iter().all(|es| {
es.iter().all(|expr| match expr {
Expr::Value(_) => true,
Expr::Identifier(ident) => {
if ident.quote_style.is_none() {
ident.value.to_lowercase() == "default"
} else {
ident.quote_style == Some('"')
}
}
Expr::UnaryOp { op, expr } => {
matches!(op, UnaryOperator::Minus | UnaryOperator::Plus)
&& matches!(
&**expr,
Expr::Value(ValueWithSpan {
value: Value::Number(_, _),
..
})
)
}
_ => false,
})
})
}),
_ => false,
}
}
@@ -124,7 +129,7 @@ impl Insert {
pub fn has_non_values_query_source(&self) -> bool {
match &self.inner {
Statement::Insert(SpInsert {
source: Some(box query),
source: Some(query),
..
}) => !matches!(&*query.body, SetExpr::Values(_)),
_ => false,
@@ -134,9 +139,9 @@ impl Insert {
pub fn query_body(&self) -> Result<Option<GtQuery>> {
Ok(match &self.inner {
Statement::Insert(SpInsert {
source: Some(box query),
source: Some(query),
..
}) => Some(query.clone().try_into()?),
}) => Some(query.as_ref().clone().try_into()?),
_ => None,
})
}
@@ -383,11 +388,9 @@ mod tests {
let q = insert.query_body().unwrap().unwrap();
assert!(insert.has_non_values_query_source());
assert!(matches!(
q.inner,
Query {
body: box SetExpr::Select { .. },
..
}
&q.inner,
sqlparser::ast::Query { body, .. }
if matches!(body.as_ref(), SetExpr::Select { .. })
));
}
_ => unreachable!(),