sql writer
This commit is contained in:
4
pkg/writers/pgsql/templates/add_column.tmpl
Normal file
4
pkg/writers/pgsql/templates/add_column.tmpl
Normal file
@@ -0,0 +1,4 @@
|
||||
ALTER TABLE {{.SchemaName}}.{{.TableName}}
|
||||
ADD COLUMN IF NOT EXISTS {{.ColumnName}} {{.ColumnType}}
|
||||
{{- if .Default}} DEFAULT {{.Default}}{{end}}
|
||||
{{- if .NotNull}} NOT NULL{{end}};
|
||||
7
pkg/writers/pgsql/templates/alter_column_default.tmpl
Normal file
7
pkg/writers/pgsql/templates/alter_column_default.tmpl
Normal file
@@ -0,0 +1,7 @@
|
||||
{{- if .SetDefault -}}
|
||||
ALTER TABLE {{.SchemaName}}.{{.TableName}}
|
||||
ALTER COLUMN {{.ColumnName}} SET DEFAULT {{.DefaultValue}};
|
||||
{{- else -}}
|
||||
ALTER TABLE {{.SchemaName}}.{{.TableName}}
|
||||
ALTER COLUMN {{.ColumnName}} DROP DEFAULT;
|
||||
{{- end -}}
|
||||
2
pkg/writers/pgsql/templates/alter_column_type.tmpl
Normal file
2
pkg/writers/pgsql/templates/alter_column_type.tmpl
Normal file
@@ -0,0 +1,2 @@
|
||||
ALTER TABLE {{.SchemaName}}.{{.TableName}}
|
||||
ALTER COLUMN {{.ColumnName}} TYPE {{.NewType}};
|
||||
84
pkg/writers/pgsql/templates/audit_function.tmpl
Normal file
84
pkg/writers/pgsql/templates/audit_function.tmpl
Normal file
@@ -0,0 +1,84 @@
|
||||
CREATE OR REPLACE FUNCTION {{.SchemaName}}.{{.FunctionName}}()
|
||||
RETURNS trigger AS
|
||||
$body$
|
||||
DECLARE
|
||||
m_funcname text = '{{.FunctionName}}';
|
||||
m_user text;
|
||||
m_atevent integer;
|
||||
BEGIN
|
||||
-- Get current user
|
||||
m_user := {{.UserFunction}}::text;
|
||||
|
||||
-- Skip audit for specific users if needed
|
||||
IF m_user IN ('noaudit', 'importuser') THEN
|
||||
IF (TG_OP = 'DELETE') THEN
|
||||
RETURN OLD;
|
||||
ELSIF (TG_OP = 'UPDATE') THEN
|
||||
RETURN NEW;
|
||||
ELSIF (TG_OP = 'INSERT') THEN
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
END IF;
|
||||
|
||||
{{- if .AuditInsert}}
|
||||
IF TG_OP = 'INSERT' THEN
|
||||
-- Record INSERT
|
||||
INSERT INTO {{.AuditSchema}}.atevent (tablename, tableprefix, rid_parent, changeuser, changedate, changetime, actionx)
|
||||
VALUES ('{{.TableName}}', {{.TablePrefix}}, new.{{.PrimaryKey}}, m_user, CURRENT_DATE, CURRENT_TIME, 1)
|
||||
RETURNING rid_atevent INTO m_atevent;
|
||||
{{- end}}
|
||||
|
||||
{{- if .AuditUpdate}}
|
||||
ELSIF TG_OP = 'UPDATE' THEN
|
||||
-- Check if any audited columns changed
|
||||
IF ({{.UpdateCondition}}) THEN
|
||||
INSERT INTO {{.AuditSchema}}.atevent (tablename, tableprefix, rid_parent, changeuser, changedate, changetime, actionx)
|
||||
VALUES ('{{.TableName}}', {{.TablePrefix}}, new.{{.PrimaryKey}}, m_user, CURRENT_DATE, CURRENT_TIME, 2)
|
||||
RETURNING rid_atevent INTO m_atevent;
|
||||
|
||||
-- Record column changes
|
||||
{{- range .UpdateColumns}}
|
||||
IF (old.{{.Name}} IS DISTINCT FROM new.{{.Name}}) THEN
|
||||
INSERT INTO {{$.AuditSchema}}.atdetail(rid_atevent, datacolumn, changedfrom, changedto)
|
||||
VALUES (m_atevent, '{{.Name}}', substr({{.OldValue}}, 1, 1000), substr({{.NewValue}}, 1, 1000));
|
||||
END IF;
|
||||
{{- end}}
|
||||
END IF;
|
||||
{{- end}}
|
||||
|
||||
{{- if .AuditDelete}}
|
||||
ELSIF TG_OP = 'DELETE' THEN
|
||||
-- Record DELETE
|
||||
INSERT INTO {{.AuditSchema}}.atevent (tablename, tableprefix, rid_parent, rid_deletedparent, changeuser, changedate, changetime, actionx)
|
||||
VALUES ('{{.TableName}}', {{.TablePrefix}}, old.{{.PrimaryKey}}, old.{{.PrimaryKey}}, m_user, CURRENT_DATE, CURRENT_TIME, 3)
|
||||
RETURNING rid_atevent INTO m_atevent;
|
||||
|
||||
-- Record deleted column values
|
||||
{{- range .DeleteColumns}}
|
||||
INSERT INTO {{$.AuditSchema}}.atdetail(rid_atevent, datacolumn, changedfrom, changedto)
|
||||
VALUES (m_atevent, '{{.Name}}', substr({{.OldValue}}, 1, 1000), NULL);
|
||||
{{- end}}
|
||||
{{- end}}
|
||||
END IF;
|
||||
|
||||
IF (TG_OP = 'DELETE') THEN
|
||||
RETURN OLD;
|
||||
ELSIF (TG_OP = 'UPDATE') THEN
|
||||
RETURN NEW;
|
||||
ELSIF (TG_OP = 'INSERT') THEN
|
||||
RETURN NEW;
|
||||
END IF;
|
||||
|
||||
RETURN NULL;
|
||||
|
||||
EXCEPTION
|
||||
WHEN OTHERS THEN
|
||||
RAISE WARNING 'Audit function % failed: %', m_funcname, SQLERRM;
|
||||
RETURN NULL;
|
||||
END;
|
||||
$body$
|
||||
LANGUAGE plpgsql
|
||||
VOLATILE
|
||||
SECURITY DEFINER;
|
||||
|
||||
COMMENT ON FUNCTION {{.SchemaName}}.{{.FunctionName}}() IS 'Audit trigger function for table {{.SchemaName}}.{{.TableName}}';
|
||||
49
pkg/writers/pgsql/templates/audit_tables.tmpl
Normal file
49
pkg/writers/pgsql/templates/audit_tables.tmpl
Normal file
@@ -0,0 +1,49 @@
|
||||
-- Audit Event Header Table
|
||||
CREATE TABLE IF NOT EXISTS {{.AuditSchema}}.atevent (
|
||||
rid_atevent serial PRIMARY KEY,
|
||||
tablename text NOT NULL,
|
||||
tableprefix text,
|
||||
rid_parent integer NOT NULL,
|
||||
rid_deletedparent integer,
|
||||
changeuser text NOT NULL,
|
||||
changedate date NOT NULL,
|
||||
changetime time NOT NULL,
|
||||
actionx smallint NOT NULL,
|
||||
CONSTRAINT ck_atevent_action CHECK (actionx IN (1, 2, 3))
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_atevent_tablename ON {{.AuditSchema}}.atevent(tablename);
|
||||
CREATE INDEX IF NOT EXISTS idx_atevent_rid_parent ON {{.AuditSchema}}.atevent(rid_parent);
|
||||
CREATE INDEX IF NOT EXISTS idx_atevent_changedate ON {{.AuditSchema}}.atevent(changedate);
|
||||
CREATE INDEX IF NOT EXISTS idx_atevent_changeuser ON {{.AuditSchema}}.atevent(changeuser);
|
||||
|
||||
COMMENT ON TABLE {{.AuditSchema}}.atevent IS 'Audit trail header table - tracks all data changes';
|
||||
COMMENT ON COLUMN {{.AuditSchema}}.atevent.rid_atevent IS 'Audit event ID';
|
||||
COMMENT ON COLUMN {{.AuditSchema}}.atevent.tablename IS 'Name of the table that was modified';
|
||||
COMMENT ON COLUMN {{.AuditSchema}}.atevent.rid_parent IS 'Primary key value of the modified record';
|
||||
COMMENT ON COLUMN {{.AuditSchema}}.atevent.rid_deletedparent IS 'Parent reference for deleted records';
|
||||
COMMENT ON COLUMN {{.AuditSchema}}.atevent.changeuser IS 'User who made the change';
|
||||
COMMENT ON COLUMN {{.AuditSchema}}.atevent.changedate IS 'Date of change';
|
||||
COMMENT ON COLUMN {{.AuditSchema}}.atevent.changetime IS 'Time of change';
|
||||
COMMENT ON COLUMN {{.AuditSchema}}.atevent.actionx IS 'Action type: 1=INSERT, 2=UPDATE, 3=DELETE';
|
||||
|
||||
-- Audit Event Detail Table
|
||||
CREATE TABLE IF NOT EXISTS {{.AuditSchema}}.atdetail (
|
||||
rid_atdetail serial PRIMARY KEY,
|
||||
rid_atevent integer NOT NULL,
|
||||
datacolumn text NOT NULL,
|
||||
changedfrom text,
|
||||
changedto text,
|
||||
CONSTRAINT fk_atdetail_atevent FOREIGN KEY (rid_atevent)
|
||||
REFERENCES {{.AuditSchema}}.atevent(rid_atevent) ON DELETE CASCADE
|
||||
);
|
||||
|
||||
CREATE INDEX IF NOT EXISTS idx_atdetail_rid_atevent ON {{.AuditSchema}}.atdetail(rid_atevent);
|
||||
CREATE INDEX IF NOT EXISTS idx_atdetail_datacolumn ON {{.AuditSchema}}.atdetail(datacolumn);
|
||||
|
||||
COMMENT ON TABLE {{.AuditSchema}}.atdetail IS 'Audit trail detail table - stores individual column changes';
|
||||
COMMENT ON COLUMN {{.AuditSchema}}.atdetail.rid_atdetail IS 'Audit detail ID';
|
||||
COMMENT ON COLUMN {{.AuditSchema}}.atdetail.rid_atevent IS 'Reference to audit event';
|
||||
COMMENT ON COLUMN {{.AuditSchema}}.atdetail.datacolumn IS 'Name of the column that changed';
|
||||
COMMENT ON COLUMN {{.AuditSchema}}.atdetail.changedfrom IS 'Old value before change';
|
||||
COMMENT ON COLUMN {{.AuditSchema}}.atdetail.changedto IS 'New value after change';
|
||||
16
pkg/writers/pgsql/templates/audit_trigger.tmpl
Normal file
16
pkg/writers/pgsql/templates/audit_trigger.tmpl
Normal file
@@ -0,0 +1,16 @@
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1
|
||||
FROM pg_trigger
|
||||
WHERE tgname = '{{.TriggerName}}'
|
||||
AND tgrelid = '{{.SchemaName}}.{{.TableName}}'::regclass
|
||||
) THEN
|
||||
CREATE TRIGGER {{.TriggerName}}
|
||||
AFTER {{.Events}}
|
||||
ON {{.SchemaName}}.{{.TableName}}
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION {{.SchemaName}}.{{.FunctionName}}();
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
39
pkg/writers/pgsql/templates/base_constraint.tmpl
Normal file
39
pkg/writers/pgsql/templates/base_constraint.tmpl
Normal file
@@ -0,0 +1,39 @@
|
||||
{{/* Base constraint template */}}
|
||||
{{- define "constraint_base" -}}
|
||||
ALTER TABLE {{.SchemaName}}.{{.TableName}}
|
||||
ADD CONSTRAINT {{.ConstraintName}}
|
||||
{{block "constraint_definition" .}}{{end}};
|
||||
{{- end -}}
|
||||
|
||||
{{/* Drop constraint with check */}}
|
||||
{{- define "drop_constraint_safe" -}}
|
||||
DO $$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1 FROM information_schema.table_constraints
|
||||
WHERE table_schema = '{{.SchemaName}}'
|
||||
AND table_name = '{{.TableName}}'
|
||||
AND constraint_name = '{{.ConstraintName}}'
|
||||
) THEN
|
||||
ALTER TABLE {{.SchemaName}}.{{.TableName}}
|
||||
DROP CONSTRAINT {{.ConstraintName}};
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
{{- end -}}
|
||||
|
||||
{{/* Add constraint with existence check */}}
|
||||
{{- define "add_constraint_safe" -}}
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.table_constraints
|
||||
WHERE table_schema = '{{.SchemaName}}'
|
||||
AND table_name = '{{.TableName}}'
|
||||
AND constraint_name = '{{.ConstraintName}}'
|
||||
) THEN
|
||||
{{template "constraint_base" .}}
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
{{- end -}}
|
||||
34
pkg/writers/pgsql/templates/base_ddl.tmpl
Normal file
34
pkg/writers/pgsql/templates/base_ddl.tmpl
Normal file
@@ -0,0 +1,34 @@
|
||||
{{/* Base DDL template with common structure */}}
|
||||
{{- define "ddl_header" -}}
|
||||
-- DDL Operation: {{.Operation}}
|
||||
-- Schema: {{.Schema}}
|
||||
-- Object: {{.ObjectName}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "ddl_footer" -}}
|
||||
-- End of {{.Operation}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Base ALTER TABLE structure */}}
|
||||
{{- define "alter_table_base" -}}
|
||||
ALTER TABLE {{.SchemaName}}.{{.TableName}}
|
||||
{{block "alter_operation" .}}{{end}};
|
||||
{{- end -}}
|
||||
|
||||
{{/* Common existence check pattern */}}
|
||||
{{- define "exists_check" -}}
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
{{block "exists_query" .}}{{end}}
|
||||
) THEN
|
||||
{{block "create_statement" .}}{{end}}
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
{{- end -}}
|
||||
|
||||
{{/* Common drop pattern */}}
|
||||
{{- define "drop_if_exists" -}}
|
||||
{{block "drop_type" .}}{{end}} IF EXISTS {{.SchemaName}}.{{.ObjectName}};
|
||||
{{- end -}}
|
||||
1
pkg/writers/pgsql/templates/comment_column.tmpl
Normal file
1
pkg/writers/pgsql/templates/comment_column.tmpl
Normal file
@@ -0,0 +1 @@
|
||||
COMMENT ON COLUMN {{.SchemaName}}.{{.TableName}}.{{.ColumnName}} IS '{{.Comment}}';
|
||||
1
pkg/writers/pgsql/templates/comment_table.tmpl
Normal file
1
pkg/writers/pgsql/templates/comment_table.tmpl
Normal file
@@ -0,0 +1 @@
|
||||
COMMENT ON TABLE {{.SchemaName}}.{{.TableName}} IS '{{.Comment}}';
|
||||
10
pkg/writers/pgsql/templates/create_foreign_key.tmpl
Normal file
10
pkg/writers/pgsql/templates/create_foreign_key.tmpl
Normal file
@@ -0,0 +1,10 @@
|
||||
ALTER TABLE {{.SchemaName}}.{{.TableName}}
|
||||
DROP CONSTRAINT IF EXISTS {{.ConstraintName}};
|
||||
|
||||
ALTER TABLE {{.SchemaName}}.{{.TableName}}
|
||||
ADD CONSTRAINT {{.ConstraintName}}
|
||||
FOREIGN KEY ({{.SourceColumns}})
|
||||
REFERENCES {{.TargetSchema}}.{{.TargetTable}} ({{.TargetColumns}})
|
||||
ON DELETE {{.OnDelete}}
|
||||
ON UPDATE {{.OnUpdate}}
|
||||
DEFERRABLE;
|
||||
2
pkg/writers/pgsql/templates/create_index.tmpl
Normal file
2
pkg/writers/pgsql/templates/create_index.tmpl
Normal file
@@ -0,0 +1,2 @@
|
||||
CREATE {{if .Unique}}UNIQUE {{end}}INDEX IF NOT EXISTS {{.IndexName}}
|
||||
ON {{.SchemaName}}.{{.TableName}} USING {{.IndexType}} ({{.Columns}});
|
||||
13
pkg/writers/pgsql/templates/create_primary_key.tmpl
Normal file
13
pkg/writers/pgsql/templates/create_primary_key.tmpl
Normal file
@@ -0,0 +1,13 @@
|
||||
DO $$
|
||||
BEGIN
|
||||
IF NOT EXISTS (
|
||||
SELECT 1 FROM information_schema.table_constraints
|
||||
WHERE table_schema = '{{.SchemaName}}'
|
||||
AND table_name = '{{.TableName}}'
|
||||
AND constraint_name = '{{.ConstraintName}}'
|
||||
) THEN
|
||||
ALTER TABLE {{.SchemaName}}.{{.TableName}}
|
||||
ADD CONSTRAINT {{.ConstraintName}} PRIMARY KEY ({{.Columns}});
|
||||
END IF;
|
||||
END;
|
||||
$$;
|
||||
@@ -0,0 +1,4 @@
|
||||
{{/* Example of using template inheritance for primary key creation */}}
|
||||
{{/* This demonstrates how to use the base exists_check pattern */}}
|
||||
{{/* Note: This is an example and not used by the actual migration writer */}}
|
||||
{{/* The actual create_primary_key.tmpl is used instead */}}
|
||||
8
pkg/writers/pgsql/templates/create_table.tmpl
Normal file
8
pkg/writers/pgsql/templates/create_table.tmpl
Normal file
@@ -0,0 +1,8 @@
|
||||
CREATE TABLE IF NOT EXISTS {{.SchemaName}}.{{.TableName}} (
|
||||
{{- range $i, $col := .Columns}}
|
||||
{{- if $i}},{{end}}
|
||||
{{$col.Name}} {{$col.Type}}
|
||||
{{- if $col.Default}} DEFAULT {{$col.Default}}{{end}}
|
||||
{{- if $col.NotNull}} NOT NULL{{end}}
|
||||
{{- end}}
|
||||
);
|
||||
9
pkg/writers/pgsql/templates/create_table_composed.tmpl
Normal file
9
pkg/writers/pgsql/templates/create_table_composed.tmpl
Normal file
@@ -0,0 +1,9 @@
|
||||
{{/* Example of table creation using composition */}}
|
||||
{{- define "create_table_composed" -}}
|
||||
CREATE TABLE IF NOT EXISTS {{template "qualified_table" .}} (
|
||||
{{- range $i, $col := .Columns}}
|
||||
{{- if $i}},{{end}}
|
||||
{{template "column_definition" $col}}
|
||||
{{- end}}
|
||||
);
|
||||
{{- end -}}
|
||||
1
pkg/writers/pgsql/templates/drop_constraint.tmpl
Normal file
1
pkg/writers/pgsql/templates/drop_constraint.tmpl
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE {{.SchemaName}}.{{.TableName}} DROP CONSTRAINT IF EXISTS {{.ConstraintName}};
|
||||
1
pkg/writers/pgsql/templates/drop_index.tmpl
Normal file
1
pkg/writers/pgsql/templates/drop_index.tmpl
Normal file
@@ -0,0 +1 @@
|
||||
DROP INDEX IF EXISTS {{.SchemaName}}.{{.IndexName}} CASCADE;
|
||||
45
pkg/writers/pgsql/templates/fragments.tmpl
Normal file
45
pkg/writers/pgsql/templates/fragments.tmpl
Normal file
@@ -0,0 +1,45 @@
|
||||
{{/* Reusable template fragments */}}
|
||||
|
||||
{{/* Column definition fragment */}}
|
||||
{{- define "column_definition" -}}
|
||||
{{.Name}} {{.Type}}
|
||||
{{- if .Default}} DEFAULT {{.Default}}{{end}}
|
||||
{{- if .NotNull}} NOT NULL{{end}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Comma-separated column list */}}
|
||||
{{- define "column_list" -}}
|
||||
{{- range $i, $col := . -}}
|
||||
{{- if $i}}, {{end}}{{$col}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Qualified table name */}}
|
||||
{{- define "qualified_table" -}}
|
||||
{{.SchemaName}}.{{.TableName}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Index method clause */}}
|
||||
{{- define "index_method" -}}
|
||||
{{- if .IndexType}}USING {{.IndexType}}{{end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Uniqueness keyword */}}
|
||||
{{- define "unique_keyword" -}}
|
||||
{{- if .Unique}}UNIQUE {{end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Referential action clauses */}}
|
||||
{{- define "referential_actions" -}}
|
||||
{{- if .OnDelete}}
|
||||
ON DELETE {{.OnDelete}}
|
||||
{{- end}}
|
||||
{{- if .OnUpdate}}
|
||||
ON UPDATE {{.OnUpdate}}
|
||||
{{- end}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Comment statement */}}
|
||||
{{- define "comment_on" -}}
|
||||
COMMENT ON {{.ObjectType}} {{.ObjectName}} IS {{quote .Comment}};
|
||||
{{- end -}}
|
||||
Reference in New Issue
Block a user