diff --git a/packages/sij-dialect-postgresql/.prettierrc b/packages/sij-dialect-postgresql/.prettierrc new file mode 100644 index 0000000..bc42b01 --- /dev/null +++ b/packages/sij-dialect-postgresql/.prettierrc @@ -0,0 +1,5 @@ +{ + "printWidth": 120, + "arrowParens": "avoid", + "singleQuote": true +} diff --git a/packages/sij-dialect-postgresql/src/ast/index.ts b/packages/sij-dialect-postgresql/src/ast/index.ts index a147812..e6a6843 100644 --- a/packages/sij-dialect-postgresql/src/ast/index.ts +++ b/packages/sij-dialect-postgresql/src/ast/index.ts @@ -1,24 +1,28 @@ -import { Expr, Ident } from "sij-core/ast"; -import { Tagged, UnTag, tag } from "sij-core/util"; -import { Extend } from "sij-core/builder"; +import { Expr, Ident } from 'sij-core/ast'; +import { Tagged, UnTag, tag } from 'sij-core/util'; +import { Extend } from 'sij-core/builder'; +import { PgAlterDomainAction } from './schema-manipulation'; interface Window extends Tagged< - "Window", + 'Window', { name: Ident; - partitionBy: Array>; + partitionBy: Array>; } > {} -const Window = (args: UnTag): Window => tag("Window", args); +const Window = (args: UnTag): Window => tag('Window', args); -type PostgreSqlExtension = Extend<{ +type PgExtension = Extend<{ Select: null | { window: Window | null; }; Delete: { using: Array; }; + DomainAction: PgAlterDomainAction; + AddDomainConstraint: boolean; + DropDomainConstraint: boolean; }>; -export { PostgreSqlExtension }; +export { PgExtension }; diff --git a/packages/sij-dialect-postgresql/src/ast/schema-manipulation.ts b/packages/sij-dialect-postgresql/src/ast/schema-manipulation.ts index c5f937f..12a5dd3 100644 --- a/packages/sij-dialect-postgresql/src/ast/schema-manipulation.ts +++ b/packages/sij-dialect-postgresql/src/ast/schema-manipulation.ts @@ -1,20 +1,35 @@ -import { QualifiedIdent, Ident, DataType } from "sij-core/ast"; +import { QualifiedIdent, Ident, DataType, Lit, StringLit } from 'sij-core/ast'; -import { Tagged, UnTag, tag } from "sij-core/util"; +import { Tagged, UnTag, tag } from 'sij-core/util'; -import type { PostgreSqlExtension } from "."; +import type { PgExtension } from '.'; + +type PgSchemaManipulation = + | Abort + | AlterAggregate + | AlterCollation + | AlterDatabase +// | AlterDefaultPrivileges + | AlterEventTrigger + | AlterForeignDataWrapper +// | AlterForeignTable +// | AlterFunction + | AlterGroupAddUser + | AlterGroupRename + +type UserSpec = Ident | 'CurrentRole' | 'CurrentUser' | 'SessionUser' /* ABORT [ WORK | TRANSACTION ] [ AND [ NO ] CHAIN ] */ interface Abort extends Tagged< - "Abort", + 'Abort', { readonly chain: boolean; } > {} -const Abort = (args: UnTag): Abort => tag("Abort", args); +const Abort = (args: UnTag): Abort => tag('Abort', args); /* ALTER AGGREGATE name ( aggregate_signature ) RENAME TO new_name @@ -30,7 +45,7 @@ where aggregate_signature is: */ interface AlterAggregate extends Tagged< - "AlterAggregate", + 'AlterAggregate', { readonly name: QualifiedIdent; readonly args: Array<[boolean, DataType]>; // empty is * @@ -38,44 +53,36 @@ interface AlterAggregate readonly action: AlterObjectAction; } > {} -const AlterAggregate = (args: UnTag): AlterAggregate => - tag("AlterAggregate", args); +const AlterAggregate = (args: UnTag): AlterAggregate => tag('AlterAggregate', args); -type AlterObjectAction = - | RenameObject - | ChangeObjectOwner - | SetObjectSchema +type AlterObjectAction = RenameObject | ChangeObjectOwner | SetObjectSchema; interface RenameObject -extends Tagged< - "RenameObject", - { - readonly newName: QualifiedIdent; - } -> {} -const RenameObject = (args: UnTag): RenameObject => -tag("RenameObject", args); - + extends Tagged< + 'RenameObject', + { + readonly newName: QualifiedIdent; + } + > {} +const RenameObject = (args: UnTag): RenameObject => tag('RenameObject', args); interface ChangeObjectOwner -extends Tagged< - "ChangeObjectOwner", - { - readonly owner: Ident | 'CurrentRole' | 'CurrentUser' | 'SessionUser'; - } -> {} -const ChangeObjectOwner = (args: UnTag): ChangeObjectOwner => -tag("ChangeObjectOwner", args); + extends Tagged< + 'ChangeObjectOwner', + { + readonly owner: UserSpec; + } + > {} +const ChangeObjectOwner = (args: UnTag): ChangeObjectOwner => tag('ChangeObjectOwner', args); interface SetObjectSchema -extends Tagged< - "SetObjectSchema", - { - readonly owner: Ident; - } -> {} -const SetObjectSchema = (args: UnTag): SetObjectSchema => -tag("SetObjectSchema", args); + extends Tagged< + 'SetObjectSchema', + { + readonly owner: Ident; + } + > {} +const SetObjectSchema = (args: UnTag): SetObjectSchema => tag('SetObjectSchema', args); /* ALTER COLLATION name REFRESH VERSION @@ -85,15 +92,14 @@ ALTER COLLATION name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSIO ALTER COLLATION name SET SCHEMA new_schema */ interface AlterCollation -extends Tagged< - "AlterCollation", - { - readonly name: Ident; - readonly action: AlterObjectAction; - } -> {} -const AlterCollation = (args: UnTag): AlterCollation => -tag("AlterCollation", args); + extends Tagged< + 'AlterCollation', + { + readonly name: Ident; + readonly action: AlterObjectAction; + } + > {} +const AlterCollation = (args: UnTag): AlterCollation => tag('AlterCollation', args); /* ALTER CONVERSION name RENAME TO new_name @@ -101,15 +107,14 @@ ALTER CONVERSION name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSI ALTER CONVERSION name SET SCHEMA new_schema */ interface AlterConversion -extends Tagged< - "AlterConversion", - { - readonly name: Ident; - readonly action: AlterObjectAction; - } -> {} -const AlterConversion = (args: UnTag): AlterConversion => -tag("AlterConversion", args); + extends Tagged< + 'AlterConversion', + { + readonly name: Ident; + readonly action: AlterObjectAction; + } + > {} +const AlterConversion = (args: UnTag): AlterConversion => tag('AlterConversion', args); /* ALTER DATABASE name [ [ WITH ] option [ ... ] ] @@ -132,4 +137,466 @@ ALTER DATABASE name SET configuration_parameter { TO | = } { value | DEFAULT } ALTER DATABASE name SET configuration_parameter FROM CURRENT ALTER DATABASE name RESET configuration_parameter ALTER DATABASE name RESET ALL -*/ \ No newline at end of file +*/ +interface AlterDatabase + extends Tagged< + 'AlterDatabase', + { + readonly name: Ident; + readonly action: AlterDatabaseAction; + } + > {} +const AlterDatabase = (args: UnTag): AlterDatabase => tag('AlterDatabase', args); + +type AlterDatabaseAction = + | ChangeSettings + | RenameObject + | ChangeObjectOwner + | SetTablespace + | RefreshCollation + | SetConfig + | ResetConfig; + +/* +ALTER DATABASE name [ [ WITH ] option [ ... ] ] + +where option can be: + + ALLOW_CONNECTIONS allowconn + CONNECTION LIMIT connlimit + IS_TEMPLATE istemplate +*/ +interface ChangeSettings + extends Tagged< + 'ChangeSettings', + { + readonly allowConnections?: boolean; + readonly connectionLimit?: number; + readonly isTemplate?: boolean; + } + > {} +const ChangeSettings = (args: UnTag): ChangeSettings => tag('ChangeSettings', args); + +/* +ALTER DATABASE name SET TABLESPACE new_tablespace +*/ +interface SetTablespace + extends Tagged< + 'SetTablespace', + { + readonly name: Ident; + } + > {} +const SetTablespace = (args: UnTag): SetTablespace => tag('SetTablespace', args); + +/* +ALTER DATABASE name REFRESH COLLATION VERSION +*/ +interface RefreshCollation extends Tagged<'RefreshCollation', {}> {} +const RefreshCollation: RefreshCollation = tag('RefreshCollation', {}); + +/* +ALTER DATABASE name SET configuration_parameter { TO | = } { value | DEFAULT } +ALTER DATABASE name SET configuration_parameter FROM CURRENT +*/ +interface SetConfig + extends Tagged< + 'SetConfig', + { + readonly name: Ident; + readonly value: Lit | 'Default' | 'FromCurrent'; + } + > {} +const SetConfig = (args: UnTag): SetConfig => tag('SetConfig', args); + +/* +ALTER DATABASE name RESET configuration_parameter +ALTER DATABASE name RESET ALL +*/ +interface ResetConfig + extends Tagged< + 'ResetConfig', + { + readonly name: Ident | null; // null is RESET ALL + } + > {} +const ResetConfig = (args: UnTag): ResetConfig => tag('ResetConfig', args); + +/* +ALTER DEFAULT PRIVILEGES + [ FOR { ROLE | USER } target_role [, ...] ] + [ IN SCHEMA schema_name [, ...] ] + abbreviated_grant_or_revoke + +where abbreviated_grant_or_revoke is one of: + +GRANT { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER } + [, ...] | ALL [ PRIVILEGES ] } + ON TABLES + TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] + +GRANT { { USAGE | SELECT | UPDATE } + [, ...] | ALL [ PRIVILEGES ] } + ON SEQUENCES + TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] + +GRANT { EXECUTE | ALL [ PRIVILEGES ] } + ON { FUNCTIONS | ROUTINES } + TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] + +GRANT { USAGE | ALL [ PRIVILEGES ] } + ON TYPES + TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] + +GRANT { USAGE | CREATE | ALL [ PRIVILEGES ] } + ON SCHEMAS + TO { [ GROUP ] role_name | PUBLIC } [, ...] [ WITH GRANT OPTION ] + +REVOKE [ GRANT OPTION FOR ] + { { SELECT | INSERT | UPDATE | DELETE | TRUNCATE | REFERENCES | TRIGGER } + [, ...] | ALL [ PRIVILEGES ] } + ON TABLES + FROM { [ GROUP ] role_name | PUBLIC } [, ...] + [ CASCADE | RESTRICT ] + +REVOKE [ GRANT OPTION FOR ] + { { USAGE | SELECT | UPDATE } + [, ...] | ALL [ PRIVILEGES ] } + ON SEQUENCES + FROM { [ GROUP ] role_name | PUBLIC } [, ...] + [ CASCADE | RESTRICT ] + +REVOKE [ GRANT OPTION FOR ] + { EXECUTE | ALL [ PRIVILEGES ] } + ON { FUNCTIONS | ROUTINES } + FROM { [ GROUP ] role_name | PUBLIC } [, ...] + [ CASCADE | RESTRICT ] + +REVOKE [ GRANT OPTION FOR ] + { USAGE | ALL [ PRIVILEGES ] } + ON TYPES + FROM { [ GROUP ] role_name | PUBLIC } [, ...] + [ CASCADE | RESTRICT ] + +REVOKE [ GRANT OPTION FOR ] + { USAGE | CREATE | ALL [ PRIVILEGES ] } + ON SCHEMAS + FROM { [ GROUP ] role_name | PUBLIC } [, ...] + [ CASCADE | RESTRICT ] +*/ +interface AlterDefaultPrivileges + extends Tagged< + 'AlterDefaultPrivileges', + { + readonly name: Ident | null; // TODO come back to this after doing grant/revoke + } + > {} +const AlterDefaultPrivileges = (args: UnTag): AlterDefaultPrivileges => + tag('AlterDefaultPrivileges', args); + +interface AbbreviatedGrant + extends Tagged< + 'AbbreviatedGrant', + { + readonly name: Ident | null; // TODO come back to this after doing grant/revoke + } + > {} +const AbbreviatedGrant = (args: UnTag): AbbreviatedGrant => tag('AbbreviatedGrant', args); + +/* +ALTER DOMAIN name + { SET DEFAULT expression | DROP DEFAULT } +ALTER DOMAIN name + { SET | DROP } NOT NULL +ALTER DOMAIN name + ADD domain_constraint [ NOT VALID ] +ALTER DOMAIN name + DROP CONSTRAINT [ IF EXISTS ] constraint_name [ RESTRICT | CASCADE ] +ALTER DOMAIN name + RENAME CONSTRAINT constraint_name TO new_constraint_name +ALTER DOMAIN name + VALIDATE CONSTRAINT constraint_name +ALTER DOMAIN name + OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER } +ALTER DOMAIN name + RENAME TO new_name +ALTER DOMAIN name + SET SCHEMA new_schema +*/ +type PgAlterDomainAction = AlterDomainNotNull; + +interface AlterDomainNotNull + extends Tagged< + 'AlterDomainNotNull', + { + readonly set: boolean; + } + > {} +const AlterDomainNotNull = (args: UnTag): AlterDomainNotNull => tag('AlterDomainNotNull', args); + +interface AlterDomainOwner + extends Tagged< + 'AlterDomainOwner', + { + readonly set: UserSpec; + } + > {} +const AlterDomainOwner = (args: UnTag): AlterDomainOwner => tag('AlterDomainOwner', args); + +interface AlterDomainRename + extends Tagged< + 'AlterDomainRename', + { + readonly set: Ident; + } + > {} +const AlterDomainRename = (args: UnTag): AlterDomainRename => tag('AlterDomainRename', args); + +interface AlterDomainSetSchema + extends Tagged< + 'AlterDomainSetSchema', + { + readonly set: Ident; + } + > {} +const AlterDomainSetSchema = (args: UnTag): AlterDomainSetSchema => + tag('AlterDomainSetSchema', args); + +/* +ALTER EVENT TRIGGER name DISABLE +ALTER EVENT TRIGGER name ENABLE [ REPLICA | ALWAYS ] +ALTER EVENT TRIGGER name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER } +ALTER EVENT TRIGGER name RENAME TO new_name +*/ +interface AlterEventTrigger + extends Tagged< + 'AlterEventTrigger', + { + readonly set: Ident; + readonly action: AlterEventTriggerAction; + } + > {} +const AlterEventTrigger = (args: UnTag): AlterEventTrigger => tag('AlterEventTrigger', args); + +type AlterEventTriggerAction = DisableEventTrigger | EnableEventTrigger | RenameObject | ChangeObjectOwner; + +interface DisableEventTrigger extends Tagged<'DisableEventTrigger', {}> {} +const DisableEventTrigger: DisableEventTrigger = tag('DisableEventTrigger', {}); + +interface EnableEventTrigger + extends Tagged< + 'EnableEventTrigger', + { + readonly mode: 'Replica' | 'Always' | 'Default'; + } + > {} +const EnableEventTrigger = (args: UnTag): EnableEventTrigger => tag('EnableEventTrigger', args); + +/* +TODO +ALTER EXTENSION name UPDATE [ TO new_version ] +ALTER EXTENSION name SET SCHEMA new_schema +ALTER EXTENSION name ADD member_object +ALTER EXTENSION name DROP member_object + +where member_object is: + + ACCESS METHOD object_name | + AGGREGATE aggregate_name ( aggregate_signature ) | + CAST (source_type AS target_type) | + COLLATION object_name | + CONVERSION object_name | + DOMAIN object_name | + EVENT TRIGGER object_name | + FOREIGN DATA WRAPPER object_name | + FOREIGN TABLE object_name | + FUNCTION function_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] | + MATERIALIZED VIEW object_name | + OPERATOR operator_name (left_type, right_type) | + OPERATOR CLASS object_name USING index_method | + OPERATOR FAMILY object_name USING index_method | + [ PROCEDURAL ] LANGUAGE object_name | + PROCEDURE procedure_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] | + ROUTINE routine_name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] | + SCHEMA object_name | + SEQUENCE object_name | + SERVER object_name | + TABLE object_name | + TEXT SEARCH CONFIGURATION object_name | + TEXT SEARCH DICTIONARY object_name | + TEXT SEARCH PARSER object_name | + TEXT SEARCH TEMPLATE object_name | + TRANSFORM FOR type_name LANGUAGE lang_name | + TYPE object_name | + VIEW object_name + +and aggregate_signature is: + +* | +[ argmode ] [ argname ] argtype [ , ... ] | +[ [ argmode ] [ argname ] argtype [ , ... ] ] ORDER BY [ argmode ] [ argname ] argtype [ , ... ] +*/ + +/* +ALTER FOREIGN DATA WRAPPER name + [ HANDLER handler_function | NO HANDLER ] + [ VALIDATOR validator_function | NO VALIDATOR ] + [ OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ]) ] +ALTER FOREIGN DATA WRAPPER name OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER } +ALTER FOREIGN DATA WRAPPER name RENAME TO new_name +*/ +interface AlterForeignDataWrapper + extends Tagged< + 'AlterForeignDataWrapper', + { + readonly name: Ident; + readonly action: RenameObject | ChangeObjectOwner | DataWrapperSettings; + } + > {} +const AlterForeignDataWrapper = (args: UnTag): AlterForeignDataWrapper => + tag('AlterForeignDataWrapper', args); + +interface DataWrapperSettings + extends Tagged< + 'DataWrapperSettings', + { + readonly handler?: Ident | null; + readonly validator?: Ident | null; + readonly options: Array; + } + > {} +const DataWrapperSettings = (args: UnTag): DataWrapperSettings => tag('DataWrapperSettings', args); + +interface DataWrapperOption + extends Tagged< + 'DataWrapperOption', + { + readonly mode: 'Add' | 'Set' | 'Drop'; + readonly name: Ident; + readonly value: StringLit; + } + > {} +const DataWrapperOption = (args: UnTag): DataWrapperOption => tag('DataWrapperOption', args); + +/* +TODO +ALTER FOREIGN TABLE [ IF EXISTS ] [ ONLY ] name [ * ] + action [, ... ] +ALTER FOREIGN TABLE [ IF EXISTS ] [ ONLY ] name [ * ] + RENAME [ COLUMN ] column_name TO new_column_name +ALTER FOREIGN TABLE [ IF EXISTS ] name + RENAME TO new_name +ALTER FOREIGN TABLE [ IF EXISTS ] name + SET SCHEMA new_schema + +where action is one of: + + ADD [ COLUMN ] column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ] + DROP [ COLUMN ] [ IF EXISTS ] column_name [ RESTRICT | CASCADE ] + ALTER [ COLUMN ] column_name [ SET DATA ] TYPE data_type [ COLLATE collation ] + ALTER [ COLUMN ] column_name SET DEFAULT expression + ALTER [ COLUMN ] column_name DROP DEFAULT + ALTER [ COLUMN ] column_name { SET | DROP } NOT NULL + ALTER [ COLUMN ] column_name SET STATISTICS integer + ALTER [ COLUMN ] column_name SET ( attribute_option = value [, ... ] ) + ALTER [ COLUMN ] column_name RESET ( attribute_option [, ... ] ) + ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } + ALTER [ COLUMN ] column_name OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ]) + ADD table_constraint [ NOT VALID ] + VALIDATE CONSTRAINT constraint_name + DROP CONSTRAINT [ IF EXISTS ] constraint_name [ RESTRICT | CASCADE ] + DISABLE TRIGGER [ trigger_name | ALL | USER ] + ENABLE TRIGGER [ trigger_name | ALL | USER ] + ENABLE REPLICA TRIGGER trigger_name + ENABLE ALWAYS TRIGGER trigger_name + SET WITHOUT OIDS + INHERIT parent_table + NO INHERIT parent_table + OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER } + OPTIONS ( [ ADD | SET | DROP ] option ['value'] [, ... ]) +*/ + +/* +ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] + action [ ... ] [ RESTRICT ] +ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] + RENAME TO new_name +ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] + OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER } +ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] + SET SCHEMA new_schema +ALTER FUNCTION name [ ( [ [ argmode ] [ argname ] argtype [, ...] ] ) ] + [ NO ] DEPENDS ON EXTENSION extension_name + +where action is one of: + + CALLED ON NULL INPUT | RETURNS NULL ON NULL INPUT | STRICT + IMMUTABLE | STABLE | VOLATILE + [ NOT ] LEAKPROOF + [ EXTERNAL ] SECURITY INVOKER | [ EXTERNAL ] SECURITY DEFINER + PARALLEL { UNSAFE | RESTRICTED | SAFE } + COST execution_cost + ROWS result_rows + SUPPORT support_function + SET configuration_parameter { TO | = } { value | DEFAULT } + SET configuration_parameter FROM CURRENT + RESET configuration_parameter + RESET ALL +*/ + +/* +ALTER GROUP role_specification ADD USER user_name [, ... ] +ALTER GROUP role_specification DROP USER user_name [, ... ] + +where role_specification can be: + + role_name + | CURRENT_ROLE + | CURRENT_USER + | SESSION_USER +*/ +interface AlterGroupAddUser +extends Tagged< + 'AlterGroupAddUser', + { + readonly role: UserSpec; + readonly drop: boolean; + } +> {} +const AlterGroupAddUser = (args: UnTag): AlterGroupAddUser => tag('AlterGroupAddUser', args); + +/* +ALTER GROUP group_name RENAME TO new_name +*/ +interface AlterGroupRename +extends Tagged< + 'AlterGroupRename', + { + readonly group: Ident; + readonly new_name: Ident; + } +> {} +const AlterGroupRename = (args: UnTag): AlterGroupRename => tag('AlterGroupRename', args); + + +export { + PgSchemaManipulation, + Abort, + AlterAggregate, + AlterCollation, + AlterDatabase, + PgAlterDomainAction, + AlterDomainNotNull, + AlterDomainOwner, + AlterDomainRename, + AlterDomainSetSchema, + AlterEventTrigger, + AlterEventTriggerAction, + DisableEventTrigger, + EnableEventTrigger, + AlterForeignDataWrapper, + DataWrapperSettings, + DataWrapperOption, + AlterGroupAddUser, + AlterGroupRename, +}; diff --git a/packages/sij-dialect-postgresql/src/render/index.ts b/packages/sij-dialect-postgresql/src/render/index.ts index de130ad..eb8fff2 100644 --- a/packages/sij-dialect-postgresql/src/render/index.ts +++ b/packages/sij-dialect-postgresql/src/render/index.ts @@ -1,3 +1,3 @@ -import { Renderer } from "sij-core"; +import { Renderer } from 'sij-core'; class PostgreSqlRenderer extends Renderer {}