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; }