File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -2,7 +2,8 @@ import { Printer } from "prettier";
22import { Node } from "sql-parser-cst" ;
33import { embedJs } from "./embedJs" ;
44import { embedJson } from "./embedJson" ;
5+ import { embedSql } from "./embedSql" ;
56
67export const embed : NonNullable < Printer < Node > [ "embed" ] > = ( ...args ) => {
7- return embedJson ( ...args ) || embedJs ( ...args ) ;
8+ return embedJson ( ...args ) || embedJs ( ...args ) || embedSql ( ... args ) ;
89} ;
Original file line number Diff line number Diff line change 1+ import { Printer } from "prettier" ;
2+ import { CreateFunctionStmt , Node , StringLiteral } from "sql-parser-cst" ;
3+ import {
4+ isAsClause ,
5+ isCreateFunctionStmt ,
6+ isLanguageClause ,
7+ isStringLiteral ,
8+ } from "./node_utils" ;
9+ import { hardline , indent , stripTrailingHardline } from "./print_utils" ;
10+
11+ export const embedSql : NonNullable < Printer < Node > [ "embed" ] > = ( path , options ) => {
12+ const node = path . node ;
13+ const parent = path . getParentNode ( 0 ) ;
14+ const grandParent = path . getParentNode ( 1 ) ;
15+
16+ if (
17+ isStringLiteral ( node ) &&
18+ isAsClause ( parent ) &&
19+ isCreateFunctionStmt ( grandParent ) &&
20+ grandParent . clauses . some ( isSqlLanguageClause )
21+ ) {
22+ return async ( textToDoc ) => {
23+ const quote = detectQuote ( node ) ;
24+
25+ if ( quote ) {
26+ const sql = await textToDoc ( node . value , options ) ;
27+
28+ return [
29+ quote ,
30+ indent ( [ hardline , stripTrailingHardline ( sql ) ] ) ,
31+ hardline ,
32+ quote ,
33+ ] ;
34+ }
35+ } ;
36+ }
37+
38+ return null ;
39+ } ;
40+
41+ const isSqlLanguageClause = (
42+ clause : CreateFunctionStmt [ "clauses" ] [ 0 ] ,
43+ ) : boolean => isLanguageClause ( clause ) && clause . name . name === "sql" ;
44+
45+ const detectQuote = (
46+ node : StringLiteral ,
47+ ) : string | undefined => {
48+ const match = node . text . match ( / ^ ( ' | \$ [ ^ $ ] * \$ ) / ) ;
49+ const quote = match ?. [ 1 ] ;
50+
51+ if ( quote && node . text . endsWith ( quote ) ) {
52+ return quote ;
53+ }
54+
55+ return undefined ;
56+ } ;
Original file line number Diff line number Diff line change @@ -202,6 +202,74 @@ describe("function", () => {
202202 AS " return /'''|\\"\\"\\"/.test(x) "
203203 ` ) ;
204204 } ) ;
205+
206+ it ( `formats dollar-quoted SQL function` , async ( ) => {
207+ await testPostgresql ( dedent `
208+ CREATE FUNCTION my_func()
209+ RETURNS INT64
210+ LANGUAGE sql
211+ AS $$
212+ SELECT 1;
213+ $$
214+ ` ) ;
215+ } ) ;
216+
217+ it ( `reformats SQL in dollar-quoted SQL function` , async ( ) => {
218+ expect (
219+ await pretty (
220+ dedent `
221+ CREATE FUNCTION my_func()
222+ RETURNS INT64
223+ LANGUAGE sql
224+ AS $body$SELECT 1;
225+ select 2$body$
226+ ` ,
227+ { dialect : "postgresql" } ,
228+ ) ,
229+ ) . toBe ( dedent `
230+ CREATE FUNCTION my_func()
231+ RETURNS INT64
232+ LANGUAGE sql
233+ AS $body$
234+ SELECT 1;
235+ SELECT 2;
236+ $body$
237+ ` ) ;
238+ } ) ;
239+
240+ it ( `formats single-quoted SQL function` , async ( ) => {
241+ await testPostgresql ( dedent `
242+ CREATE FUNCTION my_func()
243+ RETURNS TEXT
244+ LANGUAGE sql
245+ AS '
246+ SELECT ''foo'';
247+ '
248+ ` ) ;
249+ } ) ;
250+
251+ it ( `reformats SQL in single-quoted SQL function` , async ( ) => {
252+ expect (
253+ await pretty (
254+ dedent `
255+ CREATE FUNCTION my_func()
256+ RETURNS TEXT
257+ LANGUAGE sql
258+ AS 'SELECT ''foo'';
259+ select ''bar'''
260+ ` ,
261+ { dialect : "postgresql" } ,
262+ ) ,
263+ ) . toBe ( dedent `
264+ CREATE FUNCTION my_func()
265+ RETURNS TEXT
266+ LANGUAGE sql
267+ AS '
268+ SELECT ''foo'';
269+ SELECT ''bar'';
270+ '
271+ ` ) ;
272+ } ) ;
205273 } ) ;
206274
207275 describe ( "drop function" , ( ) => {
You can’t perform that action at this time.
0 commit comments