[postgres] Add support for custom binary operators (#548)

* [postgres] Add support for custom binary operators

More details about operators in general are at:
https://www.postgresql.org/docs/current/sql-createoperator.html. This
patch attempts to parse `SELECT` queries that reference an operator
using `OPERATOR(<optional_schema>.<operator_name>)` syntax.

This is a PostgreSQL extension. There are no provisions for user-defined operators in the SQL standard.

* fix code-review comments and ci failures

* Allow custom operator in generic dialects too

* Parse `OPERATOR` as Vec<String>

* fix: std

Co-authored-by: Andrew Lamb <andrew@nerdnetworks.org>
This commit is contained in:
Kaushik Iska 2022-08-05 10:53:58 -07:00 committed by GitHub
parent 6c98228e71
commit 1c64129f76
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 114 additions and 32 deletions

View file

@ -1565,3 +1565,55 @@ fn parse_fetch() {
pg_and_generic()
.verified_stmt("FETCH BACKWARD ALL IN \"SQL_CUR0x7fa44801bc00\" INTO \"new_table\"");
}
#[test]
fn parse_custom_operator() {
// operator with a database and schema
let sql = r#"SELECT * FROM events WHERE relname OPERATOR(database.pg_catalog.~) '^(table)$'"#;
let select = pg().verified_only_select(sql);
assert_eq!(
select.selection,
Some(Expr::BinaryOp {
left: Box::new(Expr::Identifier(Ident {
value: "relname".into(),
quote_style: None,
})),
op: BinaryOperator::PGCustomBinaryOperator(vec![
"database".into(),
"pg_catalog".into(),
"~".into()
]),
right: Box::new(Expr::Value(Value::SingleQuotedString("^(table)$".into())))
})
);
// operator with a schema
let sql = r#"SELECT * FROM events WHERE relname OPERATOR(pg_catalog.~) '^(table)$'"#;
let select = pg().verified_only_select(sql);
assert_eq!(
select.selection,
Some(Expr::BinaryOp {
left: Box::new(Expr::Identifier(Ident {
value: "relname".into(),
quote_style: None,
})),
op: BinaryOperator::PGCustomBinaryOperator(vec!["pg_catalog".into(), "~".into()]),
right: Box::new(Expr::Value(Value::SingleQuotedString("^(table)$".into())))
})
);
// custom operator without a schema
let sql = r#"SELECT * FROM events WHERE relname OPERATOR(~) '^(table)$'"#;
let select = pg().verified_only_select(sql);
assert_eq!(
select.selection,
Some(Expr::BinaryOp {
left: Box::new(Expr::Identifier(Ident {
value: "relname".into(),
quote_style: None,
})),
op: BinaryOperator::PGCustomBinaryOperator(vec!["~".into()]),
right: Box::new(Expr::Value(Value::SingleQuotedString("^(table)$".into())))
})
);
}