Merge branch 'main' into no-whitespace-parser

This commit is contained in:
Luca Cappelletti 2025-12-04 12:22:21 +01:00 committed by GitHub
commit 7e0d3a9362
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
16 changed files with 374 additions and 24 deletions

View file

@ -23,7 +23,9 @@
mod test_utils;
use helpers::attached_token::AttachedToken;
use sqlparser::ast::{DataType, DropBehavior, DropOperator, DropOperatorSignature};
use sqlparser::ast::{
DataType, DropBehavior, DropOperator, DropOperatorClass, DropOperatorSignature,
};
use sqlparser::tokenizer::Span;
use test_utils::*;
@ -6930,6 +6932,14 @@ fn parse_drop_operator() {
drop_behavior: Some(DropBehavior::Cascade),
})
);
// Test error: DROP OPERATOR with no operators
let sql = "DROP OPERATOR (INTEGER, INTEGER)";
assert!(pg().parse_sql_statements(sql).is_err());
// Test error: DROP OPERATOR IF EXISTS with no operators
let sql = "DROP OPERATOR IF EXISTS (INTEGER, INTEGER)";
assert!(pg().parse_sql_statements(sql).is_err());
}
#[test]
@ -6985,13 +6995,84 @@ fn parse_drop_operator_family() {
}
}
}
// Test error: DROP OPERATOR FAMILY with no names
let sql = "DROP OPERATOR FAMILY USING btree";
assert!(pg_and_generic().parse_sql_statements(sql).is_err());
// Test error: DROP OPERATOR FAMILY IF EXISTS with no names
let sql = "DROP OPERATOR FAMILY IF EXISTS USING btree";
assert!(pg_and_generic().parse_sql_statements(sql).is_err());
}
#[test]
fn parse_drop_operator_class() {
for if_exists in [true, false] {
for drop_behavior in [
None,
Some(DropBehavior::Cascade),
Some(DropBehavior::Restrict),
] {
for index_method in &["btree", "hash", "gist", "gin", "spgist", "brin"] {
for (names_str, names_vec) in [
(
"widget_ops",
vec![ObjectName::from(vec![Ident::new("widget_ops")])],
),
(
"myschema.int4_ops",
vec![ObjectName::from(vec![
Ident::new("myschema"),
Ident::new("int4_ops"),
])],
),
(
"ops1, ops2, schema.ops3",
vec![
ObjectName::from(vec![Ident::new("ops1")]),
ObjectName::from(vec![Ident::new("ops2")]),
ObjectName::from(vec![Ident::new("schema"), Ident::new("ops3")]),
],
),
] {
let sql = format!(
"DROP OPERATOR CLASS{} {} USING {}{}",
if if_exists { " IF EXISTS" } else { "" },
names_str,
index_method,
match drop_behavior {
Some(behavior) => format!(" {}", behavior),
None => String::new(),
}
);
assert_eq!(
pg_and_generic().verified_stmt(&sql),
Statement::DropOperatorClass(DropOperatorClass {
if_exists,
names: names_vec.clone(),
using: Ident::new(*index_method),
drop_behavior,
})
);
}
}
}
}
// Test error: DROP OPERATOR CLASS with no names
let sql = "DROP OPERATOR CLASS USING btree";
assert!(pg_and_generic().parse_sql_statements(sql).is_err());
// Test error: DROP OPERATOR CLASS IF EXISTS with no names
let sql = "DROP OPERATOR CLASS IF EXISTS USING btree";
assert!(pg_and_generic().parse_sql_statements(sql).is_err());
}
#[test]
fn parse_create_operator_family() {
for index_method in &["btree", "hash", "gist", "gin", "spgist", "brin"] {
assert_eq!(
pg().verified_stmt(&format!(
pg_and_generic().verified_stmt(&format!(
"CREATE OPERATOR FAMILY my_family USING {index_method}"
)),
Statement::CreateOperatorFamily(CreateOperatorFamily {
@ -7000,7 +7081,7 @@ fn parse_create_operator_family() {
})
);
assert_eq!(
pg().verified_stmt(&format!(
pg_and_generic().verified_stmt(&format!(
"CREATE OPERATOR FAMILY myschema.test_family USING {index_method}"
)),
Statement::CreateOperatorFamily(CreateOperatorFamily {
@ -7026,7 +7107,7 @@ fn parse_create_operator_class() {
let sql = format!(
"CREATE OPERATOR CLASS {class_name} {default_clause}FOR TYPE INT4 USING btree{family_clause} AS OPERATOR 1 <"
);
match pg().verified_stmt(&sql) {
match pg_and_generic().verified_stmt(&sql) {
Statement::CreateOperatorClass(CreateOperatorClass {
name,
default,
@ -7056,7 +7137,7 @@ fn parse_create_operator_class() {
}
// Test comprehensive operator class with all fields
match pg().verified_stmt("CREATE OPERATOR CLASS CAS_btree_ops DEFAULT FOR TYPE CAS USING btree FAMILY CAS_btree_ops AS OPERATOR 1 <, OPERATOR 2 <=, OPERATOR 3 =, OPERATOR 4 >=, OPERATOR 5 >, FUNCTION 1 cas_cmp(CAS, CAS)") {
match pg_and_generic().verified_stmt("CREATE OPERATOR CLASS CAS_btree_ops DEFAULT FOR TYPE CAS USING btree FAMILY CAS_btree_ops AS OPERATOR 1 <, OPERATOR 2 <=, OPERATOR 3 =, OPERATOR 4 >=, OPERATOR 5 >, FUNCTION 1 cas_cmp(CAS, CAS)") {
Statement::CreateOperatorClass(CreateOperatorClass {
name,
default: true,
@ -7075,7 +7156,7 @@ fn parse_create_operator_class() {
}
// Test operator with argument types
match pg().verified_stmt(
match pg_and_generic().verified_stmt(
"CREATE OPERATOR CLASS test_ops FOR TYPE INT4 USING gist AS OPERATOR 1 < (INT4, INT4)",
) {
Statement::CreateOperatorClass(CreateOperatorClass { ref items, .. }) => {
@ -7100,7 +7181,7 @@ fn parse_create_operator_class() {
}
// Test operator FOR SEARCH
match pg().verified_stmt(
match pg_and_generic().verified_stmt(
"CREATE OPERATOR CLASS test_ops FOR TYPE INT4 USING gist AS OPERATOR 1 < FOR SEARCH",
) {
Statement::CreateOperatorClass(CreateOperatorClass { ref items, .. }) => {
@ -7144,7 +7225,7 @@ fn parse_create_operator_class() {
}
// Test function with operator class arg types
match pg().verified_stmt("CREATE OPERATOR CLASS test_ops FOR TYPE INT4 USING btree AS FUNCTION 1 (INT4, INT4) btcmp(INT4, INT4)") {
match pg_and_generic().verified_stmt("CREATE OPERATOR CLASS test_ops FOR TYPE INT4 USING btree AS FUNCTION 1 (INT4, INT4) btcmp(INT4, INT4)") {
Statement::CreateOperatorClass(CreateOperatorClass {
ref items,
..
@ -7167,11 +7248,11 @@ fn parse_create_operator_class() {
}
// Test function with no arguments (empty parentheses normalizes to no parentheses)
pg().one_statement_parses_to(
pg_and_generic().one_statement_parses_to(
"CREATE OPERATOR CLASS test_ops FOR TYPE INT4 USING btree AS FUNCTION 1 my_func()",
"CREATE OPERATOR CLASS test_ops FOR TYPE INT4 USING btree AS FUNCTION 1 my_func",
);
match pg().verified_stmt(
match pg_and_generic().verified_stmt(
"CREATE OPERATOR CLASS test_ops FOR TYPE INT4 USING btree AS FUNCTION 1 my_func",
) {
Statement::CreateOperatorClass(CreateOperatorClass { ref items, .. }) => {
@ -7196,7 +7277,7 @@ fn parse_create_operator_class() {
}
// Test multiple items including STORAGE
match pg().verified_stmt("CREATE OPERATOR CLASS gist_ops FOR TYPE geometry USING gist AS OPERATOR 1 <<, FUNCTION 1 gist_consistent(internal, geometry, INT4), STORAGE box") {
match pg_and_generic().verified_stmt("CREATE OPERATOR CLASS gist_ops FOR TYPE geometry USING gist AS OPERATOR 1 <<, FUNCTION 1 gist_consistent(internal, geometry, INT4), STORAGE box") {
Statement::CreateOperatorClass(CreateOperatorClass {
ref items,
..