All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project aims to adhere to Semantic Versioning.
Given that the parser produces a typed AST, any changes to the AST will technically be breaking and thus will result in a 0.(N+1) version. We document changes that break via addition as “Added”.
Check https://github.com/sqlparser-rs/sqlparser-rs/commits/main for undocumented changes.
CREATE TABLE with ORDER BY (#824) - Thanks @ankrgyl^ operator (#813) - Thanks @michael-2956BIGNUMERIC type in BigQuery (#811) - Thanks @togami2864ReplaceSelectElement colum_name --> column_name (#822) - Thanks @togami2864SELECT * REPLACE <Expr> AS <Identifier> in BigQuery dialect (#798) - Thanks @togami2864TRANSIENT keyword in Snowflake dialect (#807) - Thanks @mobuchowskiJSON keyword (#799) - Thanks @togami2864RENAME for wildcard SELECTs (#784) - Thanks @Jefffreyfeat: dollar-quoted strings support (#772) - Thanks @vasilev-alex
ALTER INDEX {INDEX_NAME} RENAME TO {NEW_INDEX_NAME} (#767) - Thanks @devgonyCREATE TABLE ON UPDATE <expr> Function (#685) - Thanks @CEOJINSUNGCREATE FUNCTION definition with $$ (#755)- Thanks @zidaye10e5) (#768) - Thanks @JefffreyDROP FUNCTION syntax (#752) - Thanks @zidaye@> <@, @? and @@ - Thanks @audunskaGenericDialect (#771) - Thanks @JefffreyNANOSECOND keyword (#749)- Thanks @waitingkuoEXCEPT clause on wildcards (#745) - Thanks @AugustoFKLCREATE FUNCTION Postgres options (#722) - Thanks @wangrunji0408CREATE TABLE x AS TABLE y (#704) - Thanks @sarahyurickROWS syntax for VALUES (#737) - Thanks @aljazerzenWHERE condition for UPDATE ON CONFLICT (#735) - Thanks @zidayeCLUSTER BY when creating Materialized View (#736) - Thanks @yuval-illumexUSING method when creating indexes. (#731) - Thanks @step-baby and @yangjiaxin01SEMI/ANTI JOIN syntax (#723) - Thanks @mingmwangEXCLUDE support for snowflake and generic dialect (#721) - Thanks @AugustoFKLMATCH AGAINST (#708) - Thanks @AugustoFKLIF NOT EXISTS in ALTER TABLE ADD COLUMN (#707) - Thanks @AugustoFKLSET TIME ZONE <value> (#727) - Thanks @waitingkuoUPDATE ... FROM ( subquery ) (#694) - Thanks @unvalleyParser::index() method to get current parsing index (#728) - Thanks @neverchanjeCOMPRESSION as keyword (#720)- Thanks @AugustoFKLPartialOrd, Ord, and Copy whenever possible (#717) - Thanks @AugustoFKLINTERVAL parsing logic and precedence (#705) - Thanks @sarahyurickON CONFLICT and RETURNING in UPDATE statement (#666) - Thanks @main and @gamifeFULLTEXT option on create table for MySQL and Generic dialects (#702) - Thanks @AugustoFKLARRAY_AGG for Bigquery and Snowflake (#662) - Thanks @SuperBo: operator for semi-structured data in Snowflake(#693) - Thanks @yuval-illumexNUMERIC and DEC ANSI data types (#695) - Thanks @AugustoFKL{INDEX | KEY} in CREATE TABLE definiton (#665) - Thanks @AugustoFKLCREATE [ { TEMPORARY | TEMP } ] SEQUENCE [ IF NOT EXISTS ] <sequence_name> (#678) - Thanks @sam-mmmDROP SEQUENCE statement (#673) - Thanks @sam-mmmCHARACTER LARGE OBJECT[(p)] and CHAR LARGE OBJECT[(p)] (#671) - Thanks @AugustoFKL[CACHE|UNCACHE] TABLE (#670) - Thanks @francis-duCEIL(expr TO DateTimeField) and FLOOR(expr TO DateTimeField) - Thanks @sarahyurickSET ROLE with a single enum. (#664) - Thanks @AugustoFKLOptions with enum for DECIMAL precision (#654) - Thanks @AugustoFKLAUTHORIZATION clause in CREATE SCHEMA statements (#641) - Thanks @AugustoFKLCLOB and BLOB (#639) - Thanks @AugustoFKLVARBINARY and BINARY (#637) - Thanks @AugustoFKLTIMESTAMP and TIME parsing preserve zone information (#646) - Thanks @AugustoFKLLIMIT x,y , restrict to MySql and Generic dialects - Thanks @AugustoFKLMILLENNIUM (2 Ns) (#633) - Thanks @sarahyurickMEDIUMINT (#630) - Thanks @AugustoFKLDOUBLE PRECISION (#629) - Thanks @AugustoFKLCLOB, BINARY, VARBINARY, BLOB data type (#618) - Thanks @ding-youngCREATE ROLE and DROP ROLE (#598) - Thanks @blxn (#612) - Thanks @mskrzypkowsset time zone to 'some-timezone' (#617) - Thanks @waitingkuoValue::Interval to Expr::Interval (#609) - Thanks @ding-youngcriterion dev-requirement from 0.3 to 0.4 in /sqlparser_bench (#611) - Thanks @dependabotQuery in Cte (#572) - Thanks @MazterQyouLOCALTIME and LOCALTIMESTAMP time functions (#592) - Thanks @MazterQyouOVERLAY expressions (#594) - Thanks @ayushgWITH TIMEZONE and WITHOUT TIMEZONE when parsing TIMESTAMP expressions (#589) - Thanks @waitingkuoIS [NOT] TRUE, IS [NOT] FALSE, and IS [NOT] UNKNOWN - Thanks (#583) @sarahyurickSIMILAR TO syntax (#569) - Thanks @ayushdgSHOW COLLATION (#564) - Thanks @MazterQyouSHOW TABLES (#563) - Thanks @MazterQyouSET NAMES literal [COLLATE literal] (#558) - Thanks @ovrBigQuery dialect - Thanks @komukomoUSE <DB> (#565) - Thanks @MazterQyouSHOW COLUMNS FROM tbl FROM db (#562) - Thanks @MazterQyouSHOW VARIABLES for MySQL dialect (#559) - Thanks @ovr and @vasilev-alexSET statement (#574) - Thanks @ovr and @vasilev-alexTRIM from with optional expr and FROM expr (#573) - Thanks @ayushdgLike and ILike to Expr variants, allow escape char (#569) - Thanks @ayushdgcurrent_user, user, etc) (#561) - Thanks @ovrLIMIT/OFFSET (#567) - Thanks @MazterQyouOPERATOR postgres syntax (#548) - Thanks @iskakaushikSAFE_CAST for BigQuery (#552) - Thanks @togami2864>> and << binary operators in Generic dialect (#553) - Thanks @ovrNestedJoin with an alias (#551) - Thanks @waitingkuoON CLUSTER for CREATE TABLE statement (ClickHouse DDL) (#527) - Thanks @andyrichardsonARRAY literals (#532) - Thanks @bitemyappAT TIME ZONE clause (#539) - Thanks @bitemyappUSING clause and table aliases in DELETE (#541) - Thanks @mobuchowskiSHOW CREATE VIEW statement (#536) - Thanks @mrob95CLONE clause in CREATE TABLE statements (#542) - Thanks @mobuchowskiWITH OFFSET Alias in table references (#528) - Thanks @sivchari") literal strings: (#530) - Thanks @komukomoON UPDATE clause on column definitions in CREATE TABLE statements (#522) - Thanks @frolovdevBoxed Query body to save stack space (#540) - Thanks @5tanINT and INTEGER types (#525) - Thanks @frolovdevWHERE NOT EXISTS as Expr::Exists rather than Expr::UnaryOp for consistency (#523) - Thanks @frolovdevExpr instead of String for argument to INTERVAL (#517) - Thanks @togami2864CLOSE (cursors) (#515) - Thanks @ovrDECLARE (cursors) (#509) - Thanks @ovrFETCH (cursors) (#510) - Thanks @ovrDATETIME keyword (#512) - Thanks @komukomoUNNEST as a table factor (#493) - Thanks @sivchariCREATE FUNCTION (hive flavor) (#496) - Thanks @mobuchowski$ or ?) in LIMIT clause (#494) - Thanks @step-babyIS TRUE and IS FALSE (#499) - Thanks @ovrDISCARD [ALL | PLANS | SEQUENCES | TEMPORARY | TEMP] (#500) - Thanks @gandronchikarray<..> HIVE data types (#491) - Thanks @mobuchowskiSET values that begin with - #495 - Thanks @mobuchowskiBigQuery dialect (#490) - Thanks @komukomoArrayIndex::indexs to ArrayIndex::indexes (#492) - Thanks @alambCOLLATE after parentheses in expressions (#507) - Thanks @razzolini-qpqFROM (#506) - Thanks @razzolini-qpqMERGE INTO semicolon handling (#508) - Thanks @mskrzypkows# as first character in field name for RedShift dialect (#485) - Thanks @yuval-illumexTABLE keyword with SELECT INTO (#487) - Thanks @MazterQyouANY/ALL operators (#477) - Thanks @ovrArrayIndex in GenericDialect (#480) - Thanks @ovrRedshift dialect, handle square brackets properly (#471) - Thanks @mskrzypkowsKILL statement (#479) - Thanks @ovrQUALIFY clause on SELECT for Snowflake dialect (#465) - Thanks @mobuchowskiPOSITION(x IN y) function syntax (#463) @yuval-illumexglobal,local, on commit for create temporary table (#456) - Thanks @gandronchikNVARCHAR data type (#462) - Thanks @yuval-illumex->, ->>, #>, and #>> (#458) - Thanks @poonaiSET ROLE statement (#455) - Thanks @slhmyKILL statement (#481) - Thanks @alambPOSITION (#469) - Thanks @alambIN parsing (#468) - Thanks @alambMERGE statements (#483) - Thanks @mskrzypkowsINTO keyword is optional for INSERT, MERGE (#473) - Thanks @mobuchowskiIS TRUE and IS FALSE expressions in boolean filter (#474) - Thanks @yuval-illumexSET VARIABLE (#484) - Thanks mobuchowskiWEEK keyword in EXTRACT (#436) - Thanks @Ted-JiangMERGE statement (#430) - Thanks @mobuchowskiSAVEPOINT statement (#438) - Thanks @poonaiTO clause in COPY (#441) - Thanks @matthewmturnerCREATE DATABASE statement (#451) - Thanks @matthewmturnerFROM clause in UPDATE statement (#450) - Thanks @slhmyCOPY options (#446) - Thanks @wangrunji0408unsigned tinyint, unsigned int, unsigned smallint and unsigned bigint datatypes (#428) - Thanks @watarukuraEXTRACT (#427) - Thanks @mobuchowski? and $ (#420) - Thanks @gamifeARRAY[1,2] , foo[1] and INT[][] (#419) - Thanks @gamifearray to be used as a function name again (#432) - @alambQuery (#423) - Thanks @max-sixtyCURRENT_TIMESTAMP, CURRENT_TIME, and CURRENT_DATE (#391) - Thanks @yuval-illumexSUPER keyword (#387) - Thanks @flaneur2020OFFSET LIMIT as well as LIMIT OFFSET (#413) - Thanks @yuval-illumexFROM <filename>, DELIMITER, and CSV HEADER options for COPY command (#409) - Thanks @poonaiCHARSET and ENGINE clauses on CREATE TABLE for mysql (#392) - Thanks @antializeDROP CONSTRAINT [ IF EXISTS ] <name> [ CASCADE ] (#396) - Thanks @tvallottonExpr::Tuple (#414) - @alambLIMIT X, Y (#415) - @alambSESSION TRANSACTION and TRANSACTION SNAPSHOT. (#379) - Thanks @poonaiALTER COLUMN and RENAME CONSTRAINT (#381) - Thanks @zhamlin*) can appear, add to FunctionArgExpr remove Expr::[Qualified]Wildcard, (#378) - Thanks @panarchGRANT/REVOKE in CONNECT, CREATE, EXECUTE or TEMPORARY - Thanks @evgenyx000x (#324) - Thanks @TheSchemm!no_std (#332) - Thanks @koushiro!~, ~*, !~, !~*) (#328) - Thanks @b41sh!Modulus to Modulo (#335) - Thanks @RGRAVITY817!sqlparser-rs GitHub org (#333) - Thanks @andygroveWindowFrame (#313) - Thanks @Jimexist!TRY_CAST syntax (#299) - Thanks @seddonm1!HiveDialect and syntax (#235) - Thanks @hntd187!SUBSTRING(col [FROM <expr>] [FOR <expr>]) syntax (#293).01 (#294)INSERT OR [..] syntax (#281) - Thanks @zhangli-pear!`identifiers` quoted with backticks instead of the standard "double-quoted" identifiers (#247) - thanks @mashuai!dialect_of!()) (#254) - thanks @eyalleshem!ARG_NAME => val) (#250) - thanks @eyalleshem!TABLE() functions in FROM (#253) - thanks @eyalleshem!PREPARE, EXECUTE, and DEALLOCATE (#243) - thanks @silathdiir!FROM (table_name) alias syntax - thanks @eyalleshem!EXPLAIN [ANALYZE] VERBOSE - thanks @ovr!ANALYZE TABLEOR REPLACE in CREATE VIEW/TABLE (#239) - thanks @Dandandan!ASC/DESC in index columns (#249) - thanks @mashuai!AUTOINCREMENT and MySQL AUTO_INCREMENT column option in CREATE TABLE (#234) - thanks @mashuai!IF NOT EXISTS for CREATE SCHEMA (#276) - thanks @alex-dukhno!JSONFILE serialization, introduced in 0.3.1 (#237)CREATE INDEX serialization to not end with a semicolon, introduced in 0.5.1 (#245)ALTER TABLE ADD COLUMN ending with a semicolon, introduced in 0.5.1 (#246) - thanks @mashuaiASSERT statement (#226)CREATE TABLE (...) WITHOUT ROWID (#208) - thanks @mashuai!CREATE VIRTUAL TABLE (#209) - thanks @mashuai!This release should have been called 0.6, as it introduces multiple incompatible changes to the API. If you don't want to upgrade yet, you can revert to the previous version by changing your Cargo.toml to:
sqlparser = "= 0.5.0"
Parser::parse_sql now accepts a &str instead of String (#182) - thanks @Dandandan!Ident (previously a simple String) to store the parsed (unquoted) value of the identifier and the quote_style separately (#143) - thanks @apparebit!FROM (table_name) (#155) - thanks @eyalleshem!INTERVAL '...' optional (#184) - thanks @maxcountryman!DATE/TIME/TIMESTAMP literals representation in the AST (TypedString { data_type, value }) and allow DATE and other keywords to be used as identifiers when not followed by a string (#187) - thanks @maxcountryman!fmt::Display) (#202) - thanks @Dandandan!TOP (<N>) [ PERCENT ] [ WITH TIES ] (#150) - thanks @alexkyllo!LIMIT row_count OFFSET offset (not followed by ROW or ROWS) and remember which variant was parsed (#158) - thanks @mjibson!CREATE TABLE IF NOT EXISTS table_name (#163) - thanks @alex-dukhno!CREATE INDEX and DROP INDEX (#167) - thanks @mashuai!ON { UPDATE | DELETE } { RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT } in FOREIGN KEY constraints (#170) - thanks @c7hm4r!CREATE SCHEMA and DROP SCHEMA (#173) - thanks @alex-dukhno!NULLS FIRST/LAST in ORDER BY expressions (#176) - thanks @houqp!LISTAGG() (#174) - thanks @maxcountryman!|| (#178) - thanks @Dandandan!&), OR (|), XOR (^) (#181) - thanks @Dandandan!ALTER TABLE ADD COLUMN, RENAME COLUMN, and RENAME TO (#203) - thanks @mashuai!ALTER TABLE DROP COLUMN (#148) - thanks @ivanceras!CREATE TABLE ... AS ... (#206) - thanks @Dandandan!STORED AS) case insensitive (#200) and don't allow quoting it (#201) - thanks @Dandandan!Value::Long(u64) and Value::Double(f64) variants with Value::Number(String) to avoid losing precision when parsing decimal literals (#130) - thanks @benesch!--features bigdecimal can be enabled to work with Value::Number(BigDecimal) instead, at the cost of an additional dependency.SHOW COLUMNS, SET <variable>=<value>, and SHOW <variable> statements (#135) - thanks @quodlibetor and @benesch!START TRANSACTION followed by a semicolon (#139) - thanks @gaffneyk!This release brings us closer to SQL-92 support, mainly thanks to the improvements contributed back from @MaterializeInc's fork and other work by @benesch.
SQLType -> DataType, remove “sql” prefix from module names (#105, #122)ASTNode -> Expr (#119)ASTNode::SQLBinaryExpr is now Expr::BinaryOp and ASTNode::SQLUnary is Expr::UnaryOp;op: SQLOperator field is now either a BinaryOperator or an UnaryOperator.SQLSelect‘s relation and joins are replaced with from: Vec<TableWithJoins>. Before this change FROM foo NATURAL JOIN bar, baz was represented as “foo” as the relation followed by two joins (Inner(Natural) and Implicit); now it’s two TableWithJoins (foo NATURAL JOIN bar and baz).SQLFunction struct (#89)Option<Vec<T>> with Vec<T> in the AST structs (#73)Value::Long() to be unsigned, use u64 consistently (#65)fmt::Display on AST nodes (#124) - thanks @vemoo!Hash (#88) and Eq (#123) on all AST nodesstd::error::Error for ParserError (#72)INTERVAL literals (#103)DATE / TIME / TIMESTAMP literals (#99)EXTRACT (#96)X'hex value' literals (#95)EXISTS subqueries (#90)BETWEEN (#80)COUNT(DISTINCT x) and similar (#77)CASE operand WHEN expected_value THEN .. and table-valued functions (#59)OVER clause) (#50)UPDATE statements (#97)INSERT INTO foo SELECT * FROM bar and FROM VALUES (...) (#91)SELECT ALL (#76)FETCH and OFFSET support, and LATERAL (#69) - thanks @thomas-jeepe!COLLATE, optional column list in CTEs (#64)START/SET/COMMIT/ROLLBACK TRANSACTION (#106) - thanks @SamuelMarks!DECIMAL and DEC aliases for NUMERIC type (#92)DROP [TABLE|VIEW] (#75)WITH options for CREATE [TABLE|VIEW] (#74)CREATE TABLE (#65)CROSS/OUTER APPLY (#120)WITH hints (#59)SELECT * FROM a OUTER JOIN b instead of parsing OUTER as an alias (#118)NOT LIKE (#82) and unary NOT (#107)NOT is not followed by an expected keyword (#71) successfully instead of returning a parse error - thanks @ivanceras! (#67) - and similar fixes for queries with no FROM (#116)ALTER TABLE ADD CONSTRAINT parsing (#65)<> instead of != (#64)uuid (#59) and chrono (#61)SELECT query with LIMIT clause but no WHERE parse - Fix incorrect behavior of ASTNode::SQLQualifiedWildcard::to_string() (returned foo* instead of foo.*) - thanks @thomas-jeepe! (#52)SQLStatement::SQLCreateTable to support Hive's EXTERNAL TABLES (CREATE EXTERNAL TABLE .. STORED AS .. LOCATION '..') - thanks @zhzy0077! (#46)SELECT DISTINCT to SQLSelect::distinct (#49)This release includes major changes to the AST structs to add a number of features, as described in #37 and #43. In particular:
ASTNode variants that represent statements were extracted from ASTNode into a separate SQLStatement enum;Parser::parse_sql now returns a Vec of parsed statements.ASTNode now represents an expression (renamed to Expr in 0.4.0)ASTNode::SQLSelect) became more complicated to support:WITH and UNION/EXCEPT/INTERSECT (via SQLQuery, Cte, and SQLSetExpr),SELECT (via SQLSelectItem),FROM/JOIN (via TableFactor).SQLObjectName struct is used instead of String or ASTNode::SQLCompoundIdentifier - for objects like tables, custom types, etc.SELECT .. FROM .. LIMIT .. (#67), fixed in 0.4.0Other than the changes listed above, some less intrusive additions include:
CREATE [MATERIALIZED] VIEW statementIN, BETWEEN, unary +/- in epressionsCHAR data type and NUMERIC not followed by (p,s).N'...')Same as 0.2.2.
Value::String, Value::DoubleQuotedString, and Token::String, making'...' parse as a string literal (Value::SingleQuotedString), and"..." fail to parse until version 0.3.0 (#36)We don't have a changelog for the changes made in 2018, but thanks to @crw5996, @cswinter, @fredrikroos, @ivanceras, @nickolay, @virattara for their contributions in the early stages of the project!
Initial release