Skip to content

Commit

Permalink
feat: support JSOX **stringified** paramTypes option (#301)
Browse files Browse the repository at this point in the history
close #233
close #277
close #279
  • Loading branch information
JounQin authored Nov 9, 2023
1 parent 254271c commit 841bc35
Show file tree
Hide file tree
Showing 15 changed files with 267 additions and 30 deletions.
2 changes: 1 addition & 1 deletion .changeset/config.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@
"linked": [],
"access": "restricted",
"baseBranch": "master",
"updateInternalDependencies": "minor",
"updateInternalDependencies": "patch",
"ignore": []
}
5 changes: 5 additions & 0 deletions .changeset/fuzzy-llamas-hang.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"prettier-plugin-sql": patch
---

feat: support `JSOX` **stringified** `paramTypes` option
2 changes: 1 addition & 1 deletion .codesandbox/ci.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"node": "16",
"node": "18",
"sandboxes": []
}
6 changes: 4 additions & 2 deletions .github/workflows/codeql.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ name: 'CodeQL'

on:
push:
branches: ['master']
branches:
- master
pull_request:
branches: ['master']
branches:
- master
schedule:
- cron: '22 11 * * 6'

Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/vercel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ jobs:
id: branch
if: ${{ github.ref == 'refs/heads/master' }}
run: |
echo "::set-output name=args::--prod"
echo "::set-output name=comment::false"
echo "args=--prod" >> $GITHUB_OUTPUT
echo "comment=false" >> $GITHUB_OUTPUT
- name: Deploy
uses: amondnet/vercel-action@v25
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"workspaces": [
"packages/*"
],
"packageManager": "pnpm@8.10.0",
"packageManager": "pnpm@8.10.2",
"scripts": {
"build": "run-p build:*",
"build:r": "r -f cjs",
Expand Down
4 changes: 3 additions & 1 deletion packages/sql/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
},
"types": "./lib/index.d.ts",
"files": [
"lib"
"lib",
"shim.d.ts"
],
"keywords": [
"sql",
Expand All @@ -44,6 +45,7 @@
"prettier": "^3.0.3"
},
"dependencies": {
"jsox": "^1.2.118",
"node-sql-parser": "^4.7.0",
"sql-formatter": "^12.2.4",
"tslib": "^2.6.0"
Expand Down
3 changes: 3 additions & 0 deletions packages/sql/shim.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
declare module 'jsox' {
export const JSOX: typeof JSON
}
33 changes: 20 additions & 13 deletions packages/sql/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
/// <reference path="../shim.d.ts" />

import { JSOX } from 'jsox'
import type { AST, Option } from 'node-sql-parser'
import nodeSqlParser from 'node-sql-parser'
import type { Options, ParserOptions, Plugin } from 'prettier'
import { format, type FormatOptions } from 'sql-formatter'
import { format, type FormatOptions, type ParamTypes } from 'sql-formatter'

import { languages } from './languages.js'

Expand All @@ -20,6 +23,7 @@ export type SqlBaseOptions = Option &
Partial<FormatOptions> & {
language?: string
formatter?: typeof NODE_SQL_PARSER | typeof SQL_FORMATTER
paramTypes?: string
}

export type SqlOptions = ParserOptions<AST> & SqlBaseOptions
Expand All @@ -42,12 +46,21 @@ const SqlPlugin: Plugin<AST | string> = {
},
printers: {
sql: {
print(path, { type, database, endOfLine, ...options }: SqlOptions) {
print(
path,
{ type, database, endOfLine, paramTypes, ...options }: SqlOptions,
) {
const value = path.node

let formatted =
typeof value === 'string'
? format(value, options)
? format(value, {
...options,
paramTypes:
paramTypes == null
? undefined
: (JSOX.parse(paramTypes) as ParamTypes),
})
: parser.sqlify(value, { type, database })

// It can never be `auto`
Expand Down Expand Up @@ -297,6 +310,7 @@ const SqlPlugin: Plugin<AST | string> = {
type: 'choice',
description:
'Specifies parameter values to fill in for placeholders inside SQL for `sql-formatter`. This option is designed to be used through API (though nothing really prevents usage from command line).',
// TODO: migrate to stringified JSOX instead
choices: [
{
value: Array,
Expand All @@ -309,7 +323,7 @@ const SqlPlugin: Plugin<AST | string> = {
'`Object` of name-value pairs for named (and indexed) placeholders',
},
],
// @ts-expect-error
// @ts-expect-error -- https://github.com/prettier/prettier/blob/953937dc63a8b37d2b7b7b6fc7f83a3201a716e9/src/main/normalize-options.js#L167
exception(value: unknown) {
return (
value == null ||
Expand All @@ -324,16 +338,9 @@ const SqlPlugin: Plugin<AST | string> = {
paramTypes: {
// since: '0.11.0',
category: 'Config',
type: 'choice',
type: 'string',
description:
'Specifies parameter types to support when parsing SQL prepared statements for `sql-formatter`.',
choices: [
{
value: Object,
description:
'Specifies parameter types to support when parsing SQL prepared statements.',
},
],
'Specifies `JSOX` **stringified** parameter types to support when parsing SQL prepared statements for `sql-formatter`.',
},
type: {
// since: '0.1.0',
Expand Down
183 changes: 183 additions & 0 deletions packages/sql/test/__snapshots__/fixtures.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,189 @@ WITH
"
`;

exports[`parser and printer > should format all fixtures > 233.sql 1`] = `
"CREATE TABLE
\\"test\\" (\\"id\\" uuid NOT NULL)
WITH
(oids = false);
"
`;

exports[`parser and printer > should format all fixtures > 277.sql 1`] = `
[Error: Parse error at token: {table_name} at line 1 column 77
Unexpected CUSTOM_PARAMETER token: {"type":"CUSTOM_PARAMETER","raw":"{table_name}","text":"{table_name}","start":76,"key":"{table_name}"}. Instead, I was expecting to see one of the following:
A LINE_COMMENT token based on:
comment → ● %LINE_COMMENT
_$ebnf$1 → _$ebnf$1 ● comment
_ → ● _$ebnf$1
property_access → expression _ %DOT ● _ property_access$subexpression$1
asteriskless_andless_expression$subexpression$1 → ● property_access
asteriskless_andless_expression → ● asteriskless_andless_expression$subexpression$1
asteriskless_free_form_sql$subexpression$1 → ● asteriskless_andless_expression
asteriskless_free_form_sql → ● asteriskless_free_form_sql$subexpression$1
free_form_sql$subexpression$1 → ● asteriskless_free_form_sql
free_form_sql → ● free_form_sql$subexpression$1
other_clause$ebnf$1 → other_clause$ebnf$1 ● free_form_sql
other_clause → %RESERVED_CLAUSE ● other_clause$ebnf$1
clause$subexpression$1 → ● other_clause
clause → ● clause$subexpression$1
expressions_or_clauses$ebnf$2 → expressions_or_clauses$ebnf$2 ● clause
expressions_or_clauses → expressions_or_clauses$ebnf$1 ● expressions_or_clauses$ebnf$2
statement → ● expressions_or_clauses statement$subexpression$1
main$ebnf$1 → main$ebnf$1 ● statement
main → ● main$ebnf$1
A BLOCK_COMMENT token based on:
comment → ● %BLOCK_COMMENT
_$ebnf$1 → _$ebnf$1 ● comment
_ → ● _$ebnf$1
property_access → expression _ %DOT ● _ property_access$subexpression$1
asteriskless_andless_expression$subexpression$1 → ● property_access
asteriskless_andless_expression → ● asteriskless_andless_expression$subexpression$1
asteriskless_free_form_sql$subexpression$1 → ● asteriskless_andless_expression
asteriskless_free_form_sql → ● asteriskless_free_form_sql$subexpression$1
free_form_sql$subexpression$1 → ● asteriskless_free_form_sql
free_form_sql → ● free_form_sql$subexpression$1
other_clause$ebnf$1 → other_clause$ebnf$1 ● free_form_sql
other_clause → %RESERVED_CLAUSE ● other_clause$ebnf$1
clause$subexpression$1 → ● other_clause
clause → ● clause$subexpression$1
expressions_or_clauses$ebnf$2 → expressions_or_clauses$ebnf$2 ● clause
expressions_or_clauses → expressions_or_clauses$ebnf$1 ● expressions_or_clauses$ebnf$2
statement → ● expressions_or_clauses statement$subexpression$1
main$ebnf$1 → main$ebnf$1 ● statement
main → ● main$ebnf$1
A ARRAY_IDENTIFIER token based on:
array_subscript → ● %ARRAY_IDENTIFIER _ square_brackets
property_access$subexpression$1 → ● array_subscript
property_access → expression _ %DOT _ ● property_access$subexpression$1
asteriskless_andless_expression$subexpression$1 → ● property_access
asteriskless_andless_expression → ● asteriskless_andless_expression$subexpression$1
asteriskless_free_form_sql$subexpression$1 → ● asteriskless_andless_expression
asteriskless_free_form_sql → ● asteriskless_free_form_sql$subexpression$1
free_form_sql$subexpression$1 → ● asteriskless_free_form_sql
free_form_sql → ● free_form_sql$subexpression$1
other_clause$ebnf$1 → other_clause$ebnf$1 ● free_form_sql
other_clause → %RESERVED_CLAUSE ● other_clause$ebnf$1
clause$subexpression$1 → ● other_clause
clause → ● clause$subexpression$1
expressions_or_clauses$ebnf$2 → expressions_or_clauses$ebnf$2 ● clause
expressions_or_clauses → expressions_or_clauses$ebnf$1 ● expressions_or_clauses$ebnf$2
statement → ● expressions_or_clauses statement$subexpression$1
main$ebnf$1 → main$ebnf$1 ● statement
main → ● main$ebnf$1
A ARRAY_KEYWORD token based on:
array_subscript → ● %ARRAY_KEYWORD _ square_brackets
property_access$subexpression$1 → ● array_subscript
property_access → expression _ %DOT _ ● property_access$subexpression$1
asteriskless_andless_expression$subexpression$1 → ● property_access
asteriskless_andless_expression → ● asteriskless_andless_expression$subexpression$1
asteriskless_free_form_sql$subexpression$1 → ● asteriskless_andless_expression
asteriskless_free_form_sql → ● asteriskless_free_form_sql$subexpression$1
free_form_sql$subexpression$1 → ● asteriskless_free_form_sql
free_form_sql → ● free_form_sql$subexpression$1
other_clause$ebnf$1 → other_clause$ebnf$1 ● free_form_sql
other_clause → %RESERVED_CLAUSE ● other_clause$ebnf$1
clause$subexpression$1 → ● other_clause
clause → ● clause$subexpression$1
expressions_or_clauses$ebnf$2 → expressions_or_clauses$ebnf$2 ● clause
expressions_or_clauses → expressions_or_clauses$ebnf$1 ● expressions_or_clauses$ebnf$2
statement → ● expressions_or_clauses statement$subexpression$1
main$ebnf$1 → main$ebnf$1 ● statement
main → ● main$ebnf$1
A ASTERISK token based on:
all_columns_asterisk → ● %ASTERISK
property_access$subexpression$1 → ● all_columns_asterisk
property_access → expression _ %DOT _ ● property_access$subexpression$1
asteriskless_andless_expression$subexpression$1 → ● property_access
asteriskless_andless_expression → ● asteriskless_andless_expression$subexpression$1
asteriskless_free_form_sql$subexpression$1 → ● asteriskless_andless_expression
asteriskless_free_form_sql → ● asteriskless_free_form_sql$subexpression$1
free_form_sql$subexpression$1 → ● asteriskless_free_form_sql
free_form_sql → ● free_form_sql$subexpression$1
other_clause$ebnf$1 → other_clause$ebnf$1 ● free_form_sql
other_clause → %RESERVED_CLAUSE ● other_clause$ebnf$1
clause$subexpression$1 → ● other_clause
clause → ● clause$subexpression$1
expressions_or_clauses$ebnf$2 → expressions_or_clauses$ebnf$2 ● clause
expressions_or_clauses → expressions_or_clauses$ebnf$1 ● expressions_or_clauses$ebnf$2
statement → ● expressions_or_clauses statement$subexpression$1
main$ebnf$1 → main$ebnf$1 ● statement
main → ● main$ebnf$1
A IDENTIFIER token based on:
identifier$subexpression$1 → ● %IDENTIFIER
identifier → ● identifier$subexpression$1
property_access$subexpression$1 → ● identifier
property_access → expression _ %DOT _ ● property_access$subexpression$1
asteriskless_andless_expression$subexpression$1 → ● property_access
asteriskless_andless_expression → ● asteriskless_andless_expression$subexpression$1
asteriskless_free_form_sql$subexpression$1 → ● asteriskless_andless_expression
asteriskless_free_form_sql → ● asteriskless_free_form_sql$subexpression$1
free_form_sql$subexpression$1 → ● asteriskless_free_form_sql
free_form_sql → ● free_form_sql$subexpression$1
other_clause$ebnf$1 → other_clause$ebnf$1 ● free_form_sql
other_clause → %RESERVED_CLAUSE ● other_clause$ebnf$1
clause$subexpression$1 → ● other_clause
clause → ● clause$subexpression$1
expressions_or_clauses$ebnf$2 → expressions_or_clauses$ebnf$2 ● clause
expressions_or_clauses → expressions_or_clauses$ebnf$1 ● expressions_or_clauses$ebnf$2
statement → ● expressions_or_clauses statement$subexpression$1
main$ebnf$1 → main$ebnf$1 ● statement
main → ● main$ebnf$1
A QUOTED_IDENTIFIER token based on:
identifier$subexpression$1 → ● %QUOTED_IDENTIFIER
identifier → ● identifier$subexpression$1
property_access$subexpression$1 → ● identifier
property_access → expression _ %DOT _ ● property_access$subexpression$1
asteriskless_andless_expression$subexpression$1 → ● property_access
asteriskless_andless_expression → ● asteriskless_andless_expression$subexpression$1
asteriskless_free_form_sql$subexpression$1 → ● asteriskless_andless_expression
asteriskless_free_form_sql → ● asteriskless_free_form_sql$subexpression$1
free_form_sql$subexpression$1 → ● asteriskless_free_form_sql
free_form_sql → ● free_form_sql$subexpression$1
other_clause$ebnf$1 → other_clause$ebnf$1 ● free_form_sql
other_clause → %RESERVED_CLAUSE ● other_clause$ebnf$1
clause$subexpression$1 → ● other_clause
clause → ● clause$subexpression$1
expressions_or_clauses$ebnf$2 → expressions_or_clauses$ebnf$2 ● clause
expressions_or_clauses → expressions_or_clauses$ebnf$1 ● expressions_or_clauses$ebnf$2
statement → ● expressions_or_clauses statement$subexpression$1
main$ebnf$1 → main$ebnf$1 ● statement
main → ● main$ebnf$1
A VARIABLE token based on:
identifier$subexpression$1 → ● %VARIABLE
identifier → ● identifier$subexpression$1
property_access$subexpression$1 → ● identifier
property_access → expression _ %DOT _ ● property_access$subexpression$1
asteriskless_andless_expression$subexpression$1 → ● property_access
asteriskless_andless_expression → ● asteriskless_andless_expression$subexpression$1
asteriskless_free_form_sql$subexpression$1 → ● asteriskless_andless_expression
asteriskless_free_form_sql → ● asteriskless_free_form_sql$subexpression$1
free_form_sql$subexpression$1 → ● asteriskless_free_form_sql
free_form_sql → ● free_form_sql$subexpression$1
other_clause$ebnf$1 → other_clause$ebnf$1 ● free_form_sql
other_clause → %RESERVED_CLAUSE ● other_clause$ebnf$1
clause$subexpression$1 → ● other_clause
clause → ● clause$subexpression$1
expressions_or_clauses$ebnf$2 → expressions_or_clauses$ebnf$2 ● clause
expressions_or_clauses → expressions_or_clauses$ebnf$1 ● expressions_or_clauses$ebnf$2
statement → ● expressions_or_clauses statement$subexpression$1
main$ebnf$1 → main$ebnf$1 ● statement
main → ● main$ebnf$1
]
`;

exports[`parser and printer > should format all fixtures > 279.sql 1`] = `
"-- create db
CREATE DATABASE test_db;
-- connect test_db
\\\\c test_db
-- create schema
CREATE SCHEMA test;
"
`;

exports[`parser and printer > should format all fixtures > basic.sql 1`] = `
"-- this is a comment
SELECT
Expand Down
Loading

0 comments on commit 841bc35

Please sign in to comment.