datafusion-sqlparse/tests/sqlparser_postgres.rs
Nikhil Benesch cf655ad1a6
Remove "sql" prefix from module names
Since this crate only deals with SQL parsing, the modules are understood
to refer to SQL and don't need to restate that explicitly.
2019-06-24 12:56:26 -04:00

267 lines
11 KiB
Rust

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#![warn(clippy::all)]
//! Test SQL syntax specific to PostgreSQL. The parser based on the
//! generic dialect is also tested (on the inputs it can handle).
use sqlparser::ast::*;
use sqlparser::dialect::{GenericSqlDialect, PostgreSqlDialect};
use sqlparser::test_utils::*;
#[test]
fn parse_create_table_with_defaults() {
let sql = "CREATE TABLE public.customer (
customer_id integer DEFAULT nextval(public.customer_customer_id_seq),
store_id smallint NOT NULL,
first_name character varying(45) NOT NULL,
last_name character varying(45) COLLATE \"es_ES\" NOT NULL,
email character varying(50),
address_id smallint NOT NULL,
activebool boolean DEFAULT true NOT NULL,
create_date date DEFAULT now()::text NOT NULL,
last_update timestamp without time zone DEFAULT now() NOT NULL,
active integer NOT NULL
) WITH (fillfactor = 20, user_catalog_table = true, autovacuum_vacuum_threshold = 100)";
match pg_and_generic().one_statement_parses_to(sql, "") {
SQLStatement::SQLCreateTable {
name,
columns,
constraints,
with_options,
external: false,
file_format: None,
location: None,
} => {
assert_eq!("public.customer", name.to_string());
assert_eq!(
columns,
vec![
SQLColumnDef {
name: "customer_id".into(),
data_type: SQLType::Int,
collation: None,
options: vec![ColumnOptionDef {
name: None,
option: ColumnOption::Default(
pg().verified_expr("nextval(public.customer_customer_id_seq)")
)
}],
},
SQLColumnDef {
name: "store_id".into(),
data_type: SQLType::SmallInt,
collation: None,
options: vec![ColumnOptionDef {
name: None,
option: ColumnOption::NotNull,
}],
},
SQLColumnDef {
name: "first_name".into(),
data_type: SQLType::Varchar(Some(45)),
collation: None,
options: vec![ColumnOptionDef {
name: None,
option: ColumnOption::NotNull,
}],
},
SQLColumnDef {
name: "last_name".into(),
data_type: SQLType::Varchar(Some(45)),
collation: Some(SQLObjectName(vec!["\"es_ES\"".into()])),
options: vec![ColumnOptionDef {
name: None,
option: ColumnOption::NotNull,
}],
},
SQLColumnDef {
name: "email".into(),
data_type: SQLType::Varchar(Some(50)),
collation: None,
options: vec![],
},
SQLColumnDef {
name: "address_id".into(),
data_type: SQLType::SmallInt,
collation: None,
options: vec![ColumnOptionDef {
name: None,
option: ColumnOption::NotNull
}],
},
SQLColumnDef {
name: "activebool".into(),
data_type: SQLType::Boolean,
collation: None,
options: vec![
ColumnOptionDef {
name: None,
option: ColumnOption::Default(Expr::SQLValue(Value::Boolean(true))),
},
ColumnOptionDef {
name: None,
option: ColumnOption::NotNull,
}
],
},
SQLColumnDef {
name: "create_date".into(),
data_type: SQLType::Date,
collation: None,
options: vec![
ColumnOptionDef {
name: None,
option: ColumnOption::Default(
pg().verified_expr("CAST(now() AS text)")
)
},
ColumnOptionDef {
name: None,
option: ColumnOption::NotNull,
}
],
},
SQLColumnDef {
name: "last_update".into(),
data_type: SQLType::Timestamp,
collation: None,
options: vec![
ColumnOptionDef {
name: None,
option: ColumnOption::Default(pg().verified_expr("now()")),
},
ColumnOptionDef {
name: None,
option: ColumnOption::NotNull,
}
],
},
SQLColumnDef {
name: "active".into(),
data_type: SQLType::Int,
collation: None,
options: vec![ColumnOptionDef {
name: None,
option: ColumnOption::NotNull
}],
},
]
);
assert!(constraints.is_empty());
assert_eq!(
with_options,
vec![
SQLOption {
name: "fillfactor".into(),
value: Value::Long(20)
},
SQLOption {
name: "user_catalog_table".into(),
value: Value::Boolean(true)
},
SQLOption {
name: "autovacuum_vacuum_threshold".into(),
value: Value::Long(100)
},
]
);
}
_ => unreachable!(),
}
}
#[test]
fn parse_create_table_from_pg_dump() {
let sql = "CREATE TABLE public.customer (
customer_id integer DEFAULT nextval('public.customer_customer_id_seq'::regclass) NOT NULL,
store_id smallint NOT NULL,
first_name character varying(45) NOT NULL,
last_name character varying(45) NOT NULL,
info text[],
address_id smallint NOT NULL,
activebool boolean DEFAULT true NOT NULL,
create_date date DEFAULT now()::date NOT NULL,
create_date1 date DEFAULT 'now'::text::date NOT NULL,
last_update timestamp without time zone DEFAULT now(),
release_year public.year,
active integer
)";
pg().one_statement_parses_to(sql, "CREATE TABLE public.customer (\
customer_id int DEFAULT nextval(CAST('public.customer_customer_id_seq' AS regclass)) NOT NULL, \
store_id smallint NOT NULL, \
first_name character varying(45) NOT NULL, \
last_name character varying(45) NOT NULL, \
info text[], \
address_id smallint NOT NULL, \
activebool boolean DEFAULT true NOT NULL, \
create_date date DEFAULT CAST(now() AS date) NOT NULL, \
create_date1 date DEFAULT CAST(CAST('now' AS text) AS date) NOT NULL, \
last_update timestamp DEFAULT now(), \
release_year public.year, \
active int\
)");
}
#[test]
fn parse_create_table_with_inherit() {
let sql = "\
CREATE TABLE bazaar.settings (\
settings_id uuid PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL, \
user_id uuid UNIQUE, \
value text[], \
use_metric boolean DEFAULT true\
)";
pg().verified_stmt(sql);
}
#[test]
fn parse_copy_example() {
let sql = r#"COPY public.actor (actor_id, first_name, last_name, last_update, value) FROM stdin;
1 PENELOPE GUINESS 2006-02-15 09:34:33 0.11111
2 NICK WAHLBERG 2006-02-15 09:34:33 0.22222
3 ED CHASE 2006-02-15 09:34:33 0.312323
4 JENNIFER DAVIS 2006-02-15 09:34:33 0.3232
5 JOHNNY LOLLOBRIGIDA 2006-02-15 09:34:33 1.343
6 BETTE NICHOLSON 2006-02-15 09:34:33 5.0
7 GRACE MOSTEL 2006-02-15 09:34:33 6.0
8 MATTHEW JOHANSSON 2006-02-15 09:34:33 7.0
9 JOE SWANK 2006-02-15 09:34:33 8.0
10 CHRISTIAN GABLE 2006-02-15 09:34:33 9.1
11 ZERO CAGE 2006-02-15 09:34:33 10.001
12 KARL BERRY 2017-11-02 19:15:42.308637+08 11.001
A Fateful Reflection of a Waitress And a Boat who must Discover a Sumo Wrestler in Ancient China
Kwara & Kogi
{"Deleted Scenes","Behind the Scenes"}
'awe':5 'awe-inspir':4 'barbarella':1 'cat':13 'conquer':16 'dog':18 'feminist':10 'inspir':6 'monasteri':21 'must':15 'stori':7 'streetcar':2
PHP ₱ USD $
\N Some other value
\\."#;
let ast = pg_and_generic().one_statement_parses_to(sql, "");
println!("{:#?}", ast);
//assert_eq!(sql, ast.to_string());
}
fn pg() -> TestedDialects {
TestedDialects {
dialects: vec![Box::new(PostgreSqlDialect {})],
}
}
fn pg_and_generic() -> TestedDialects {
TestedDialects {
dialects: vec![
Box::new(PostgreSqlDialect {}),
Box::new(GenericSqlDialect {}),
],
}
}