-
Notifications
You must be signed in to change notification settings - Fork 14
Format LANGUAGE SQL function/procedure bodies #61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 1 commit
4e30fe6
c354f94
e3372f2
ae1bf5f
966121a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| import { Printer } from "prettier"; | ||
| import { CreateFunctionStmt, Node, StringLiteral } from "sql-parser-cst"; | ||
| import { | ||
| isAsClause, | ||
| isCreateFunctionStmt, | ||
| isLanguageClause, | ||
| isStringLiteral, | ||
| } from "./node_utils"; | ||
| import { hardline, indent, stripTrailingHardline } from "./print_utils"; | ||
|
|
||
| export const embedSql: NonNullable<Printer<Node>["embed"]> = (path, options) => { | ||
| const node = path.node; | ||
| const parent = path.getParentNode(0); | ||
| const grandParent = path.getParentNode(1); | ||
|
|
||
| if ( | ||
| isStringLiteral(node) && | ||
| isAsClause(parent) && | ||
| isCreateFunctionStmt(grandParent) && | ||
| grandParent.clauses.some(isSqlLanguageClause) | ||
| ) { | ||
| return async (textToDoc) => { | ||
| const quote = detectQuote(node); | ||
|
|
||
| if (quote) { | ||
| const sql = await textToDoc(node.value, options); | ||
|
|
||
| return [ | ||
| quote, | ||
| indent([hardline, stripTrailingHardline(sql)]), | ||
| hardline, | ||
| quote, | ||
| ]; | ||
| } | ||
| }; | ||
| } | ||
|
|
||
| return null; | ||
| }; | ||
|
|
||
| const isSqlLanguageClause = ( | ||
| clause: CreateFunctionStmt["clauses"][0], | ||
| ): boolean => isLanguageClause(clause) && clause.name.name === "sql"; | ||
|
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In PostgreSQL the language name is case-insensitive when unquoted. So However, that case-insensitivity only applies when the language name identifier is not quoted. So
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I was following the code in
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for the info. |
||
|
|
||
| const detectQuote = ( | ||
| node: StringLiteral, | ||
| ): string | undefined => { | ||
| const match = node.text.match(/^('|\$[^$]*\$)/); | ||
| const quote = match?.[1]; | ||
|
|
||
| if (quote && node.text.endsWith(quote)) { | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wen't with this version over
Owner
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There's no need to check both the start and end of the string to determine its quoting style. When the string starts with
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good to know. I presumed that this is handled by the parser and indicated that in my commit message but let me know if that's not the case and I'll change the commit message. Or ignore this if you squash commits when merging :) |
||
| return quote; | ||
| } | ||
|
|
||
| return undefined; | ||
| }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there an option that can be passed here to tell
textToDocto retain the string quoting whenquote === "'"?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Handling the escaped quotes properly is very hard to do and IMHO not worth the effort. We'd need to keep track which quotes were escaped in the original code and then re-escape them later. I don't even know from where to start with when solving this problem.
In practice one generally doesn't use single quotes for these SQL strings. At most one would for quoting a very simple SQL. If quotes are needed inside there, one generally just switches to another quoting style (like the dollar-quotes) instead of using escapes.
What I would suggest is:
$$ ... $$, which can't be done when the string already contains$$as substring).This is largely the approach taken inside
embedJs()function where strings are converted to eitherr''' ... '''orr""" ... """quoting style (specific to BigQuery).There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree completely!