Updates
This commit is contained in:
+3
@@ -0,0 +1,3 @@
|
||||
type Params = {};
|
||||
|
||||
function createDuplicateTablesTriggers({}: Params) {}
|
||||
+106
@@ -0,0 +1,106 @@
|
||||
```sql
|
||||
DELIMITER //
|
||||
|
||||
CREATE PROCEDURE dsql_replicate_databases(IN source_db VARCHAR(64), IN target_db VARCHAR(64))
|
||||
BEGIN
|
||||
-- Declare variables
|
||||
DECLARE done INT DEFAULT FALSE;
|
||||
DECLARE table_name VARCHAR(64);
|
||||
DECLARE column_list TEXT;
|
||||
DECLARE trigger_sql TEXT;
|
||||
|
||||
-- Cursor to iterate over tables in source_db
|
||||
DECLARE cur CURSOR FOR
|
||||
SELECT TABLE_NAME
|
||||
FROM INFORMATION_SCHEMA.TABLES
|
||||
WHERE TABLE_SCHEMA = source_db;
|
||||
|
||||
-- Handler for end of cursor
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
|
||||
|
||||
-- Start transaction to ensure consistency
|
||||
START TRANSACTION;
|
||||
|
||||
-- Open cursor
|
||||
OPEN cur;
|
||||
|
||||
read_loop: LOOP
|
||||
FETCH cur INTO table_name;
|
||||
IF done THEN
|
||||
LEAVE read_loop;
|
||||
END IF;
|
||||
|
||||
-- Dynamically get column names for the table
|
||||
SELECT GROUP_CONCAT(CONCAT('NEW.', COLUMN_NAME))
|
||||
INTO column_list
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = source_db
|
||||
AND TABLE_NAME = table_name;
|
||||
|
||||
-- Drop existing triggers if they exist
|
||||
SET @drop_trigger_insert = CONCAT('DROP TRIGGER IF EXISTS after_insert_', table_name);
|
||||
SET @drop_trigger_update = CONCAT('DROP TRIGGER IF EXISTS after_update_', table_name);
|
||||
SET @drop_trigger_delete = CONCAT('DROP TRIGGER IF EXISTS after_delete_', table_name);
|
||||
PREPARE stmt_drop_insert FROM @drop_trigger_insert;
|
||||
EXECUTE stmt_drop_insert;
|
||||
DEALLOCATE PREPARE stmt_drop_insert;
|
||||
PREPARE stmt_drop_update FROM @drop_trigger_update;
|
||||
EXECUTE stmt_drop_update;
|
||||
DEALLOCATE PREPARE stmt_drop_update;
|
||||
PREPARE stmt_drop_delete FROM @drop_trigger_delete;
|
||||
EXECUTE stmt_drop_delete;
|
||||
DEALLOCATE PREPARE stmt_drop_delete;
|
||||
|
||||
-- Create INSERT trigger
|
||||
SET @trigger_sql = CONCAT(
|
||||
'CREATE TRIGGER after_insert_', table_name,
|
||||
' AFTER INSERT ON ', source_db, '.', table_name, ' FOR EACH ROW ',
|
||||
'BEGIN ',
|
||||
'INSERT INTO ', target_db, '.', table_name, ' (',
|
||||
(SELECT GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = source_db AND TABLE_NAME = table_name), ') ',
|
||||
'VALUES (', column_list, '); ',
|
||||
'END;'
|
||||
);
|
||||
PREPARE stmt FROM @trigger_sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Create UPDATE trigger
|
||||
SET @trigger_sql = CONCAT(
|
||||
'CREATE TRIGGER after_update_', table_name,
|
||||
' AFTER UPDATE ON ', source_db, '.', table_name, ' FOR EACH ROW ',
|
||||
'BEGIN ',
|
||||
'UPDATE ', target_db, '.', table_name, ' SET ',
|
||||
(SELECT GROUP_CONCAT(CONCAT(COLUMN_NAME, '=NEW.', COLUMN_NAME))
|
||||
FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = source_db AND TABLE_NAME = table_name),
|
||||
' WHERE ',
|
||||
(SELECT CONCAT('id=NEW.id')
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = source_db AND TABLE_NAME = table_name AND COLUMN_NAME = 'id' LIMIT 1), '; ',
|
||||
'END;'
|
||||
);
|
||||
PREPARE stmt FROM @trigger_sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Create DELETE trigger
|
||||
SET @trigger_sql = CONCAT(
|
||||
'CREATE TRIGGER after_delete_', table_name,
|
||||
' AFTER DELETE ON ', source_db, '.', table_name, ' FOR EACH ROW ',
|
||||
'BEGIN ',
|
||||
'DELETE FROM ', target_db, '.', table_name, ' WHERE id=OLD.id; ',
|
||||
'END;'
|
||||
);
|
||||
PREPARE stmt FROM @trigger_sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
END LOOP;
|
||||
|
||||
CLOSE cur;
|
||||
COMMIT;
|
||||
|
||||
END //
|
||||
|
||||
DELIMITER ;
|
||||
```
|
||||
+212
@@ -0,0 +1,212 @@
|
||||
DELIMITER / / CREATE PROCEDURE replicate_databases(
|
||||
IN source_db VARCHAR(64),
|
||||
IN target_db VARCHAR(64)
|
||||
) BEGIN -- Declare variables
|
||||
DECLARE done INT DEFAULT FALSE;
|
||||
|
||||
DECLARE table_name VARCHAR(64);
|
||||
|
||||
DECLARE column_list TEXT;
|
||||
|
||||
DECLARE trigger_sql TEXT;
|
||||
|
||||
-- Cursor to iterate over tables in source_db
|
||||
DECLARE cur CURSOR FOR
|
||||
SELECT
|
||||
TABLE_NAME
|
||||
FROM
|
||||
INFORMATION_SCHEMA.TABLES
|
||||
WHERE
|
||||
TABLE_SCHEMA = source_db;
|
||||
|
||||
-- Handler for end of cursor
|
||||
DECLARE CONTINUE HANDLER FOR NOT FOUND
|
||||
SET
|
||||
done = TRUE;
|
||||
|
||||
-- Start transaction to ensure consistency
|
||||
START TRANSACTION;
|
||||
|
||||
-- Open cursor
|
||||
OPEN cur;
|
||||
|
||||
read_loop: LOOP FETCH cur INTO table_name;
|
||||
|
||||
IF done THEN LEAVE read_loop;
|
||||
|
||||
END IF;
|
||||
|
||||
-- Dynamically get column names for the table
|
||||
SELECT
|
||||
GROUP_CONCAT(CONCAT('NEW.', COLUMN_NAME)) INTO column_list
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_SCHEMA = source_db
|
||||
AND TABLE_NAME = table_name;
|
||||
|
||||
-- Drop existing triggers if they exist
|
||||
SET
|
||||
@drop_trigger_insert = CONCAT(
|
||||
'DROP TRIGGER IF EXISTS after_insert_',
|
||||
table_name
|
||||
);
|
||||
|
||||
SET
|
||||
@drop_trigger_update = CONCAT(
|
||||
'DROP TRIGGER IF EXISTS after_update_',
|
||||
table_name
|
||||
);
|
||||
|
||||
SET
|
||||
@drop_trigger_delete = CONCAT(
|
||||
'DROP TRIGGER IF EXISTS after_delete_',
|
||||
table_name
|
||||
);
|
||||
|
||||
PREPARE stmt_drop_insert
|
||||
FROM
|
||||
@drop_trigger_insert;
|
||||
|
||||
EXECUTE stmt_drop_insert;
|
||||
|
||||
DEALLOCATE PREPARE stmt_drop_insert;
|
||||
|
||||
PREPARE stmt_drop_update
|
||||
FROM
|
||||
@drop_trigger_update;
|
||||
|
||||
EXECUTE stmt_drop_update;
|
||||
|
||||
DEALLOCATE PREPARE stmt_drop_update;
|
||||
|
||||
PREPARE stmt_drop_delete
|
||||
FROM
|
||||
@drop_trigger_delete;
|
||||
|
||||
EXECUTE stmt_drop_delete;
|
||||
|
||||
DEALLOCATE PREPARE stmt_drop_delete;
|
||||
|
||||
-- Create INSERT trigger
|
||||
SET
|
||||
@trigger_sql = CONCAT(
|
||||
'CREATE TRIGGER after_insert_',
|
||||
table_name,
|
||||
' AFTER INSERT ON ',
|
||||
source_db,
|
||||
'.',
|
||||
table_name,
|
||||
' FOR EACH ROW ',
|
||||
'BEGIN ',
|
||||
'INSERT INTO ',
|
||||
target_db,
|
||||
'.',
|
||||
table_name,
|
||||
' (',
|
||||
(
|
||||
SELECT
|
||||
GROUP_CONCAT(COLUMN_NAME)
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_SCHEMA = source_db
|
||||
AND TABLE_NAME = table_name
|
||||
),
|
||||
') ',
|
||||
'VALUES (',
|
||||
column_list,
|
||||
'); ',
|
||||
'END;'
|
||||
);
|
||||
|
||||
PREPARE stmt
|
||||
FROM
|
||||
@trigger_sql;
|
||||
|
||||
EXECUTE stmt;
|
||||
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Create UPDATE trigger
|
||||
SET
|
||||
@trigger_sql = CONCAT(
|
||||
'CREATE TRIGGER after_update_',
|
||||
table_name,
|
||||
' AFTER UPDATE ON ',
|
||||
source_db,
|
||||
'.',
|
||||
table_name,
|
||||
' FOR EACH ROW ',
|
||||
'BEGIN ',
|
||||
'UPDATE ',
|
||||
target_db,
|
||||
'.',
|
||||
table_name,
|
||||
' SET ',
|
||||
(
|
||||
SELECT
|
||||
GROUP_CONCAT(CONCAT(COLUMN_NAME, '=NEW.', COLUMN_NAME))
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_SCHEMA = source_db
|
||||
AND TABLE_NAME = table_name
|
||||
),
|
||||
' WHERE ',
|
||||
(
|
||||
SELECT
|
||||
CONCAT('id=NEW.id')
|
||||
FROM
|
||||
INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE
|
||||
TABLE_SCHEMA = source_db
|
||||
AND TABLE_NAME = table_name
|
||||
AND COLUMN_NAME = 'id'
|
||||
LIMIT
|
||||
1
|
||||
), '; ', 'END;'
|
||||
);
|
||||
|
||||
PREPARE stmt
|
||||
FROM
|
||||
@trigger_sql;
|
||||
|
||||
EXECUTE stmt;
|
||||
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Create DELETE trigger
|
||||
SET
|
||||
@trigger_sql = CONCAT(
|
||||
'CREATE TRIGGER after_delete_',
|
||||
table_name,
|
||||
' AFTER DELETE ON ',
|
||||
source_db,
|
||||
'.',
|
||||
table_name,
|
||||
' FOR EACH ROW ',
|
||||
'BEGIN ',
|
||||
'DELETE FROM ',
|
||||
target_db,
|
||||
'.',
|
||||
table_name,
|
||||
' WHERE id=OLD.id; ',
|
||||
'END;'
|
||||
);
|
||||
|
||||
PREPARE stmt
|
||||
FROM
|
||||
@trigger_sql;
|
||||
|
||||
EXECUTE stmt;
|
||||
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
END LOOP;
|
||||
|
||||
CLOSE cur;
|
||||
|
||||
COMMIT;
|
||||
|
||||
END / / DELIMITER;
|
||||
@@ -0,0 +1,23 @@
|
||||
export const TriggerParadigms = ["sync_tables", "sync_dbs"] as const;
|
||||
|
||||
type Params = {
|
||||
userId?: string | number;
|
||||
paradigm: (typeof TriggerParadigms)[number];
|
||||
dbId?: string | number;
|
||||
tableName?: string;
|
||||
};
|
||||
|
||||
export default function grabTriggerName({
|
||||
userId,
|
||||
paradigm,
|
||||
dbId,
|
||||
tableName,
|
||||
}: Params) {
|
||||
let triggerName = `dsql_trig_${paradigm}`;
|
||||
|
||||
if (userId) triggerName += `_${userId}`;
|
||||
if (dbId) triggerName += `_${dbId}`;
|
||||
if (tableName) triggerName += `_${tableName}`;
|
||||
|
||||
return triggerName;
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
import { DSQL_DatabaseSchemaType, DSQL_TableSchemaType } from "../../../types";
|
||||
|
||||
const TriggerTypes = [
|
||||
{
|
||||
name: "after_insert",
|
||||
value: "INSERT",
|
||||
},
|
||||
{
|
||||
name: "after_update",
|
||||
value: "UPDATE",
|
||||
},
|
||||
{
|
||||
name: "after_delete",
|
||||
value: "DELETE",
|
||||
},
|
||||
] as const;
|
||||
|
||||
export type TriggerSQLGenParams = {
|
||||
type: (typeof TriggerTypes)[number];
|
||||
srcDbSchema: DSQL_DatabaseSchemaType;
|
||||
srcTableSchema: DSQL_TableSchemaType;
|
||||
content: string;
|
||||
proceedureName: string;
|
||||
};
|
||||
|
||||
export default function triggerSQLGen({
|
||||
type,
|
||||
srcDbSchema,
|
||||
srcTableSchema,
|
||||
content,
|
||||
proceedureName,
|
||||
}: TriggerSQLGenParams) {
|
||||
let sql = `DELIMITER //\n`;
|
||||
|
||||
sql += `CREATE PROCEDURE ${proceedureName}`;
|
||||
sql += `\nBEGIN`;
|
||||
|
||||
sql += ` ${content}`;
|
||||
|
||||
sql += `\nEND //`;
|
||||
sql += `\nDELIMITER\n`;
|
||||
|
||||
return sql;
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
import { DSQL_DatabaseSchemaType, DSQL_TableSchemaType } from "../../../types";
|
||||
import triggerSQLGen, { TriggerSQLGenParams } from "./trigger-sql-gen";
|
||||
|
||||
type Params = TriggerSQLGenParams & {
|
||||
dstDbSchema: DSQL_DatabaseSchemaType;
|
||||
dstTableSchema: DSQL_TableSchemaType;
|
||||
};
|
||||
|
||||
export default function tableReplicationTriggerSQLGen({
|
||||
type,
|
||||
dstDbSchema,
|
||||
dstTableSchema,
|
||||
srcDbSchema,
|
||||
srcTableSchema,
|
||||
userId,
|
||||
paradigm,
|
||||
}: Params) {
|
||||
let sql = `CREATE TRIGGER`;
|
||||
|
||||
const srcColumns = srcTableSchema.fields
|
||||
.map((fld) => fld.fieldName)
|
||||
.filter((fld) => typeof fld == "string");
|
||||
const dstColumns = dstTableSchema.fields
|
||||
.map((fld) => fld.fieldName)
|
||||
.filter((fld) => typeof fld == "string");
|
||||
|
||||
if (type.name == "after_insert") {
|
||||
sql += ` INSERT INTO ${dstDbSchema.dbFullName}.${dstTableSchema.tableName}`;
|
||||
sql += ` (${dstColumns.join(",")})`;
|
||||
sql += ` VALUES (${dstColumns.map((c) => `NEW.${c}`).join(",")})`;
|
||||
} else if (type.name == "after_update") {
|
||||
sql += ` UPDATE ${dstDbSchema.dbFullName}.${dstTableSchema.tableName}`;
|
||||
sql += ` SET ${dstColumns.map((c) => `${c}=NEW.${c}`).join(",")}`;
|
||||
sql += ` WHERE id = NEW.id`;
|
||||
} else if (type.name == "after_delete") {
|
||||
sql += ` DELETE FROM ${dstDbSchema.dbFullName}.${dstTableSchema.tableName}`;
|
||||
sql += ` WHERE id = OLD.id`;
|
||||
}
|
||||
|
||||
return triggerSQLGen({
|
||||
content: sql,
|
||||
srcDbSchema,
|
||||
srcTableSchema,
|
||||
type,
|
||||
paradigm,
|
||||
userId,
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
```sql
|
||||
DELIMITER //
|
||||
|
||||
CREATE PROCEDURE dsql_replicate_two_tables(
|
||||
IN source_db VARCHAR(64),
|
||||
IN target_db VARCHAR(64),
|
||||
IN source_table VARCHAR(64),
|
||||
IN target_table VARCHAR(64)
|
||||
)
|
||||
BEGIN
|
||||
-- Declare variables
|
||||
DECLARE column_list TEXT;
|
||||
DECLARE set_clause TEXT;
|
||||
DECLARE trigger_sql TEXT;
|
||||
|
||||
-- Start transaction to ensure consistency
|
||||
START TRANSACTION;
|
||||
|
||||
-- Dynamically get column names for the source table
|
||||
SELECT GROUP_CONCAT(CONCAT('NEW.', COLUMN_NAME))
|
||||
INTO column_list
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = source_db
|
||||
AND TABLE_NAME = source_table;
|
||||
|
||||
SELECT GROUP_CONCAT(CONCAT(COLUMN_NAME, '=NEW.', COLUMN_NAME))
|
||||
INTO set_clause
|
||||
FROM INFORMATION_SCHEMA.COLUMNS
|
||||
WHERE TABLE_SCHEMA = source_db
|
||||
AND TABLE_NAME = source_table;
|
||||
|
||||
-- Drop existing triggers if they exist
|
||||
SET @drop_trigger_insert = CONCAT('DROP TRIGGER IF EXISTS after_insert_', source_table);
|
||||
SET @drop_trigger_update = CONCAT('DROP TRIGGER IF EXISTS after_update_', source_table);
|
||||
SET @drop_trigger_delete = CONCAT('DROP TRIGGER IF EXISTS after_delete_', source_table);
|
||||
PREPARE stmt_drop_insert FROM @drop_trigger_insert;
|
||||
EXECUTE stmt_drop_insert;
|
||||
DEALLOCATE PREPARE stmt_drop_insert;
|
||||
PREPARE stmt_drop_update FROM @drop_trigger_update;
|
||||
EXECUTE stmt_drop_update;
|
||||
DEALLOCATE PREPARE stmt_drop_update;
|
||||
PREPARE stmt_drop_delete FROM @drop_trigger_delete;
|
||||
EXECUTE stmt_drop_delete;
|
||||
DEALLOCATE PREPARE stmt_drop_delete;
|
||||
|
||||
-- Create INSERT trigger
|
||||
SET @trigger_sql = CONCAT(
|
||||
'CREATE TRIGGER after_insert_', source_table,
|
||||
' AFTER INSERT ON ', source_db, '.', source_table, ' FOR EACH ROW ',
|
||||
'BEGIN ',
|
||||
'INSERT INTO ', target_db, '.', target_table, ' (',
|
||||
(SELECT GROUP_CONCAT(COLUMN_NAME) FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = source_db AND TABLE_NAME = source_table), ') ',
|
||||
'VALUES (', column_list, '); ',
|
||||
'END;'
|
||||
);
|
||||
PREPARE stmt FROM @trigger_sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Create UPDATE trigger
|
||||
-- Assume 'id' as the primary key; adjust if different
|
||||
SET @trigger_sql = CONCAT(
|
||||
'CREATE TRIGGER after_update_', source_table,
|
||||
' AFTER UPDATE ON ', source_db, '.', source_table, ' FOR EACH ROW ',
|
||||
'BEGIN ',
|
||||
'UPDATE ', target_db, '.', target_table, ' SET ',
|
||||
set_clause,
|
||||
' WHERE id = NEW.id; ',
|
||||
'END;'
|
||||
);
|
||||
PREPARE stmt FROM @trigger_sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
-- Create DELETE trigger
|
||||
SET @trigger_sql = CONCAT(
|
||||
'CREATE TRIGGER after_delete_', source_table,
|
||||
' AFTER DELETE ON ', source_db, '.', source_table, ' FOR EACH ROW ',
|
||||
'BEGIN ',
|
||||
'DELETE FROM ', target_db, '.', target_table, ' WHERE id = OLD.id; ',
|
||||
'END;'
|
||||
);
|
||||
PREPARE stmt FROM @trigger_sql;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
COMMIT;
|
||||
|
||||
END //
|
||||
|
||||
DELIMITER ;
|
||||
```
|
||||
@@ -0,0 +1,53 @@
|
||||
import { DSQL_DatabaseSchemaType, DSQL_TableSchemaType } from "../../../types";
|
||||
import grabTriggerName, { TriggerParadigms } from "./grab-trigger-name";
|
||||
|
||||
const TriggerTypes = [
|
||||
{
|
||||
name: "after_insert",
|
||||
value: "INSERT",
|
||||
},
|
||||
{
|
||||
name: "after_update",
|
||||
value: "UPDATE",
|
||||
},
|
||||
{
|
||||
name: "after_delete",
|
||||
value: "DELETE",
|
||||
},
|
||||
] as const;
|
||||
|
||||
export type TriggerSQLGenParams = {
|
||||
type: (typeof TriggerTypes)[number];
|
||||
srcDbSchema: DSQL_DatabaseSchemaType;
|
||||
srcTableSchema: DSQL_TableSchemaType;
|
||||
content: string;
|
||||
userId?: string | number;
|
||||
paradigm: (typeof TriggerParadigms)[number];
|
||||
};
|
||||
|
||||
export default function triggerSQLGen({
|
||||
type,
|
||||
srcDbSchema,
|
||||
srcTableSchema,
|
||||
content,
|
||||
userId,
|
||||
paradigm,
|
||||
}: TriggerSQLGenParams) {
|
||||
let sql = `CREATE TRIGGER`;
|
||||
|
||||
let triggerName = grabTriggerName({
|
||||
paradigm,
|
||||
dbId: srcDbSchema.id,
|
||||
tableName: srcTableSchema.tableName,
|
||||
userId,
|
||||
});
|
||||
|
||||
sql += ` ${triggerName}`;
|
||||
sql += ` AFTER ${type.value} ON ${srcTableSchema.tableName}`;
|
||||
sql += ` FOR EACH ROW BEGIN`;
|
||||
|
||||
sql += ` ${content}`;
|
||||
sql += ` END`;
|
||||
|
||||
return sql;
|
||||
}
|
||||
Reference in New Issue
Block a user