unittest/scripts/setup_js/dump_utils.inc (196 lines of code) (raw):
function md5_table(session, schema, table, where = "", partitions = []) {
const columns = [];
const has_pri = 0 != session.runSql("SELECT COUNT(*) FROM information_schema.statistics WHERE index_name = 'PRIMARY' AND table_schema = ? AND table_name = ?", [schema, table]).fetchOne()[0];
for (const c of session.runSql("desc !.!", [schema, table]).fetchAll()) {
columns.push(c[0]);
}
var query = `SELECT @crc := sha1(concat(@crc, sha1(concat_ws('#', ${columns.map((c) => 'convert(! using binary)').join(', ')})))),@cnt := @cnt + 1 as discard from !.!`;
const params = [];
params.push(...columns);
params.push(schema, table);
if (partitions.length) {
query += ` PARTITION (${partitions.map((p) => '!').join(', ')})`;
params.push(...partitions);
}
if (has_pri) {
query += " use index(PRIMARY)";
}
if (where) {
query += " WHERE ";
query += where;
}
if (!has_pri) {
query += ` ORDER BY ${columns.map((c) => '!').join(', ')}`;
params.push(...columns);
}
session.runSql("SET @crc = ''");
session.runSql("SET @cnt = 0");
session.runSql(query, params);
const row = session.runSql("select @crc, @cnt").fetchOne();
return {"sha1": row[0], "count": row[1]};
}
function snapshot_account(session, auser, ahost) {
user={}
user["create"]=session.runSql("SHOW CREATE USER ?@?", [auser, ahost]).fetchOne()[0];
user["grants"]=[];
gres=session.runSql("SHOW GRANTS FOR ?@?", [auser, ahost]);
row=gres.fetchOne();
while(row) {
user["grants"].push(row[0]);
row=gres.fetchOne();
}
return user;
}
function snapshot_accounts(session) {
accounts={};
var res=session.runSql("SELECT user,host FROM mysql.user").fetchAll();
for(r in res) {
user=snapshot_account(session, res[r][0], res[r][1]);
name=res[r][0]+"@"+res[r][1];
accounts[name]=user;
}
return accounts;
}
function snapshot_table_data(session, schema, table) {
// CHECKSUM TABLE returns different values for floating point values when they're loaded with LOAD DATA
// Bug#31071891
// cksum = session.runSql("CHECKSUM TABLE `"+schema+"`.`"+table+"`").fetchOne()[1];
// count = session.runSql("SELECT count(*) FROM `"+schema+"`.`"+table+"`").fetchOne()[0];
// return {"checksum":cksum, "rowcount":count};
return md5_table(session, schema, table);
}
function snapshot_tables_and_triggers(session, schema) {
var tables={};
var names=session.runSql("SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = ? and table_type = 'BASE TABLE'", [schema]).fetchAll();
for(t in names) {
var tname=names[t]["TABLE_NAME"];
tables[tname]=snapshot_table_data(session, schema, tname);
tables[tname]["ddl"]=session.runSql("SHOW CREATE TABLE `"+schema+"`.`"+tname+"`").fetchOne()[1];
// on Windows "SHOW CREATE" keeps adding slashes at the end of a DATA|INDEX directory, mitigate that
tables[tname]["ddl"] = tables[tname]["ddl"].replace(/\/+/g, "/")
var res=session.runSql("SELECT trigger_name FROM information_schema.triggers WHERE trigger_schema = ? and event_object_table = ?", [schema, tname]).fetchAll();
var triggers={};
for(tr in res) {
var trname=res[tr][0];
triggers[trname]=session.runSql("SHOW CREATE TRIGGER `"+schema+"`.`"+trname+"`").fetchOne()[1];
}
tables[tname]["triggers"]=triggers;
}
return tables;
}
function snapshot_views(session, schema) {
var tables={};
var names=session.runSql("SELECT TABLE_NAME FROM information_schema.tables WHERE table_schema = ? and table_type = 'VIEW'", [schema]).fetchAll();
for(t in names) {
var tname=names[t]["TABLE_NAME"];
tables[tname]={};
tables[tname]["ddl"]=session.runSql("SHOW CREATE VIEW `"+schema+"`.`"+tname+"`").fetchOne()[1];
}
return tables;
}
function snapshot_procedures(session, schema) {
var procedures={};
var names=session.runSql("SELECT * FROM information_schema.routines WHERE routine_schema = ? and routine_type = 'PROCEDURE'", [schema]).fetchAll();
for(t in names) {
var tname=names[t]["ROUTINE_NAME"];
procedures[tname]={};
procedures[tname]["ddl"]=session.runSql("SHOW CREATE PROCEDURE `"+schema+"`.`"+tname+"`").fetchOne()[1];
}
return procedures;
}
function snapshot_functions(session, schema) {
var functions={};
var names=session.runSql("SELECT * FROM information_schema.routines WHERE routine_schema = ? and routine_type = 'FUNCTION'", [schema]).fetchAll();
for(t in names) {
var tname=names[t]["ROUTINE_NAME"];
functions[tname]={};
functions[tname]["ddl"]=session.runSql("SHOW CREATE FUNCTION `"+schema+"`.`"+tname+"`").fetchOne()[1];
}
return functions;
}
function snapshot_events(session, schema) {
var events={};
var names=session.runSql("SHOW EVENTS IN `"+schema+"`").fetchAll();
for(t in names) {
var tname=names[t]["Name"];
events[tname]={};
events[tname]["ddl"]=session.runSql("SHOW CREATE EVENT `"+schema+"`.`"+tname+"`").fetchOne()[1];
}
return events;
}
function snapshot_schema(session, schema) {
var obj={};
obj["tables"]=snapshot_tables_and_triggers(session, schema);
obj["views"]=snapshot_views(session, schema);
obj["procedures"]=snapshot_procedures(session, schema);
obj["functions"]=snapshot_functions(session, schema);
obj["events"]=snapshot_events(session, schema);
return obj;
}
function snapshot_schemas(session) {
var schemas={};
var names=session.runSql("SELECT * FROM information_schema.schemata WHERE schema_name not in ('sys', 'information_schema', 'mysql', 'performance_schema')").fetchAll();
for(s in names) {
var sname=names[s]["SCHEMA_NAME"];
ddl=session.runSql("SHOW CREATE SCHEMA `"+sname+"`").fetchOne()[1];
schemas[sname]=snapshot_schema(session, sname);
schemas[sname]["ddl"]=ddl;
}
return schemas;
}
function snapshot_tablespaces(session) {
// not supported atm
return {};
}
function snapshot_instance(session) {
var snapshot={};
snapshot["accounts"]=snapshot_accounts(session);
snapshot["tablespaces"]=snapshot_tablespaces(session);
snapshot["schemas"]=snapshot_schemas(session);
// normalize the JSON encoding
return JSON.parse(JSON.stringify(snapshot));
}
function strip_keys(obj, keys) {
obj=Object.assign({}, obj);
for(k in keys) {
delete obj[keys[k]];
}
return obj;
}
function strip_snapshot_data(snapshot) {
copy=JSON.parse(JSON.stringify(snapshot));
for(s in copy["schemas"]) {
var tables=copy["schemas"][s]["tables"];
for(t in tables) {
delete tables[t]["count"];
delete tables[t]["sha1"];
}
}
return copy;
}
function wipe_instance(session) {
session.runSql("set foreign_key_checks=0");
var r=session.runSql("SHOW SCHEMAS");
var rows=r.fetchAll();
for(var i in rows) {
var row=rows[i];
if(["mysql", "performance_schema", "sys", "information_schema"].includes(row[0]))
continue;
session.runSql("DROP SCHEMA "+row[0]);
}
var r=session.runSql("SELECT user,host FROM mysql.user");
var rows=r.fetchAll();
for(var i in rows) {
var row=rows[i];
if(["mysql.sys", "mysql.session", "mysql.infoschema"].includes(row[0]))
continue;
if(row[0]=="root"&&(row[1]=="localhost"||row[1]=="%"))
continue;
session.runSql("DROP USER ?@?", [row[0], row[1]]);
}
session.runSql("RESET MASTER");
session.runSql("RESET SLAVE ALL");
session.runSql("set foreign_key_checks=1");
}
function quote_identifier(schema, object = undefined) {
function quote(identifier) {
return "`" + identifier.replaceAll('`', '``') + "`";
}
var ret = quote(schema);
if (object !== undefined) {
ret += "." + quote(object);
}
return ret;
}