pgsql-ast-parser
Advanced tools
Comparing version 4.1.13 to 4.2.0
@@ -9,2 +9,4 @@ import * as a from './syntax/ast'; | ||
comment?: (val: a.CommentStatement) => a.Statement | nil; | ||
do?: (val: a.DoStatement) => a.Statement | nil; | ||
createFunction?: (val: a.CreateFunctionStatement) => a.Statement | nil; | ||
raise?: (val: a.RaiseStatement) => a.Statement | nil; | ||
@@ -132,2 +134,4 @@ createSchema?: (val: a.CreateSchemaStatement) => a.Statement | nil; | ||
createMaterializedView(val: a.CreateMaterializedViewStatement): a.Statement | nil; | ||
do(val: a.DoStatement): a.Statement | nil; | ||
createFunction(val: a.CreateFunctionStatement): a.Statement | nil; | ||
show(val: a.ShowStatement): a.Statement | nil; | ||
@@ -134,0 +138,0 @@ createEnum(val: a.CreateEnumType): a.Statement | nil; |
{ | ||
"name": "pgsql-ast-parser", | ||
"version": "4.1.13", | ||
"version": "4.2.0", | ||
"description": "Yet another simple Postgres SQL parser/modifier", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -12,2 +12,4 @@ import * as a from './syntax/ast'; | ||
comment?: (val: a.CommentStatement) => a.Statement | nil | ||
do?: (val: a.DoStatement) => a.Statement | nil | ||
createFunction?: (val: a.CreateFunctionStatement) => a.Statement | nil | ||
raise?: (val: a.RaiseStatement) => a.Statement | nil | ||
@@ -259,2 +261,6 @@ createSchema?: (val: a.CreateSchemaStatement) => a.Statement | nil | ||
return this.comment(val); | ||
case 'do': | ||
return this.do(val); | ||
case 'create function': | ||
return this.createFunction(val); | ||
default: | ||
@@ -300,2 +306,41 @@ throw NotSupported.never(val); | ||
do(val: a.DoStatement): a.Statement | nil { | ||
return val; | ||
} | ||
createFunction(val: a.CreateFunctionStatement): a.Statement | nil { | ||
// process arguments | ||
const args = arrayNilMap(val.arguments, a => { | ||
const type = this.dataType(a.type); | ||
return assignChanged(a, { type }); | ||
}); | ||
// process return type | ||
let returns: typeof val.returns; | ||
if (val.returns) { | ||
switch (val.returns.kind) { | ||
case 'table': | ||
returns = assignChanged(val.returns, { | ||
columns: arrayNilMap(val.returns.columns, v => { | ||
const type = this.dataType(v.type); | ||
return type && assignChanged(v, { type }) | ||
}) | ||
}); | ||
break; | ||
case undefined: | ||
case null: | ||
case 'array': | ||
returns = this.dataType(val.returns); | ||
break; | ||
default: | ||
throw NotSupported.never(val.returns); | ||
} | ||
} | ||
return assignChanged(val, { | ||
returns, | ||
arguments: args, | ||
}); | ||
} | ||
show(val: a.ShowStatement): a.Statement | nil { | ||
@@ -302,0 +347,0 @@ return val; |
@@ -14,2 +14,3 @@ import 'mocha'; | ||
/^float$/, | ||
/^codeblock$/, | ||
] | ||
@@ -152,2 +153,16 @@ function next(expected: any) { | ||
}) | ||
it ('tokenizes code block', () => { | ||
lexer.reset(`before $$ code $ block $$ after`); | ||
next({ type: 'word', value: 'before' }); | ||
next({ type: 'codeblock', value: ' code $ block ' }); | ||
next({ type: 'word', value: 'after' }); | ||
}) | ||
it ('tokenizes multiline code block', () => { | ||
const multi = `code | ||
block`; | ||
lexer.reset(`$$${multi}$$`); | ||
next({ type: 'codeblock', value: multi }); | ||
}) | ||
}); |
@@ -1,2 +0,2 @@ | ||
import {compile, keywords} from 'moo'; | ||
import { compile, keywords } from 'moo'; | ||
import { sqlKeywords } from './keywords'; | ||
@@ -87,2 +87,7 @@ export { LOCATION } from './syntax/ast'; | ||
}, | ||
codeblock: { | ||
match: /\$\$(?:.|[\s\t\n\v\f\r])*\$\$/s, | ||
lineBreaks: true, | ||
value: (x: string) => x.substr(2, x.length - 4), | ||
}, | ||
}); | ||
@@ -89,0 +94,0 @@ |
@@ -34,2 +34,4 @@ // import { IType } from '../../interfaces'; | ||
| RaiseStatement | ||
| CreateFunctionStatement | ||
| DoStatement | ||
| StartTransactionStatement) & { | ||
@@ -40,2 +42,34 @@ [LOCATION]?: StatementLocation; | ||
export interface DoStatement { | ||
type: 'do'; | ||
language?: string; | ||
code: string; | ||
} | ||
export interface CreateFunctionStatement extends QName { | ||
type: 'create function'; | ||
code: string; | ||
orReplace?: boolean; | ||
language?: string; | ||
arguments: FunctionArgument[]; | ||
returns?: DataTypeDef | ReturnsTable; | ||
purity?: 'immutable' | 'stable' | 'volatile'; | ||
leakproof?: boolean; | ||
onNullInput?: 'call' | 'null' | 'strict'; | ||
} | ||
export interface ReturnsTable { | ||
kind: 'table'; | ||
columns: { name: string; type: DataTypeDef }[]; | ||
} | ||
export type FunctionArgumentMode = 'in' | 'out' | 'inout' | 'variadic'; | ||
export interface FunctionArgument { | ||
name?: string; | ||
type: DataTypeDef; | ||
default?: Expr; | ||
mode?: FunctionArgumentMode; | ||
} | ||
export interface CommentStatement { | ||
@@ -337,2 +371,3 @@ type: 'comment'; | ||
constraints?: TableConstraint[]; | ||
inherits?: QName[]; | ||
} | ||
@@ -339,0 +374,0 @@ |
@@ -28,2 +28,21 @@ import 'mocha'; | ||
checkCreateTable(`CREATE TABLE capitals ( | ||
state char(2) | ||
) INHERITS (cities)`, { | ||
type: 'create table', | ||
name: 'capitals', | ||
columns: [{ name: 'state', dataType: { name: 'char', config: [2] } }], | ||
inherits: [{ name: 'cities' }], | ||
}); | ||
checkCreateTable(`CREATE TABLE capitals ( | ||
state char(2) | ||
) INHERITS (global.cities, named)`, { | ||
type: 'create table', | ||
name: 'capitals', | ||
columns: [{ name: 'state', dataType: { name: 'char', config: [2] } }], | ||
inherits: [{ name: 'cities', schema: 'global' }, { name: 'named' }], | ||
}); | ||
checkCreateTable(['create table test(value pg_catalog.varchar(12))'], { | ||
@@ -30,0 +49,0 @@ type: 'create table', |
@@ -432,3 +432,3 @@ import { IAstPartialMapper, AstDefaultMapper } from './ast-mapper'; | ||
} | ||
ret.push(' IS ', literal(c.comment),' '); | ||
ret.push(' IS ', literal(c.comment), ' '); | ||
}, | ||
@@ -547,2 +547,77 @@ | ||
do: d => { | ||
ret.push('DO'); | ||
if (d.language) { | ||
ret.push(' LANGUAGE ', d.language); | ||
} | ||
ret.push(' $$', d.code, '$$'); | ||
}, | ||
createFunction: c => { | ||
ret.push(c.orReplace ? 'CREATE OR REPLACE FUNCTION ' : 'CREATE FUNCTION '); | ||
visitQualifiedName(c); | ||
// args | ||
list(c.arguments, a => { | ||
if (a.mode) { | ||
ret.push(a.mode, ' '); | ||
} | ||
if (a.name) { | ||
ret.push(name(a.name), ' '); | ||
} | ||
m.dataType(a.type); | ||
}, true); | ||
// ret type | ||
if (c.returns) { | ||
switch (c.returns.kind) { | ||
case 'table': | ||
ret.push(' RETURNS TABLE '); | ||
list(c.returns.columns, t => { | ||
ret.push(name(t.name), ' '); | ||
m.dataType(t.type); | ||
}, true); | ||
break; | ||
case undefined: | ||
case null: | ||
case 'array': | ||
ret.push(' RETURNS '); | ||
m.dataType(c.returns); | ||
break; | ||
default: | ||
throw NotSupported.never(c.returns); | ||
} | ||
} | ||
ret.push(' AS $$', c.code, '$$'); | ||
// function settings | ||
if (c.language) { | ||
ret.push('LANGUAGE ', c.language, ' '); | ||
} | ||
if (c.purity) { | ||
ret.push(c.purity.toUpperCase(), ' '); | ||
} | ||
if (typeof c.leakproof === 'boolean') { | ||
ret.push(c.leakproof ? 'LEAKPROOF ' : 'NOT LEAKPROOF '); | ||
} | ||
switch (c.onNullInput) { | ||
case 'call': | ||
ret.push('CALLED ON NULL INPUT '); | ||
break; | ||
case 'null': | ||
ret.push('RETURNS NULL ON NULL INPUT '); | ||
break; | ||
case 'strict': | ||
ret.push('STRICT '); | ||
break; | ||
case null: | ||
case undefined: | ||
break; | ||
default: | ||
throw NotSupported.never(c.onNullInput); | ||
} | ||
}, | ||
with: w => { | ||
@@ -648,3 +723,7 @@ ret.push('WITH '); | ||
} | ||
ret.push(')'); | ||
ret.push(') '); | ||
if (t.inherits?.length) { | ||
ret.push(' INHERITS '); | ||
list(t.inherits, i => visitQualifiedName(i), true); | ||
} | ||
}, | ||
@@ -692,3 +771,3 @@ | ||
from: t => m.super().from(t), | ||
from: t => m.super().from(t), | ||
@@ -816,3 +895,3 @@ fromCall: s => { | ||
ret.push(' USING '); | ||
list(r.using, ({type, value}) => { | ||
list(r.using, ({ type, value }) => { | ||
ret.push(type.toUpperCase(), '='); | ||
@@ -905,3 +984,3 @@ m.expr(value); | ||
} | ||
if(c.tablespace) { | ||
if (c.tablespace) { | ||
ret.push(' TABLESPACE ', name(c.tablespace)); | ||
@@ -908,0 +987,0 @@ } |
import { nil } from '../utils'; | ||
export declare const LOCATION: unique symbol; | ||
export declare type Statement = (SelectStatement | CreateTableStatement | CreateSequenceStatement | CreateIndexStatement | CreateExtensionStatement | CommitStatement | InsertStatement | UpdateStatement | ShowStatement | PrepareStatement | DeleteStatement | WithStatement | RollbackStatement | TablespaceStatement | CreateViewStatement | CreateMaterializedViewStatement | AlterTableStatement | AlterSequenceStatement | SetGlobalStatement | SetTimezone | CreateEnumType | TruncateTableStatement | DropTableStatement | DropSequenceStatement | DropIndexStatement | CommentStatement | CreateSchemaStatement | RaiseStatement | StartTransactionStatement) & { | ||
export declare type Statement = (SelectStatement | CreateTableStatement | CreateSequenceStatement | CreateIndexStatement | CreateExtensionStatement | CommitStatement | InsertStatement | UpdateStatement | ShowStatement | PrepareStatement | DeleteStatement | WithStatement | RollbackStatement | TablespaceStatement | CreateViewStatement | CreateMaterializedViewStatement | AlterTableStatement | AlterSequenceStatement | SetGlobalStatement | SetTimezone | CreateEnumType | TruncateTableStatement | DropTableStatement | DropSequenceStatement | DropIndexStatement | CommentStatement | CreateSchemaStatement | RaiseStatement | CreateFunctionStatement | DoStatement | StartTransactionStatement) & { | ||
[LOCATION]?: StatementLocation; | ||
}; | ||
export interface DoStatement { | ||
type: 'do'; | ||
language?: string; | ||
code: string; | ||
} | ||
export interface CreateFunctionStatement extends QName { | ||
type: 'create function'; | ||
code: string; | ||
orReplace?: boolean; | ||
language?: string; | ||
arguments: FunctionArgument[]; | ||
returns?: DataTypeDef | ReturnsTable; | ||
purity?: 'immutable' | 'stable' | 'volatile'; | ||
leakproof?: boolean; | ||
onNullInput?: 'call' | 'null' | 'strict'; | ||
} | ||
export interface ReturnsTable { | ||
kind: 'table'; | ||
columns: { | ||
name: string; | ||
type: DataTypeDef; | ||
}[]; | ||
} | ||
export declare type FunctionArgumentMode = 'in' | 'out' | 'inout' | 'variadic'; | ||
export interface FunctionArgument { | ||
name?: string; | ||
type: DataTypeDef; | ||
default?: Expr; | ||
mode?: FunctionArgumentMode; | ||
} | ||
export interface CommentStatement { | ||
@@ -242,2 +272,3 @@ type: 'comment'; | ||
constraints?: TableConstraint[]; | ||
inherits?: QName[]; | ||
} | ||
@@ -244,0 +275,0 @@ export interface CreateColumnDef { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
1241454
162
13406