diff --git a/src/sqlparser/src/parser.rs b/src/sqlparser/src/parser.rs index 2b6654d0cc4df..a3c63c4b2b357 100644 --- a/src/sqlparser/src/parser.rs +++ b/src/sqlparser/src/parser.rs @@ -1475,7 +1475,24 @@ impl Parser { /// Report unexpected token pub fn expected(&self, expected: &str, found: Token) -> Result { - parser_err!(format!("Expected {}, found: {}", expected, found)) + let start_off = self.index.saturating_sub(10); + let end_off = self.index.min(self.tokens.len()); + let near_tokens = &self.tokens[start_off..end_off]; + struct TokensDisplay<'a>(&'a [Token]); + impl<'a> fmt::Display for TokensDisplay<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for token in self.0 { + write!(f, "{}", token)?; + } + Ok(()) + } + } + parser_err!(format!( + "Expected {}, found: {}\nNear \"{}\"", + expected, + found, + TokensDisplay(near_tokens), + )) } /// Look for an expected keyword and consume it if it exists diff --git a/src/sqlparser/tests/sqlparser_common.rs b/src/sqlparser/tests/sqlparser_common.rs index f0821fe87685c..b4c263252e0d9 100644 --- a/src/sqlparser/tests/sqlparser_common.rs +++ b/src/sqlparser/tests/sqlparser_common.rs @@ -126,16 +126,12 @@ fn parse_update() { let sql = "UPDATE t WHERE 1"; let res = parse_sql_statements(sql); - assert_eq!( - ParserError::ParserError("Expected SET, found: WHERE".to_string()), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()).contains("Expected SET, found: WHERE")); let sql = "UPDATE t SET a = 1 extrabadstuff"; let res = parse_sql_statements(sql); - assert_eq!( - ParserError::ParserError("Expected end of statement, found: extrabadstuff".to_string()), - res.unwrap_err() + assert!( + format!("{}", res.unwrap_err()).contains("Expected end of statement, found: extrabadstuff") ); } @@ -252,10 +248,7 @@ fn parse_select_all() { #[test] fn parse_select_all_distinct() { let result = parse_sql_statements("SELECT ALL DISTINCT name FROM customer"); - assert_eq!( - ParserError::ParserError("syntax error at or near \"DISTINCT\"".to_string()), - result.unwrap_err(), - ); + assert!(format!("{}", result.unwrap_err()).contains("syntax error at or near \"DISTINCT\"")); } #[test] @@ -283,10 +276,7 @@ fn parse_select_wildcard() { let sql = "SELECT * + * FROM foo;"; let result = parse_sql_statements(sql); - assert_eq!( - ParserError::ParserError("Expected end of statement, found: +".to_string()), - result.unwrap_err(), - ); + assert!(format!("{}", result.unwrap_err()).contains("Expected end of statement, found: +")); } #[test] @@ -323,16 +313,10 @@ fn parse_column_aliases() { #[test] fn test_eof_after_as() { let res = parse_sql_statements("SELECT foo AS"); - assert_eq!( - ParserError::ParserError("Expected an identifier after AS, found: EOF".to_string()), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()).contains("Expected an identifier after AS, found: EOF")); let res = parse_sql_statements("SELECT 1 FROM foo AS"); - assert_eq!( - ParserError::ParserError("Expected an identifier after AS, found: EOF".to_string()), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()).contains("Expected an identifier after AS, found: EOF")); } #[test] @@ -378,19 +362,13 @@ fn parse_select_count_distinct() { let sql = "SELECT COUNT(ALL DISTINCT + x) FROM customer"; let res = parse_sql_statements(sql); - assert_eq!( - ParserError::ParserError("Cannot specify both ALL and DISTINCT".to_string()), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()).contains("Cannot specify both ALL and DISTINCT")); } #[test] fn parse_invalid_infix_not() { let res = parse_sql_statements("SELECT c FROM t WHERE c NOT ("); - assert_eq!( - ParserError::ParserError("Expected end of statement, found: NOT".to_string()), - res.unwrap_err(), - ); + assert!(format!("{}", res.unwrap_err(),).contains("Expected end of statement, found: NOT")); } #[test] @@ -1191,10 +1169,7 @@ fn parse_extract() { verified_stmt("SELECT EXTRACT(SECOND FROM d)"); let res = parse_sql_statements("SELECT EXTRACT(0 FROM d)"); - assert_eq!( - ParserError::ParserError("Expected date/time field, found: 0".to_string()), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()).contains("Expected date/time field, found: 0")); } #[test] @@ -1707,18 +1682,12 @@ fn parse_alter_table_alter_column_type() { #[test] fn parse_bad_constraint() { let res = parse_sql_statements("ALTER TABLE tab ADD"); - assert_eq!( - ParserError::ParserError("Expected identifier, found: EOF".to_string()), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()).contains("Expected identifier, found: EOF")); let res = parse_sql_statements("CREATE TABLE tab (foo int,"); - assert_eq!( - ParserError::ParserError( - "Expected column name or constraint definition, found: EOF".to_string() - ), - res.unwrap_err() - ); + + assert!(format!("{}", res.unwrap_err()) + .contains("Expected column name or constraint definition, found: EOF")); } fn run_explain_analyze(query: &str, expected_analyze: bool, expected_options: ExplainOptions) { @@ -1821,22 +1790,16 @@ fn parse_explain_with_invalid_options() { assert!(res.is_err()); let res = parse_sql_statements("EXPLAIN (VERBOSE TRACE) SELECT sqrt(id) FROM foo"); - assert_eq!( - ParserError::ParserError("Expected ), found: TRACE".to_string()), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()).contains("Expected ), found: TRACE")); let res = parse_sql_statements("EXPLAIN () SELECT sqrt(id) FROM foo"); assert!(res.is_err()); let res = parse_sql_statements("EXPLAIN (VERBOSE, ) SELECT sqrt(id) FROM foo"); - assert_eq!( - ParserError::ParserError( - "Expected one of VERBOSE or TRACE or TYPE or LOGICAL or PHYSICAL or DISTSQL, found: )" - .to_string() - ), - res.unwrap_err() - ); + + let err_msg = + "Expected one of VERBOSE or TRACE or TYPE or LOGICAL or PHYSICAL or DISTSQL, found: )"; + assert!(format!("{}", res.unwrap_err()).contains(err_msg)); } #[test] @@ -2140,16 +2103,10 @@ fn parse_literal_interval() { ); let result = parse_sql_statements("SELECT INTERVAL '1' SECOND TO SECOND"); - assert_eq!( - ParserError::ParserError("Expected end of statement, found: SECOND".to_string()), - result.unwrap_err(), - ); + assert!(format!("{}", result.unwrap_err()).contains("Expected end of statement, found: SECOND")); let result = parse_sql_statements("SELECT INTERVAL '10' HOUR (1) TO HOUR (2)"); - assert_eq!( - ParserError::ParserError("Expected end of statement, found: (".to_string()), - result.unwrap_err(), - ); + assert!(format!("{}", result.unwrap_err()).contains("Expected end of statement, found: (")); verified_only_select("SELECT INTERVAL '1' YEAR"); verified_only_select("SELECT INTERVAL '1' MONTH"); @@ -2516,10 +2473,8 @@ fn parse_natural_join() { ); let sql = "SELECT * FROM t1 natural"; - assert_eq!( - ParserError::ParserError("Expected a join type after NATURAL, found: EOF".to_string()), - parse_sql_statements(sql).unwrap_err(), - ); + assert!(format!("{}", parse_sql_statements(sql).unwrap_err(),) + .contains("Expected a join type after NATURAL, found: EOF")); } #[test] @@ -2583,10 +2538,7 @@ fn parse_join_syntax_variants() { ); let res = parse_sql_statements("SELECT * FROM a OUTER JOIN b ON 1"); - assert_eq!( - ParserError::ParserError("Expected LEFT, RIGHT, or FULL, found: OUTER".to_string()), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()).contains("Expected LEFT, RIGHT, or FULL, found: OUTER")); } #[test] @@ -2775,10 +2727,8 @@ fn parse_multiple_statements() { one_statement_parses_to(&(sql1.to_owned() + ";"), sql1); // Check that forgetting the semicolon results in an error: let res = parse_sql_statements(&(sql1.to_owned() + " " + sql2_kw + sql2_rest)); - assert_eq!( - ParserError::ParserError("Expected end of statement, found: ".to_string() + sql2_kw), - res.unwrap_err() - ); + let err_msg = "Expected end of statement, found: "; + assert!(format!("{}", res.unwrap_err()).contains(err_msg)); } test_with("SELECT foo", "SELECT", " bar"); // ensure that SELECT/WITH is not parsed as a table or column alias if ';' @@ -2840,25 +2790,24 @@ fn parse_overlay() { "SELECT OVERLAY('abc' PLACING 'xyz' FROM 1 FOR 2)", ); - assert_eq!( - parse_sql_statements("SELECT OVERLAY('abc', 'xyz')").unwrap_err(), - ParserError::ParserError("Expected PLACING, found: ,".to_owned()) - ); - - assert_eq!( - parse_sql_statements("SELECT OVERLAY('abc' PLACING 'xyz')").unwrap_err(), - ParserError::ParserError("Expected FROM, found: )".to_owned()) - ); - - assert_eq!( - parse_sql_statements("SELECT OVERLAY('abc' PLACING 'xyz' FOR 2)").unwrap_err(), - ParserError::ParserError("Expected FROM, found: FOR".to_owned()) - ); - - assert_eq!( - parse_sql_statements("SELECT OVERLAY('abc' PLACING 'xyz' FOR 2 FROM 1)").unwrap_err(), - ParserError::ParserError("Expected FROM, found: FOR".to_owned()) - ); + for (sql, err_msg) in [ + ("SELECT OVERLAY('abc', 'xyz')", "Expected PLACING, found: ,"), + ( + "SELECT OVERLAY('abc' PLACING 'xyz')", + "Expected FROM, found: )", + ), + ( + "SELECT OVERLAY('abc' PLACING 'xyz' FOR 2)", + "Expected FROM, found: FOR", + ), + ( + "SELECT OVERLAY('abc' PLACING 'xyz' FOR 2 FROM 1)", + "Expected FROM, found: FOR", + ), + ] { + let res = parse_sql_statements(sql); + assert!(format!("{}", res.unwrap_err()).contains(err_msg)); + } } #[test] @@ -2880,10 +2829,10 @@ fn parse_trim() { one_statement_parses_to("SELECT TRIM(' foo ')", "SELECT TRIM(' foo ')"); - assert_eq!( - ParserError::ParserError("Expected ), found: 'xyz'".to_owned()), - parse_sql_statements("SELECT TRIM(FOO 'xyz' FROM 'xyzfooxyz')").unwrap_err() - ); + let res = parse_sql_statements("SELECT TRIM(FOO 'xyz' FROM 'xyzfooxyz')"); + + let err_msg = "Expected ), found: 'xyz'"; + assert!(format!("{}", res.unwrap_err()).contains(err_msg)); } #[test] @@ -2910,20 +2859,13 @@ fn parse_exists_subquery() { verified_stmt("SELECT EXISTS (SELECT 1)"); let res = parse_sql_statements("SELECT EXISTS ("); - assert_eq!( - ParserError::ParserError( - "Expected SELECT, VALUES, or a subquery in the query body, found: EOF".to_string() - ), - res.unwrap_err(), - ); + let err_msg = "Expected SELECT, VALUES, or a subquery in the query body, found: EOF"; + assert!(format!("{}", res.unwrap_err()).contains(err_msg)); let res = parse_sql_statements("SELECT EXISTS (NULL)"); - assert_eq!( - ParserError::ParserError( - "Expected SELECT, VALUES, or a subquery in the query body, found: NULL".to_string() - ), - res.unwrap_err(), - ); + + let err_msg = "Expected SELECT, VALUES, or a subquery in the query body, found: NULL"; + assert!(format!("{}", res.unwrap_err()).contains(err_msg)); } #[test] @@ -3162,16 +3104,12 @@ fn parse_drop_table() { }; let sql = "DROP TABLE"; - assert_eq!( - ParserError::ParserError("Expected identifier, found: EOF".to_string()), - parse_sql_statements(sql).unwrap_err(), - ); + assert!(format!("{}", parse_sql_statements(sql).unwrap_err(),) + .contains("Expected identifier, found: EOF")); let sql = "DROP TABLE IF EXISTS foo CASCADE RESTRICT"; - assert_eq!( - ParserError::ParserError("Expected end of statement, found: RESTRICT".to_string()), - parse_sql_statements(sql).unwrap_err(), - ); + assert!(format!("{}", parse_sql_statements(sql).unwrap_err(),) + .contains("Expected end of statement, found: RESTRICT")); } #[test] @@ -3232,10 +3170,7 @@ fn parse_create_user() { #[test] fn parse_invalid_subquery_without_parens() { let res = parse_sql_statements("SELECT SELECT 1 FROM bar WHERE 1=1 FROM baz"); - assert_eq!( - ParserError::ParserError("Expected end of statement, found: 1".to_string()), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()).contains("Expected end of statement, found: 1")); } #[test] @@ -3396,21 +3331,13 @@ fn lateral_derived() { let sql = "SELECT * FROM customer LEFT JOIN LATERAL generate_series(1, customer.id)"; let res = parse_sql_statements(sql); - assert_eq!( - ParserError::ParserError( - "Expected subquery after LATERAL, found: generate_series".to_string() - ), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()) + .contains("Expected subquery after LATERAL, found: generate_series")); let sql = "SELECT * FROM a LEFT JOIN LATERAL (b CROSS JOIN c)"; let res = parse_sql_statements(sql); - assert_eq!( - ParserError::ParserError( - "Expected SELECT, VALUES, or a subquery in the query body, found: b".to_string() - ), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()) + .contains("Expected SELECT, VALUES, or a subquery in the query body, found: b")); } #[test] @@ -3463,22 +3390,13 @@ fn parse_start_transaction() { ); let res = parse_sql_statements("START TRANSACTION ISOLATION LEVEL BAD"); - assert_eq!( - ParserError::ParserError("Expected isolation level, found: BAD".to_string()), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()).contains("Expected isolation level, found: BAD")); let res = parse_sql_statements("START TRANSACTION BAD"); - assert_eq!( - ParserError::ParserError("Expected end of statement, found: BAD".to_string()), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()).contains("Expected end of statement, found: BAD")); let res = parse_sql_statements("START TRANSACTION READ ONLY,"); - assert_eq!( - ParserError::ParserError("Expected transaction mode, found: EOF".to_string()), - res.unwrap_err() - ); + assert!(format!("{}", res.unwrap_err()).contains("Expected transaction mode, found: EOF")); } #[test] diff --git a/src/sqlparser/tests/sqlparser_postgres.rs b/src/sqlparser/tests/sqlparser_postgres.rs index f80ca930e2895..db6f06c9cb8a7 100644 --- a/src/sqlparser/tests/sqlparser_postgres.rs +++ b/src/sqlparser/tests/sqlparser_postgres.rs @@ -307,29 +307,27 @@ fn parse_create_table_if_not_exists() { #[test] fn parse_bad_if_not_exists() { - let res = parse_sql_statements("CREATE TABLE NOT EXISTS uk_cities ()"); - assert_eq!( - ParserError::ParserError("Expected end of statement, found: EXISTS".to_string()), - res.unwrap_err() - ); - - let res = parse_sql_statements("CREATE TABLE IF EXISTS uk_cities ()"); - assert_eq!( - ParserError::ParserError("Expected end of statement, found: EXISTS".to_string()), - res.unwrap_err() - ); - - let res = parse_sql_statements("CREATE TABLE IF uk_cities ()"); - assert_eq!( - ParserError::ParserError("Expected end of statement, found: uk_cities".to_string()), - res.unwrap_err() - ); - - let res = parse_sql_statements("CREATE TABLE IF NOT uk_cities ()"); - assert_eq!( - ParserError::ParserError("Expected end of statement, found: NOT".to_string()), - res.unwrap_err() - ); + for (sql, err_msg) in [ + ( + "CREATE TABLE NOT EXISTS uk_cities ()", + "Expected end of statement, found: EXISTS", + ), + ( + "CREATE TABLE IF EXISTS uk_cities ()", + "Expected end of statement, found: EXISTS", + ), + ( + "CREATE TABLE IF uk_cities ()", + "Expected end of statement, found: uk_cities", + ), + ( + "CREATE TABLE IF NOT uk_cities ()", + "Expected end of statement, found: NOT", + ), + ] { + let res = parse_sql_statements(sql); + assert!(format!("{}", res.unwrap_err()).contains(err_msg)); + } } #[test] @@ -438,27 +436,14 @@ fn parse_set() { one_statement_parses_to("SET a TO b", "SET a = b"); one_statement_parses_to("SET SESSION a = b", "SET a = b"); - - assert_eq!( - parse_sql_statements("SET"), - Err(ParserError::ParserError( - "Expected identifier, found: EOF".to_string() - )), - ); - - assert_eq!( - parse_sql_statements("SET a b"), - Err(ParserError::ParserError( - "Expected equals sign or TO, found: b".to_string() - )), - ); - - assert_eq!( - parse_sql_statements("SET a ="), - Err(ParserError::ParserError( - "Expected variable value, found: EOF".to_string() - )), - ); + for (sql, err_msg) in [ + ("SET", "Expected identifier, found: EOF"), + ("SET a b", "Expected equals sign or TO, found: b"), + ("SET a =", "Expected variable value, found: EOF"), + ] { + let res = parse_sql_statements(sql); + assert!(format!("{}", res.unwrap_err()).contains(err_msg)); + } } #[test] @@ -1042,12 +1027,9 @@ fn parse_array() { ); let sql = "SELECT [[1, 2], [3, 4]]"; - assert_eq!( - parse_sql_statements(sql), - Err(ParserError::ParserError( - "Expected an expression:, found: [".to_string() - )), - ); + let res = parse_sql_statements(sql); + let err_msg = "Expected an expression:, found: ["; + assert!(format!("{}", res.unwrap_err()).contains(err_msg)); } #[test] diff --git a/src/sqlparser/tests/testdata/array.yaml b/src/sqlparser/tests/testdata/array.yaml index f166818c21548..be97042cfa0c0 100644 --- a/src/sqlparser/tests/testdata/array.yaml +++ b/src/sqlparser/tests/testdata/array.yaml @@ -6,11 +6,17 @@ - input: CREATE TABLE t(a int[][][]); formatted_sql: CREATE TABLE t (a INT[][][]) - input: CREATE TABLE t(a int[); - error_msg: 'sql parser error: Expected ], found: )' + error_msg: |- + sql parser error: Expected ], found: ) + Near "CREATE TABLE t(a int[" - input: CREATE TABLE t(a int[[]); - error_msg: 'sql parser error: Expected ], found: [' + error_msg: |- + sql parser error: Expected ], found: [ + Near "CREATE TABLE t(a int[" - input: CREATE TABLE t(a int]); - error_msg: 'sql parser error: Expected '','' or '')'' after column definition, found: ]' + error_msg: |- + sql parser error: Expected ',' or ')' after column definition, found: ] + Near "CREATE TABLE t(a int" - input: SELECT foo[0] FROM foos formatted_sql: SELECT foo[0] FROM foos - input: SELECT foo[0][0] FROM foos diff --git a/src/sqlparser/tests/testdata/create.yaml b/src/sqlparser/tests/testdata/create.yaml index 9c8983a2293da..b3d573ad79ba3 100644 --- a/src/sqlparser/tests/testdata/create.yaml +++ b/src/sqlparser/tests/testdata/create.yaml @@ -16,7 +16,9 @@ - input: CREATE TABLE t (a INT, b INT) AS SELECT 1 AS b, 2 AS a formatted_sql: CREATE TABLE t (a INT, b INT) AS SELECT 1 AS b, 2 AS a - input: CREATE SOURCE src - error_msg: 'sql parser error: Expected ROW, found: EOF' + error_msg: |- + sql parser error: Expected ROW, found: EOF + Near "CREATE SOURCE src" - input: CREATE SOURCE src ROW FORMAT JSON formatted_sql: CREATE SOURCE src ROW FORMAT JSON - input: CREATE SOURCE IF NOT EXISTS src WITH (kafka.topic = 'abc', kafka.servers = 'localhost:1001') ROW FORMAT PROTOBUF MESSAGE 'Foo' ROW SCHEMA LOCATION 'file://' @@ -41,7 +43,9 @@ - input: CREATE USER user WITH SUPERUSER CREATEDB PASSWORD 'password' formatted_sql: CREATE USER user WITH SUPERUSER CREATEDB PASSWORD 'password' - input: CREATE SINK snk - error_msg: 'sql parser error: Expected FROM or AS after CREATE SINK sink_name, found: EOF' + error_msg: |- + sql parser error: Expected FROM or AS after CREATE SINK sink_name, found: EOF + Near "CREATE SINK snk" - input: CREATE SINK IF NOT EXISTS snk FROM mv WITH (connector = 'mysql', mysql.endpoint = '127.0.0.1:3306', mysql.table = '', mysql.database = '', mysql.user = '', mysql.password = '') formatted_sql: CREATE SINK IF NOT EXISTS snk FROM mv WITH (connector = 'mysql', mysql.endpoint = '127.0.0.1:3306', mysql.table = '', mysql.database = '', mysql.user = '', mysql.password = '') - input: CREATE SINK IF NOT EXISTS snk AS SELECT count(*) AS cnt FROM mv WITH (connector = 'mysql', mysql.endpoint = '127.0.0.1:3306', mysql.table = '', mysql.database = '', mysql.user = '', mysql.password = '') @@ -55,4 +59,6 @@ - input: create user tmp with encrypted password '' password null error_msg: 'sql parser error: conflicting or redundant options' - input: create user tmp with encrypted password null - error_msg: 'sql parser error: Expected literal string, found: null' + error_msg: |- + sql parser error: Expected literal string, found: null + Near " tmp with encrypted password null" diff --git a/src/sqlparser/tests/testdata/insert.yaml b/src/sqlparser/tests/testdata/insert.yaml index cb2f32526b81b..553d05052d4cb 100644 --- a/src/sqlparser/tests/testdata/insert.yaml +++ b/src/sqlparser/tests/testdata/insert.yaml @@ -1,5 +1,7 @@ # This file is automatically generated. See `src/sqlparser/test_runner/src/bin/apply.rs` for more information. - input: INSERT public.customer (id, name, active) VALUES (1, 2, 3) - error_msg: 'sql parser error: Expected INTO, found: public' + error_msg: |- + sql parser error: Expected INTO, found: public + Near "INSERT" - input: INSERT INTO t VALUES(1,3), (2,4) RETURNING *, a, a as aaa formatted_sql: INSERT INTO t VALUES (1, 3), (2, 4) RETURNING (*, a, a AS aaa) diff --git a/src/sqlparser/tests/testdata/select.yaml b/src/sqlparser/tests/testdata/select.yaml index 589b6baef5a2c..0c551cd4d7d73 100644 --- a/src/sqlparser/tests/testdata/select.yaml +++ b/src/sqlparser/tests/testdata/select.yaml @@ -42,9 +42,13 @@ - input: SELECT * FROM t FETCH FIRST ROWS WITH TIES error_msg: 'sql parser error: WITH TIES cannot be specified without ORDER BY clause' - input: select * from (select 1 from 1); - error_msg: 'sql parser error: Expected identifier, found: 1' + error_msg: |- + sql parser error: Expected identifier, found: 1 + Near "from (select 1 from 1" - input: select * from (select * from tumble(t, x, interval '10' minutes)) - error_msg: 'sql parser error: Expected ), found: minutes' + error_msg: |- + sql parser error: Expected ), found: minutes + Near "(t, x, interval '10'" - input: SELECT 1, FROM t error_msg: 'sql parser error: syntax error at or near "FROM"' - input: SELECT 1, WHERE true @@ -69,4 +73,6 @@ - input: SELECT 1::float(54) error_msg: 'sql parser error: precision for type float must be less than 54 bits' - input: SELECT 1::int(2) - error_msg: 'sql parser error: Expected end of statement, found: (' + error_msg: |- + sql parser error: Expected end of statement, found: ( + Near "SELECT 1::int"