Skip to content

Commit da153bf

Browse files
committed
Make a PostgreSQLDialect
Add is_primary and is_unique in the column definition Initial code for testing alter table
1 parent 74b34fa commit da153bf

File tree

4 files changed

+125
-13
lines changed

4 files changed

+125
-13
lines changed

src/dialect.rs

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,88 @@ impl Dialect for AnsiSqlDialect {
370370
pub struct GenericSqlDialect {}
371371

372372
impl Dialect for GenericSqlDialect {
373+
fn keywords(&self) -> Vec<&'static str> {
374+
return vec![
375+
"SELECT",
376+
"FROM",
377+
"WHERE",
378+
"LIMIT",
379+
"ORDER",
380+
"GROUP",
381+
"BY",
382+
"HAVING",
383+
"UNION",
384+
"ALL",
385+
"INSERT",
386+
"INTO",
387+
"UPDATE",
388+
"DELETE",
389+
"IN",
390+
"IS",
391+
"NULL",
392+
"SET",
393+
"CREATE",
394+
"EXTERNAL",
395+
"TABLE",
396+
"ASC",
397+
"DESC",
398+
"AND",
399+
"OR",
400+
"NOT",
401+
"AS",
402+
"STORED",
403+
"CSV",
404+
"PARQUET",
405+
"LOCATION",
406+
"WITH",
407+
"WITHOUT",
408+
"HEADER",
409+
"ROW",
410+
// SQL types
411+
"CHAR",
412+
"CHARACTER",
413+
"VARYING",
414+
"LARGE",
415+
"OBJECT",
416+
"VARCHAR",
417+
"CLOB",
418+
"BINARY",
419+
"VARBINARY",
420+
"BLOB",
421+
"FLOAT",
422+
"REAL",
423+
"DOUBLE",
424+
"PRECISION",
425+
"INT",
426+
"INTEGER",
427+
"SMALLINT",
428+
"BIGINT",
429+
"NUMERIC",
430+
"DECIMAL",
431+
"DEC",
432+
"BOOLEAN",
433+
"DATE",
434+
"TIME",
435+
"TIMESTAMP",
436+
];
437+
}
438+
439+
fn is_identifier_start(&self, ch: char) -> bool {
440+
(ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z') || ch == '@'
441+
}
442+
443+
fn is_identifier_part(&self, ch: char) -> bool {
444+
(ch >= 'a' && ch <= 'z')
445+
|| (ch >= 'A' && ch <= 'Z')
446+
|| (ch >= '0' && ch <= '9')
447+
|| ch == '@'
448+
|| ch == '_'
449+
}
450+
}
451+
452+
pub struct PostgreSqlDialect {}
453+
454+
impl Dialect for PostgreSqlDialect {
373455
fn keywords(&self) -> Vec<&'static str> {
374456
return vec![
375457
"SELECT",
@@ -443,6 +525,9 @@ impl Dialect for GenericSqlDialect {
443525
"FALSE",
444526
"COPY",
445527
"STDIN",
528+
"PRIMARY",
529+
"KEY",
530+
"UNIQUE",
446531
];
447532
}
448533

src/sqlast.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,8 @@ pub struct SQLColumnDef {
176176
pub name: String,
177177
pub data_type: SQLType,
178178
pub allow_null: bool,
179+
pub is_primary: bool,
180+
pub is_unique: bool,
179181
pub default: Option<Box<ASTNode>>,
180182
}
181183

src/sqlparser.rs

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -478,6 +478,8 @@ impl Parser {
478478
loop {
479479
if let Some(Token::Identifier(column_name)) = self.next_token() {
480480
if let Ok(data_type) = self.parse_data_type() {
481+
let is_primary = self.parse_keywords(vec!["PRIMARY", "KEY"]);
482+
let is_unique = self.parse_keyword("UNIQUE");
481483
let default = if self.parse_keyword("DEFAULT"){
482484
let expr = self.parse_expr(0)?;
483485
Some(Box::new(expr))
@@ -500,6 +502,8 @@ impl Parser {
500502
name: column_name,
501503
data_type: data_type,
502504
allow_null,
505+
is_primary,
506+
is_unique,
503507
default,
504508
});
505509
}
@@ -509,6 +513,8 @@ impl Parser {
509513
name: column_name,
510514
data_type: data_type,
511515
allow_null,
516+
is_primary,
517+
is_unique,
512518
default,
513519
});
514520
break;
@@ -538,6 +544,7 @@ impl Parser {
538544
}
539545
}
540546

547+
541548
/// Parse a copy statement
542549
pub fn parse_copy(&mut self) -> Result<ASTNode, ParserError> {
543550
let table_name = self.parse_tablename()?;
@@ -1090,13 +1097,13 @@ impl Parser {
10901097
#[cfg(test)]
10911098
mod tests {
10921099

1093-
use super::super::dialect::GenericSqlDialect;
1100+
use super::super::dialect::PostgreSqlDialect;
10941101
use super::*;
10951102

10961103
#[test]
10971104
fn test_prev_index(){
10981105
let sql: &str = "SELECT version()";
1099-
let mut tokenizer = Tokenizer::new(&GenericSqlDialect{}, &sql);
1106+
let mut tokenizer = Tokenizer::new(&PostgreSqlDialect{}, &sql);
11001107
let tokens = tokenizer.tokenize().expect("error tokenizing");
11011108
let mut parser = Parser::new(tokens);
11021109
assert_eq!(parser.prev_token(), None);
@@ -1542,9 +1549,9 @@ mod tests {
15421549
fn parse_create_table_with_inherit() {
15431550
let sql = String::from("
15441551
CREATE TABLE bazaar.settings (
1545-
user_id uuid,
1552+
settings_id uuid PRIMARY KEY DEFAULT uuid_generate_v4() NOT NULL,
1553+
user_id uuid UNIQUE,
15461554
value text[],
1547-
settings_id uuid DEFAULT uuid_generate_v4() NOT NULL,
15481555
use_metric boolean DEFAULT true
15491556
)
15501557
INHERITS (system.record)");
@@ -1554,14 +1561,40 @@ mod tests {
15541561
assert_eq!("bazaar.settings", name);
15551562

15561563
let c_name = &columns[0];
1564+
assert_eq!("settings_id", c_name.name);
1565+
assert_eq!(SQLType::Custom("uuid".into()), c_name.data_type);
1566+
assert_eq!(false, c_name.allow_null);
1567+
assert_eq!(true, c_name.is_primary);
1568+
assert_eq!(false, c_name.is_unique);
1569+
1570+
let c_name = &columns[1];
15571571
assert_eq!("user_id", c_name.name);
15581572
assert_eq!(SQLType::Custom("uuid".into()), c_name.data_type);
15591573
assert_eq!(true, c_name.allow_null);
1574+
assert_eq!(false, c_name.is_primary);
1575+
assert_eq!(true, c_name.is_unique);
15601576
}
15611577
_ => assert!(false),
15621578
}
15631579
}
15641580

1581+
#[test]
1582+
fn parse_alter_table_constraint_primary_key(){
1583+
let sql = String::from("
1584+
ALTER TABLE ONLY bazaar.address
1585+
ADD CONSTRAINT address_pkey PRIMARY KEY (address_id)");
1586+
let ast = parse_sql(&sql);
1587+
}
1588+
1589+
#[test]
1590+
fn parse_alter_table_constraint_foreign_key(){
1591+
let sql = String::from("
1592+
ALTER TABLE ONLY public.customer
1593+
ADD CONSTRAINT customer_address_id_fkey FOREIGN KEY (address_id) REFERENCES public.address(address_id) ON UPDATE CASCADE ON DELETE RESTRICT;
1594+
");
1595+
let ast = parse_sql(&sql);
1596+
}
1597+
15651598
#[test]
15661599
fn parse_copy_example(){
15671600
let sql = String::from(r#"
@@ -1681,7 +1714,7 @@ PHP ₱ USD $
16811714
}
16821715

16831716
fn parser(sql: &str) -> Parser {
1684-
let dialect = GenericSqlDialect {};
1717+
let dialect = PostgreSqlDialect {};
16851718
let mut tokenizer = Tokenizer::new(&dialect, &sql);
16861719
let tokens = tokenizer.tokenize().unwrap();
16871720
debug!("tokens: {:#?}", tokens);

src/sqltokenizer.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -203,14 +203,6 @@ impl<'a> Tokenizer<'a> {
203203
tokens.push(token);
204204
}
205205
Ok(tokens)
206-
/*
207-
Ok(tokens
208-
.into_iter()
209-
.filter(|t| match t {
210-
Token::Whitespace(..) => false,
211-
_ => true,
212-
}).collect())
213-
*/
214206
}
215207

216208
/// Get the next token or return None

0 commit comments

Comments
 (0)