Releases: sbdchd/squawk
Parser Improvements & Fixes + Error Docs Hyperlinks
More Parser Validation + CI Hardening
v2.54.0 - 2026-05-24
Added
-
lexer: add parsing and erroring for num trailing suffix (#1159)
error[syntax-error]: trailing junk after numeric literal ╭▸ stdin:1:11 │ 1 │ SELECT 0x0y; ╰╴ ━ -
parser: warn about empty / invalid params & empty quoted idents (#1164)
error[syntax-error]: empty delimited identifier ╭▸ stdin:1:8 │ 1 │ select "", $, $2147483648 ╰╴ ━━ error[syntax-error]: missing parameter number ╭▸ stdin:1:12 │ 1 │ select "", $, $2147483648 ╰╴ ━ error[syntax-error]: parameter number too large ╭▸ stdin:1:15 │ 1 │ select "", $, $2147483648 ╰╴ ━━━━━━━━━━━ -
parser: warn about invalid octal/hex/binary digits (#1163)
error[syntax-error]: invalid digit for a base 2 literal ╭▸ stdin:1:12 │ 1 │ select 0b104, 0o7719, 0xg ╰╴ ━ error[syntax-error]: invalid digit for a base 8 literal ╭▸ stdin:1:20 │ 1 │ select 0b104, 0o7719, 0xg ╰╴ ━ error[syntax-error]: trailing junk after numeric literal ╭▸ stdin:1:25 │ 1 │ select 0b104, 0o7719, 0xg ╰╴ ━ -
parser: improve error reporting for malformed literals (#1162)
error[syntax-error]: trailing junk after positional parameter ╭▸ stdin:1:10 │ 1 │ SELECT $1a; ╰╴ ━instead of
error[syntax-error]: trailing junk after positional parameter ╭▸ stdin:1:10 │ 1 │ SELECT $1a; ╰╴ ━━━ -
parser: improve lexing numbers (#1161)
select .4;
now produces:
NUMERIC_NUMBER@7..9 ".4"instead of:
INT_NUMBER@7..9 ".4" -
ide: goto def for
t.c%type(#1161)create table t(a int, b text); -- ^ dest create function f(x t.a%type) returns s.t.b%type -- ^ source as $$ select 'hello'::text $$ language sql;
-
ide: find refs for types like
bit(#1153)create type pg_catalog.bit; -- ^^^ source create function pg_catalog.bit(bigint, integer) returns bit -- ^^^ ref language internal;
-
ide: add hover for string literals (#1155)
Now we decode the escape sequences for string literals on hover and show the
value up to the first new line. -
ide: improve numeric literal type inference (#1156)
select 2147483647; -- type: integer select 2147483648; -- type: bigint select 100000000000000000000000; -- type: numeric
-
fmt: literals & binary operators (#1169)
Format binary operators and literals.
-- before select TRUE and FALSE; select X'AF'; -- after select true and false; select x'AF';
-
fmt: unquote column aliases when possible (#1168)
-- before select 1 as "foo"; -- after select 1 as foo;
Changed
Fixed
- lexer: fix unicode escape string issue (#1158)
- vscode: update TextMate grammar to support other numeric literal kinds (#1157)
v2.53.0 - 2026-05-17
Added
Changed
Fixed
- install: fix windows npx install bug (#1140)
Fix NPX Windows Install + Parser Improvements
Fix NPM Package Publishing
Changed
Attempt to fix npm install method
Improved Parser Validation for Strings + Updated Install Method
Added
-
parser: validation for bit, byte, and escape string types (#1132)
select b'01' '10'; select x'0F' '10'; select e'foo' 'bar';
now gives:
error[syntax-error]: Expected new line or comma between string literals ╭▸ stdin:1:13 │ 1 │ select b'01' '10'; ╰╴ ━ error[syntax-error]: Expected new line or comma between string literals ╭▸ stdin:2:13 │ 2 │ select x'0F' '10'; ╰╴ ━ error[syntax-error]: Expected new line or comma between string literals ╭▸ stdin:3:14 │ 3 │ select e'foo' 'bar'; ╰╴ ━
-
parser: validation for escape sequences (#1125, #1123, #1122, #1128, #1129)
select U&'wrong: !061' UESCAPE '!'; select U&"wrong: \06" UESCAPE '\';
now gives:
error[syntax-error]: Unicode escape requires 4 hex digits: !XXXX ╭▸ stdin:1:20 │ 1 │ select U&'wrong: !061' UESCAPE '!'; ╰╴ ━━━━ error[syntax-error]: Unicode escape requires 4 hex digits: \XXXX ╭▸ stdin:2:20 │ 2 │ select U&"wrong: \06" UESCAPE '\'; ╰╴ ━━━
Changed
-
ci: update npm based install method (#1133)
Instead of fetching the binary via an install script we use an optional
peer dependency, mirroring ESBuild and Sentry.
Fixed
-
cli: fix missing binary exit code (#1130)
Before if the install script didn't run the NPM JS shim would exit without
erroring. Thanks @nwalters512! -
parser: parsing unicode escape idents in cast position (#1127)
select 2::U&"!0069!006E!0074!0038" UESCAPE '!' from t;
now parses without error
File Level Disable Comment For `assume_in_transaction`
v2.51.0 - 2026-05-06
Added
-
linter: add file-level override to disable
assume_in_transaction(#996). Thanks @reteps!When using
assume-in-transaction, you can disable it on a per file basis using a comment:-- squawk-disable-assume-in-transaction -
syntax: add validation for
select into(#1116)Warn about invalid usages, such as:
select 4 a union select 5 a into t;with t as (select 1 a into t) select * from t;select * from t where a in (select 1 a into t);
and more!
-
parser: add empty statement to ast (#1111)
; ; ;
now gives:
SOURCE_FILE@0..5 EMPTY_STMT@0..1 SEMICOLON@0..1 ";" WHITESPACE@1..2 "\n" EMPTY_STMT@2..3 SEMICOLON@2..3 ";" WHITESPACE@3..4 "\n" EMPTY_STMT@4..5 SEMICOLON@4..5 ";" -
ide: code actions create table as <-> select into + parser fix (#1113)
Create table and select into are roughly interchangable, so this code action
supports switching between. -
ide: show comments for types and columns (#1110)
Changed
- parser: cleanup insert & create rule ast grammar to be more strict (#1112)
Fixed
New Rules: Prefer Repack, Identifier Too Long, Require Concurrent Reindex, Require Concurrent Partition Detach + A Lexer Fix
Added
-
linter: new rule: prefer-repack (#1105)
repackisn't out yet, coming in PG19, but when it's out:-- instead of cluster foo; -- or vacuum full foo; -- use repack (concurrently) foo;
-
linter: new rule: require-concurrent-reindex (#1104)
-- instead of reindex table foo; -- use reindex table concurrently foo;
-
linter: new rule: require-concurrent-partition-detach (#1103)
-- instead of alter table t detach partition p; -- use alter table t detach partition p concurrently;
-
linter: new rule: identifier-too-long (#1102)
Postgres truncates identifiers that are too long, we now warn about this.
create table table_very_long_very_long_very_long_very_long_very_long_very_long (c bigint);
warning[identifier-too-long]: `table_very_long_very_long_very_long_very_long_very_long_very_long` is too long and will be truncated to 63 bytes. ╭▸ stdin:1:14 │ 1 │ create table table_very_long_very_long_very_long_very_long_very_long_very_long (c bigint); │ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ ╭╴ 1 - create table table_very_long_very_long_very_long_very_long_very_long_very_long (c bigint); 1 + create table table_very_long_very_long_very_long_very_long_very_long_very_lo (c bigint); ╰╴Thanks @subnix for coming up with this idea!
-
linter: parallel file checking (#1099)
We now check files in parallel using rayon, which gives a nice speed up of
22-55%. -
lexer/ide: fix lexing of non-ascii + fix case folding in goto def (#1101)
Previously we case folding all of the characters in our unquoted identifiers
including unicode. This differed from Postgres behavior which only folded ascii.Now we correctly error instead of resolving in the following:
with t as (select 1 Äpfel) select äpfel from t; -- ^ goto def no longer resolves
Additionally fixed a bug in the lexer where we weren't lexing unicode identifiers.
For example, the following now lexes:
with t as (select 1 🦀) select 🦀 from t;
Spring Cleaning + Some IDE Improvements
Added
-
ide: goto def for select into (#1086)
select 1 a into t; -- ^ 2. dest select a from t; -- ^ 1. goto def src
and
select 1 a into t; -- ^ 2. dest select a from t; -- ^ 1. goto def src
-
ide: goto def with view & qualified column (#1081)
create view v as select 1 id, 2 b; -- ^ 2. dest select v.id from v; -- ^ 1. goto def src
-
ide: goto def from graph_table to create property graph (#1077)
create property graph myshop vertex tables (t key (a) no properties); -- ^ 2. dest select 1 from graph_table (myshop -- ^ 1. goto def src match (n is t) columns (1 as x));
-
fmt: more work towards full select and create table support (#1079)
-- before create table t(a int,b text); -- after create table t( a int, b text );
-- before select array[[1,2],[3,4]]; -- after select array[[1, 2], [3, 4]];
Fixed
-
ide: fix shadowing cte column w/
*hover + func call syntax for cte & views (#1094)-- shadowing create table t(a int, b int); with t as ( select 1 ), -- yy overrides y since there's only 1 column in the * u(x, yy) as ( select *, 2 y, 3 z from t ) select y from u; -- ^ 1. goto def src - doesn't resolve because of override above
-- function call syntax for cte column with cte as (select 1 as a) -- ^ 2. dest select a(cte) from cte; -- ^ 1. goto def src
-- function call syntax for view column create view v as select 1 as a; -- ^ 2. dest select a(v) from v; -- ^ 1. goto def src
Internal
- ide/server/wasm: use salsa for binder caching (#1078)
- ide: cleanup goto def & find ref tests to prep for extension support (#1080)
- ide: split resolve into resolve/collect/ast_nav & dedupe code (#1085)
- ide: consolidate name helpers (#1090)
- ide: update return types in resolve_name_ref to use Location (#1089)
- ide: simplify hovering for names (#1088)
- ide: refactor hover & find refs to use goto_def (#1087)
- ide: refactor resolve and fix a couple edge cases (#1094)
- ide: refactor resolve to use name related functions (#1092)
- ide: refactor code actions into their own modules (#1091)
New Rule: require-table-schema + IDE & Parser Improvements
Added
-
linter: add require-table-schema rule (#1046, #1064, #1073). Thanks @Flaiers!
Note: this rule is disabled by default and must be enabled via the new
--includeflag.-- error create table posts(id bigint); -- okay create table public.posts(id bigint);
-
parser: improve error recovery for misplaced join clauses (#1065)
The following now gives a concise error message:
-- join after the where select * from t where x > 1 join k on true;
-
parser: support more statement kinds in create schema parsing (#1061)
-
ide: semantic syntax highlighting improvements (#1059, #1060, #1068)
We now highlight all the tokens in types. We were missing some like
setof.Additionally, we highlight names by their underlying kind i.e., table, function, column.
This is powered by goto def.You can't tell from GitHub's highlighting, but if you use the language
server, we now highlight thebint.bas a function:create table t(a int); create function b(t) returns int as 'select 1' language sql; select b(t), t.b from t;
-
ide: show function comment on hover (#1070)
-
ide: code action to rewrite between != and <> (#1066)
-
ide: goto def for create property graph (#1074)
Fixed
-
parser: fix param parsing (#1068)
Before,
double precisionwas parsed as a param nameddoublewith typeprecision.
Now it's parsed correctly as an unnamed param of typedouble precision.create function f(double precision) returns int8 as 'select $1' language sql;