From 2844d18d4c8d3293f24ef28635b69253ebe5ce25 Mon Sep 17 00:00:00 2001 From: Rene Krenn Date: Wed, 6 Apr 2016 12:26:30 +0200 Subject: [PATCH] MT#17795 cdr fields for balance id, cash/freetime before/after, package id -original ALTER TABLE accounting.cdr is refactored by introducing first set of separate entity-attribute-value tables. hot-fixable, no downtimes. -further refactored to extract "provider" and "direction" columns elements (n=2) to manage values in data tables in a n-dimensional mannor. it turns out rateomats column model implementation will get complex to support data tables for arbitrary dimensions n. -updated table names, removed autoinc staring values (ids cannot be distinguished in data tables any more) -removed IF NOT/EXISTS -added GRANTs for 'exporter'@'localhost' MT#17795: Melita needs the billing profile package id tracked in cdrs. Note that this is the package assigned to the contract at the time rate-o-mat processes the cdr (no history!), which also specifies the interval for creating balance interval records. *_*_profile_package_id int(11) unsigned MT#17795: Link to the balance interval (billing.contract_balances record) for the sake of completeness. It might also be useful for invoice generation (MT#14253). *_*_contract_balance_id int(11) unsigned MT#17795: The balance interval's cash balance values before and after rating the call. *_*_cash_balance_before decimal(14,6) *_*_cash_balance_after decimal(14,6) MT#17795: The balance interval's free time balance values before and after rating the call. *_*_free_time_balance_before int(10) unsigned *_*_free_time_balance_after int(10) unsigned Change-Id: Ie891fc13a3610f4cdd9a57ccc573cc395c4e3729 --- db_scripts/diff/15236.down | 26 ++++++++ db_scripts/diff/15236.up | 131 +++++++++++++++++++++++++++++++++++++ db_scripts/diff/15237.down | 7 ++ db_scripts/diff/15237.up | 105 +++++++++++++++++++++++++++++ 4 files changed, 269 insertions(+) create mode 100644 db_scripts/diff/15236.down create mode 100644 db_scripts/diff/15236.up create mode 100644 db_scripts/diff/15237.down create mode 100644 db_scripts/diff/15237.up diff --git a/db_scripts/diff/15236.down b/db_scripts/diff/15236.down new file mode 100644 index 00000000..05556ab7 --- /dev/null +++ b/db_scripts/diff/15236.down @@ -0,0 +1,26 @@ +#only DDL stmts with implicit commits + +REVOKE SELECT ON accounting.cdr_direction FROM 'exporter'@'localhost'; + +REVOKE SELECT ON accounting.cdr_provider FROM 'exporter'@'localhost'; + +REVOKE SELECT ON accounting.cdr_cash_balance FROM 'exporter'@'localhost'; +REVOKE SELECT ON accounting.cdr_cash_balance_data FROM 'exporter'@'localhost'; + +REVOKE SELECT ON accounting.cdr_time_balance FROM 'exporter'@'localhost'; +REVOKE SELECT ON accounting.cdr_time_balance_data FROM 'exporter'@'localhost'; + +REVOKE SELECT ON accounting.cdr_relation FROM 'exporter'@'localhost'; +REVOKE SELECT ON accounting.cdr_relation_data FROM 'exporter'@'localhost'; + +DROP TABLE accounting.cdr_cash_balance_data; +DROP TABLE accounting.cdr_cash_balance; + +DROP TABLE accounting.cdr_time_balance_data; +DROP TABLE accounting.cdr_time_balance; + +DROP TABLE accounting.cdr_relation_data; +DROP TABLE accounting.cdr_relation; + +DROP TABLE accounting.cdr_provider; +DROP TABLE accounting.cdr_direction; \ No newline at end of file diff --git a/db_scripts/diff/15236.up b/db_scripts/diff/15236.up new file mode 100644 index 00000000..ed7575be --- /dev/null +++ b/db_scripts/diff/15236.up @@ -0,0 +1,131 @@ +SET autocommit=0; #not only DDL stmts +CREATE TABLE accounting.cdr_provider ( + id int(3) unsigned NOT NULL AUTO_INCREMENT, + type ENUM( + 'carrier', + 'reseller', + 'customer' + ) NOT NULL, + PRIMARY KEY (id), + UNIQUE KEY cpc_type_idx (type) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO accounting.cdr_provider SET id=null, type='carrier'; +INSERT INTO accounting.cdr_provider SET id=null, type='reseller'; +INSERT INTO accounting.cdr_provider SET id=null, type='customer'; + +CREATE TABLE accounting.cdr_direction ( #implicit commit + id int(3) unsigned NOT NULL AUTO_INCREMENT, + type ENUM( + 'source', + 'destination' + ) NOT NULL, + PRIMARY KEY (id), + UNIQUE KEY cdc_type_idx (type) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; +#the name "direction" for "source" and "destination" is still not ideal, +#it must not be confused with a fee record's 'in' and 'out'. +INSERT INTO accounting.cdr_direction SET id=null, type='source'; +INSERT INTO accounting.cdr_direction SET id=null, type='destination'; + +CREATE TABLE accounting.cdr_cash_balance ( #implicit commit + id int(3) unsigned NOT NULL AUTO_INCREMENT, + type ENUM( + 'cash_balance' + ) NOT NULL, + PRIMARY KEY (id), + UNIQUE KEY ccbc_type_idx (type) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO accounting.cdr_cash_balance SET id=null, type='cash_balance'; + +CREATE TABLE accounting.cdr_time_balance ( #implicit commit + id int(3) unsigned NOT NULL AUTO_INCREMENT, + type ENUM( + 'free_time_balance' + ) NOT NULL, + PRIMARY KEY (id), + UNIQUE KEY ctbc_type_idx (type) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO accounting.cdr_time_balance SET id=null, type='free_time_balance'; + +CREATE TABLE accounting.cdr_relation ( + id int(3) unsigned NOT NULL AUTO_INCREMENT, + type ENUM( + 'profile_package_id', + 'contract_balance_id' + ) NOT NULL, + #ref varchar(255) DEFAULT NULL, #e.g. "billing.contract_balances.id" + PRIMARY KEY (id), + UNIQUE KEY crc_type_idx (type) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +INSERT INTO accounting.cdr_relation SET id=null, type='profile_package_id'; +INSERT INTO accounting.cdr_relation SET id=null, type='contract_balance_id'; + +#up to 4 times the cardinality of accounting.cdr: +CREATE TABLE accounting.cdr_cash_balance_data ( #implicit commit + cdr_id int(10) unsigned NOT NULL, + provider_id int(3) unsigned NOT NULL, + direction_id int(3) unsigned NOT NULL, + cash_balance_id int(3) unsigned NOT NULL, + val_before decimal(14,6) NOT NULL, + val_after decimal(14,6) NOT NULL, + cdr_start_time decimal(13,3) NOT NULL, #partitioning key, but https://bugs.mysql.com/bug.php?id=72274 + PRIMARY KEY (cdr_id, provider_id, direction_id, cash_balance_id, cdr_start_time) + ## Partitioned tables using the InnoDB storage engine do not support foreign keys. + #,FOREIGN KEY (cdr_id) REFERENCES accounting.cdr(id) ON DELETE CASCADE ON UPDATE CASCADE, + #FOREIGN KEY (provider_id) REFERENCES accounting.cdr_provider(id) ON DELETE RESTRICT ON UPDATE RESTRICT, + #FOREIGN KEY (direction_id) REFERENCES accounting.cdr_direction(id) ON DELETE RESTRICT ON UPDATE RESTRICT, + #FOREIGN KEY (cash_balance_id) REFERENCES accounting.cdr_cash_balance(id) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +#up to 4 times the cardinality of accounting.cdr: +CREATE TABLE accounting.cdr_time_balance_data ( + cdr_id int(10) unsigned NOT NULL, + provider_id int(3) unsigned NOT NULL, + direction_id int(3) unsigned NOT NULL, + time_balance_id int(3) unsigned NOT NULL, + val_before int(10) unsigned NOT NULL, + val_after int(10) unsigned NOT NULL, + cdr_start_time decimal(13,3) NOT NULL, #partitioning key, but https://bugs.mysql.com/bug.php?id=72274 + PRIMARY KEY (cdr_id, provider_id, direction_id, time_balance_id, cdr_start_time) + ## Partitioned tables using the InnoDB storage engine do not support foreign keys. + #,FOREIGN KEY (cdr_id) REFERENCES accounting.cdr(id) ON DELETE CASCADE ON UPDATE CASCADE, + #FOREIGN KEY (provider_id) REFERENCES accounting.cdr_provider(id) ON DELETE RESTRICT ON UPDATE RESTRICT, + #FOREIGN KEY (direction_id) REFERENCES accounting.cdr_direction(id) ON DELETE RESTRICT ON UPDATE RESTRICT, + #FOREIGN KEY (time_balance_id) REFERENCES accounting.cdr_time_balance(id) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +#6 times the cardinality of accounting.cdr: +CREATE TABLE accounting.cdr_relation_data ( + cdr_id int(10) unsigned NOT NULL, + provider_id int(3) unsigned NOT NULL, + direction_id int(3) unsigned NOT NULL, + relation_id int(3) unsigned NOT NULL, + val int(10) unsigned NOT NULL, + cdr_start_time decimal(13,3) NOT NULL, #partitioning key, but https://bugs.mysql.com/bug.php?id=72274 + PRIMARY KEY (cdr_id, provider_id, direction_id, relation_id, cdr_start_time) + ## Partitioned tables using the InnoDB storage engine do not support foreign keys. + #,FOREIGN KEY (cdr_id) REFERENCES accounting.cdr(id) ON DELETE CASCADE ON UPDATE CASCADE, + #FOREIGN KEY (provider_id) REFERENCES accounting.cdr_provider(id) ON DELETE RESTRICT ON UPDATE RESTRICT, + #FOREIGN KEY (direction_id) REFERENCES accounting.cdr_direction(id) ON DELETE RESTRICT ON UPDATE RESTRICT, + #FOREIGN KEY (relation_id) REFERENCES accounting.cdr_relation(id) ON DELETE RESTRICT ON UPDATE RESTRICT +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +COMMIT; #final commit + +#non-transactional: +GRANT SELECT ON accounting.cdr_direction TO 'exporter'@'localhost'; + +GRANT SELECT ON accounting.cdr_provider TO 'exporter'@'localhost'; + +GRANT SELECT ON accounting.cdr_cash_balance TO 'exporter'@'localhost'; +GRANT SELECT ON accounting.cdr_cash_balance_data TO 'exporter'@'localhost'; + +GRANT SELECT ON accounting.cdr_time_balance TO 'exporter'@'localhost'; +GRANT SELECT ON accounting.cdr_time_balance_data TO 'exporter'@'localhost'; + +GRANT SELECT ON accounting.cdr_relation TO 'exporter'@'localhost'; +GRANT SELECT ON accounting.cdr_relation_data TO 'exporter'@'localhost'; \ No newline at end of file diff --git a/db_scripts/diff/15237.down b/db_scripts/diff/15237.down new file mode 100644 index 00000000..a01a12d9 --- /dev/null +++ b/db_scripts/diff/15237.down @@ -0,0 +1,7 @@ +USE accounting; + +DROP TRIGGER cdr_cascade_update_trig; +DROP TRIGGER cdr_cascade_delete_trig; +DROP TRIGGER cdr_relation_rest_cascade_delete_trig; +DROP TRIGGER cdr_provider_rest_cascade_delete_trig; +DROP TRIGGER cdr_direction_rest_cascade_delete_trig; diff --git a/db_scripts/diff/15237.up b/db_scripts/diff/15237.up new file mode 100644 index 00000000..bd182f31 --- /dev/null +++ b/db_scripts/diff/15237.up @@ -0,0 +1,105 @@ +USE accounting; + +-- cdr cascade update +DROP TRIGGER IF EXISTS cdr_cascade_update_trig; +DELIMITER ;; +CREATE TRIGGER cdr_cascade_update_trig AFTER UPDATE ON cdr + FOR EACH ROW BEGIN + + UPDATE cdr_relation_data SET cdr_id = NEW.id WHERE cdr_id = OLD.id; + UPDATE cdr_cash_balance_data SET cdr_id = NEW.id WHERE cdr_id = OLD.id; + UPDATE cdr_time_balance_data SET cdr_id = NEW.id WHERE cdr_id = OLD.id; + + END;; +DELIMITER ; + +-- cdr cascade delete +DROP TRIGGER IF EXISTS cdr_cascade_delete_trig; +DELIMITER ;; +CREATE TRIGGER cdr_cascade_delete_trig AFTER DELETE ON cdr + FOR EACH ROW BEGIN + + DELETE FROM cdr_relation_data WHERE cdr_id = OLD.id; + DELETE FROM cdr_cash_balance_data WHERE cdr_id = OLD.id; + DELETE FROM cdr_time_balance_data WHERE cdr_id = OLD.id; + + END;; +DELIMITER ; + +-- cdr_relation cascade delete restriction +DROP TRIGGER IF EXISTS cdr_relation_rest_cascade_delete_trig; +DELIMITER ;; +CREATE TRIGGER cdr_relation_rest_cascade_delete_trig BEFORE DELETE ON cdr_relation + FOR EACH ROW BEGIN + + SELECT count(relation_id) INTO @rel_count FROM cdr_relation_data WHERE relation_id = OLD.id LIMIT 1; + + IF @rel_count > 0 THEN + SET @err_msg = 'Error deleting data from accounting.cdr_relation, related data exists in accounting.cdr_relation_data'; + SIGNAL sqlstate '45000' SET message_text = @err_msg; + END IF; + + END;; +DELIMITER ; + +-- cdr_provider cascade delete restriction +DROP TRIGGER IF EXISTS cdr_provider_rest_cascade_delete_trig; +DELIMITER ;; +CREATE TRIGGER cdr_provider_rest_cascade_delete_trig BEFORE DELETE ON cdr_provider + FOR EACH ROW BEGIN + + SELECT count(provider_id) INTO @rel_prov_count + FROM cdr_relation_data WHERE provider_id = OLD.id LIMIT 1; + SELECT count(provider_id) INTO @cash_balance_prov_count + FROM cdr_cash_balance_data WHERE provider_id = OLD.id LIMIT 1; + SELECT count(provider_id) INTO @time_balance_prov_count + FROM cdr_time_balance_data WHERE provider_id = OLD.id LIMIT 1; + + IF @rel_prov_count > 0 THEN + SET @err_msg = 'Error deleting data from accounting.cdr_provider, related data exists in accounting.cdr_relation_data'; + SIGNAL sqlstate '45000' SET message_text = @err_msg; + END IF; + + IF @cash_balance_prov_count > 0 THEN + SET @err_msg = 'Error deleting data from accounting.cdr_provider, related data exists in accounting.cdr_cash_balance_data'; + SIGNAL sqlstate '45000' SET message_text = @err_msg; + END IF; + + IF @time_balance_prov_count > 0 THEN + SET @err_msg = 'Error deleting data from accounting.cdr_provider, related data exists in accounting.cdr_time_balance_data'; + SIGNAL sqlstate '45000' SET message_text = @err_msg; + END IF; + + END;; +DELIMITER ; + +-- cdr_direction cascade delete restriction +DROP TRIGGER IF EXISTS cdr_direction_rest_cascade_delete_trig; +DELIMITER ;; +CREATE TRIGGER cdr_direction_rest_cascade_delete_trig BEFORE DELETE ON cdr_direction + FOR EACH ROW BEGIN + + SELECT count(direction_id) INTO @rel_dir_count + FROM cdr_relation_data WHERE direction_id = OLD.id LIMIT 1; + SELECT count(direction_id) INTO @cash_balance_dir_count + FROM cdr_cash_balance_data WHERE direction_id = OLD.id LIMIT 1; + SELECT count(direction_id) INTO @time_balance_dir_count + FROM cdr_time_balance_data WHERE direction_id = OLD.id LIMIT 1; + + IF @rel_dir_count > 0 THEN + SET @err_msg = 'Error deleting data from accounting.cdr_direction, related data exists in accounting.cdr_relation_data'; + SIGNAL sqlstate '45000' SET message_text = @err_msg; + END IF; + + IF @cash_balance_dir_count > 0 THEN + SET @err_msg = 'Error deleting data from accounting.cdr_direction, related data exists in accounting.cdr_cash_balance_data'; + SIGNAL sqlstate '45000' SET message_text = @err_msg; + END IF; + + IF @time_balance_dir_count > 0 THEN + SET @err_msg = 'Error deleting data from accounting.cdr_direction, related data exists in accounting.cdr_time_balance_data'; + SIGNAL sqlstate '45000' SET message_text = @err_msg; + END IF; + + END;; +DELIMITER ;