Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/squawk_linter/src/rules/prefer_text_field.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ fn is_not_allowed_varchar(ty: &ast::Type) -> bool {
ast::Type::DoubleType(_) => false,
ast::Type::TimeType(_) => false,
ast::Type::IntervalType(_) => false,
ast::Type::ExprType(_) => false,
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/squawk_linter/src/rules/prefer_timestamptz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ pub fn is_not_allowed_timestamp(ty: &ast::Type) -> bool {
false
}
ast::Type::IntervalType(_) => false,
ast::Type::ExprType(_) => false,
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/squawk_linter/src/visitors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ pub(crate) fn is_not_valid_int_type(
ast::Type::DoubleType(_) => false,
ast::Type::TimeType(_) => false,
ast::Type::IntervalType(_) => false,
ast::Type::ExprType(_) => false,
}
}

Expand Down
1 change: 1 addition & 0 deletions crates/squawk_parser/src/generated/syntax_kind.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 51 additions & 17 deletions crates/squawk_parser/src/grammar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2017,7 +2017,18 @@ fn name_ref_(p: &mut Parser<'_>) -> Option<CompletedMarker> {
// A type name followed by a string is a type cast so we insert a CAST_EXPR
// preceding it to wrap the previously parsed data.
// e.g., `select numeric '12312'`
if opt_string_literal(p).is_some() {
if p.at_ts(STRING_FIRST) {
// Wrap expr in type.
// TODO: can we unify types & exprs?
let cm = if kind == NAME_REF {
let path_segment = cm.precede(p).complete(p, PATH_SEGMENT);
let path = path_segment.precede(p).complete(p, PATH);
path.precede(p).complete(p, PATH_TYPE)
} else {
cm
};

string_literal(p);
if kind == INTERVAL_TYPE {
opt_interval_trailing(p);
}
Expand Down Expand Up @@ -2045,11 +2056,18 @@ fn between_expr(p: &mut Parser<'_>) -> CompletedMarker {

fn call_expr_args(p: &mut Parser<'_>, lhs: CompletedMarker) -> CompletedMarker {
assert!(p.at(L_PAREN));
let prev_kind = lhs.kind();
let m = lhs.precede(p);
arg_list(p);
opt_agg_clauses(p);
let cm = m.complete(p, CALL_EXPR);
if opt_string_literal(p).is_some() {
let mut cm = m.complete(p, CALL_EXPR);
if p.at_ts(STRING_FIRST) {
// Wrap expr in type.
// TODO: can we unify types & exprs?
if prev_kind == FIELD_EXPR {
cm = cm.precede(p).complete(p, EXPR_TYPE);
}
string_literal(p);
cm.precede(p).complete(p, CAST_EXPR)
} else {
cm
Expand Down Expand Up @@ -2199,9 +2217,13 @@ fn postfix_dot_expr(
) -> Result<CompletedMarker, CompletedMarker> {
assert!(p.at(DOT));
field_expr(p, Some(lhs), allow_calls).map(|cm| {
// A field followed by a literal is a type cast so we insert a CAST_EXPR
// preceding it to wrap the previously parsed data.
if opt_string_literal(p).is_some() {
if p.at_ts(STRING_FIRST) {
// wrap our previous expression in a type
// TODO: can we unify types & exprs?
let cm = cm.precede(p).complete(p, EXPR_TYPE);
string_literal(p);
// A field followed by a literal is a type cast so we insert a CAST_EXPR
// preceding it to wrap the previously parsed data.
cm.precede(p).complete(p, CAST_EXPR)
} else {
cm
Expand Down Expand Up @@ -2433,17 +2455,29 @@ fn expr_bp(p: &mut Parser<'_>, bp: u8, r: &Restrictions) -> Option<CompletedMark
Associativity::Left => op_bp + 1,
Associativity::Right => op_bp,
};
let _ = expr_bp(p, op_bp, r);
lhs = m.complete(
p,
if matches!(op, COLON_COLON) {
CAST_EXPR
} else if matches!(op, FAT_ARROW | COLON_EQ) {
NAMED_ARG
} else {
BIN_EXPR
},
);
let rhs = expr_bp(p, op_bp, r);
lhs = if matches!(op, COLON_COLON) {
if let Some(rhs) = rhs {
match rhs.kind() {
NAME_REF => {
// wrap our previous expression in a type
// TODO: can we unify types & exprs?
let path_segment = rhs.precede(p).complete(p, PATH_SEGMENT);
let path = path_segment.precede(p).complete(p, PATH);
path.precede(p).complete(p, PATH_TYPE);
}
FIELD_EXPR | CALL_EXPR | INDEX_EXPR => {
rhs.precede(p).complete(p, EXPR_TYPE);
}
_ => {}
}
};
m.complete(p, CAST_EXPR)
} else if matches!(op, FAT_ARROW | COLON_EQ) {
m.complete(p, NAMED_ARG)
} else {
m.complete(p, BIN_EXPR)
};
}
Some(lhs)
}
Expand Down
4 changes: 4 additions & 0 deletions crates/squawk_parser/tests/data/ok/select_casts.sql
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ select int8('1234');
select 44::bit(3);
select cast(-44 as bit(12));
select '1110'::bit(4)::integer;
select '{1}'::pg_catalog.varchar(1)[];

select '{1,2,3}'::int[];
select foo::int;
Expand Down Expand Up @@ -206,6 +207,8 @@ select '{1}'::pg_catalog.int8[];

-- cast
select cast(a as foo.bar);
select cast('{1}' as pg_catalog.varchar(1)[]);


-- treat
select treat(a as foo.b);
Expand Down Expand Up @@ -268,3 +271,4 @@ select boolean 'false';

select foo.bar '100';
select foo.bar(10, 2) '100';
select pg_catalog.varchar(100) '{123}';
Original file line number Diff line number Diff line change
Expand Up @@ -46,8 +46,11 @@ SOURCE_FILE
TARGET_LIST
TARGET
CAST_EXPR
NAME_REF
TEXT_KW "text"
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
TEXT_KW "text"
WHITESPACE " "
LITERAL
STRING "'Hello World'"
Expand Down
14 changes: 10 additions & 4 deletions crates/squawk_parser/tests/snapshots/tests__explain_ok.snap
Original file line number Diff line number Diff line change
Expand Up @@ -538,8 +538,11 @@ SOURCE_FILE
COLON_COLON
COLON ":"
COLON ":"
NAME_REF
INTEGER_KW "integer"
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
INTEGER_KW "integer"
WHITESPACE " "
AND_KW "AND"
WHITESPACE " "
Expand All @@ -555,8 +558,11 @@ SOURCE_FILE
COLON_COLON
COLON ":"
COLON ":"
NAME_REF
INTEGER_KW "integer"
PATH_TYPE
PATH
PATH_SEGMENT
NAME_REF
INTEGER_KW "integer"
WHITESPACE "\n "
GROUP_BY_CLAUSE
GROUP_KW "GROUP"
Expand Down
Loading
Loading