polardbxengine/router/tests/component/data/local_modules/common_statements.js

579 lines
17 KiB
JavaScript

var defaults = {
version_comment: "community",
account_user: "root",
metadata_schema_version: [1, 0, 1],
exec_time: 0.0,
group_replication_single_primary_mode: 1,
// array-of-array
// - server-uuid
// - hostname
// - port
// - state
// - xport (if available and needed)
group_replication_membership: [],
port: mysqld.session.port,
innodb_cluster_name: "test",
innodb_cluster_replicaset_name: "default",
use_bootstrap_big_data: false,
replication_group_members: [],
innodb_cluster_insances: [],
innodb_cluster_hosts: [],
innodb_cluster_user_hosts: [],
bootstrap_report_host_pattern: ".*",
user_host_pattern: ".*",
};
function ensure_type(options, field, expected_type) {
var current_type = typeof(options[field]);
if (expected_type === "array") {
tested_type = "object";
} else {
tested_type = expected_type;
}
if (current_type !== tested_type) throw "expected " + field + " to be a " + expected_type + ", got " + current_type;
if (expected_type === "array") {
if (!Array.isArray(options[field])) throw "expected " + field + " to be a " + expected_type + ", got " + current_type;
}
}
/**
* create response for commonly used statements
*
* @param {string} stmt_key statement key
* @param {object} [options] options replacement values for statement text and response
* @returns On success, response object, otherwise 'undefined'
*/
exports.get = function get(stmt_key, options) {
// let 'options' overwrite the 'defaults'
options = Object.assign({}, defaults, options);
ensure_type(options, "version_comment", "string");
ensure_type(options, "account_user", "string");
ensure_type(options, "metadata_schema_version", "array");
ensure_type(options, "exec_time", "number");
ensure_type(options, "port", "number");
var statements = {
mysql_client_select_version_comment: {
stmt: "select @@version_comment limit 1",
exec_time: options["exec_time"],
result: {
columns: [
{
name: "@@version_comment",
type: "STRING"
}
],
rows: [
[ options["version_comment"] ]
]
}
},
mysql_client_select_user: {
stmt: "select USER()",
result: {
columns: [
{
name: "USER()",
type: "STRING"
}
],
rows: [
[ options["account_user"] ]
]
}
},
select_port: {
stmt: "select @@port",
result: {
columns: [
{
name: "@@port",
type: "LONG"
}
],
rows: [
[ options["port"] ]
]
}
},
router_select_schema_version: {
stmt: "SELECT * FROM mysql_innodb_cluster_metadata.schema_version",
exec_time: options["exec_time"],
result: {
columns: [
{
type: "LONGLONG",
name: "major"
},
{
type: "LONGLONG",
name: "minor"
},
{
type: "LONGLONG",
name: "patch"
}
],
rows: [
options["metadata_schema_version"]
]
}
},
router_select_group_membership_with_primary_mode: {
stmt: "SELECT member_id, member_host, member_port, member_state, @@group_replication_single_primary_mode FROM performance_schema.replication_group_members WHERE channel_name = 'group_replication_applier'",
exec_time: options["exec_time"],
result: {
columns: [
{
"name": "member_id",
"type": "STRING"
},
{
"name": "member_host",
"type": "STRING"
},
{
"name": "member_port",
"type": "LONG"
},
{
"name": "member_state",
"type": "STRING"
},
{
"name": "@@group_replication_single_primary_mode",
"type": "LONGLONG"
}
],
rows: options["group_replication_membership"].map(function(currentValue) {
var result = currentValue.slice();
// if group_replication_membership contains x port we need to remove it
// as this query does not want it
if (result.length === 5)
result.splice(-1,1);
return result.concat([ options["group_replication_single_primary_mode"] ]);
}),
}
},
router_select_group_replication_primary_member: {
"stmt": "show status like 'group_replication_primary_member'",
"result": {
"columns": [
{
"name": "Variable_name",
"type": "VAR_STRING"
},
{
"name": "Value",
"type": "VAR_STRING"
}
],
"rows": [
[
"group_replication_primary_member",
options["group_replication_primary_member"]
]
]
}
},
router_select_metadata: {
stmt: "SELECT R.replicaset_name, I.mysql_server_uuid, I.role, I.weight, I.version_token, I.addresses->>'$.mysqlClassic', I.addresses->>'$.mysqlX' FROM mysql_innodb_cluster_metadata.clusters AS F JOIN mysql_innodb_cluster_metadata.replicasets AS R ON F.cluster_id = R.cluster_id JOIN mysql_innodb_cluster_metadata.instances AS I"
+ " ON R.replicaset_id = I.replicaset_id WHERE F.cluster_name = '"
+ options.innodb_cluster_name + "'"
+ (options.gr_id === undefined || options.gr_id === "" ? "" : (" AND R.attributes->>'$.group_replication_group_name' = '" + options.gr_id + "'"))
+ ";",
result : {
columns : [
{
"name": "replicaset_name",
"type": "VAR_STRING"
},
{
"name": "mysql_server_uuid",
"type": "VAR_STRING"
},
{
"name": "role",
"type": "STRING"
},
{
"name": "weight",
"type": "FLOAT"
},
{
"name": "version_token",
"type": "LONG"
},
{
"name": "I.addresses->>'$.mysqlClassic'",
"type": "LONGBLOB"
},
{
"name": "I.addresses->>'$.mysqlX'",
"type": "LONGBLOB"
}
],
rows: options["group_replication_membership"].map(function(currentValue) {
return [
options.innodb_cluster_replicaset_name,
currentValue[0],
"HA",
null,
null,
currentValue[1] + ":" + currentValue[2],
currentValue[1] + ":" + currentValue[4]
]
}),
}
},
router_count_clusters_and_replicasets: {
stmt: "SELECT ((SELECT count(*) FROM mysql_innodb_cluster_metadata.clusters) <= 1 AND (SELECT count(*) FROM mysql_innodb_cluster_metadata.replicasets) <= 1) as has_one_replicaset, (SELECT attributes->>'$.group_replication_group_name' FROM mysql_innodb_cluster_metadata.replicasets) = @@group_replication_group_name as replicaset_is_ours",
result: {
columns: [
{
"type": "LONGLONG",
"name": "has_one_replicaset"
},
{
"type": "LONGLONG",
"name": "replicaset_is_ours"
}
],
rows: [
[
1,
1
]
]
}
},
router_check_member_state:
{
stmt: "SELECT member_state FROM performance_schema.replication_group_members WHERE member_id = @@server_uuid",
result: {
columns: [
{
"type": "STRING",
"name": "member_state"
}
],
rows: [
[
"ONLINE"
]
]
}
},
router_select_members_count:
{
"stmt": "SELECT SUM(IF(member_state = 'ONLINE', 1, 0)) as num_onlines, COUNT(*) as num_total FROM performance_schema.replication_group_members",
"result": {
"columns": [
{
"type": "LONGLONG",
"name": "num_onlines"
},
{
"type": "LONGLONG",
"name": "num_total"
}
],
"rows": [
[
3,
3
]
]
}
},
router_select_replication_group_name:
{
"stmt": "select @@group_replication_group_name",
"result": {
"columns": [
{
"type": "STRING",
"name": "@@group_replication_group_name"
}
],
"rows": [
[
"replication-1"
]
]
}
},
router_show_cipher_status:
{
"stmt": "show status like 'ssl_cipher'",
"result": {
"columns": [
{
"type": "STRING",
"name": "Variable_name"
},
{
"type": "STRING",
"name": "Value"
}
],
"rows": [
[
"Ssl_cipher",
""
]
]
}
},
router_select_cluster_instances:
{
"stmt": "SELECT F.cluster_name, R.replicaset_name, JSON_UNQUOTE(JSON_EXTRACT(I.addresses, '$.mysqlClassic')) FROM mysql_innodb_cluster_metadata.clusters AS F, mysql_innodb_cluster_metadata.instances AS I, mysql_innodb_cluster_metadata.replicasets AS R WHERE R.replicaset_id = (SELECT replicaset_id FROM mysql_innodb_cluster_metadata.instances WHERE mysql_server_uuid = @@server_uuid)AND I.replicaset_id = R.replicaset_id AND R.cluster_id = F.cluster_id",
"result": {
"columns": [
{
"type": "LONGLONG",
"name": "cluster_name"
},
{
"type": "STRING",
"name": "replicaset_name"
},
{
"type": "STRING",
"name": "JSON_UNQUOTE(JSON_EXTRACT(I.addresses, '$.mysqlClassic'))"
}
],
rows: options["innodb_cluster_insances"].map(function(currentValue) {
return [
options.innodb_cluster_cluster_name,
options.innodb_cluster_replicaset_name,
currentValue[0] + ":" + currentValue[1],
]
})
}
},
router_start_transaction:
{
"stmt": "START TRANSACTION",
"ok": {}
},
router_select_hosts:
{
stmt_regex: "^SELECT host_id, host_name, ip_address FROM mysql_innodb_cluster_metadata.hosts WHERE host_name = '"
+ options.bootstrap_report_host_pattern + "' LIMIT 1",
result: {
columns: [
{
"type": "STRING",
"name": "host_id"
},
{
"type": "STRING",
"name": "host_name"
},
{
"type": "STRING",
"name": "ip_address"
}
],
rows: options["innodb_cluster_hosts"].map(function(currentValue) {
return [
currentValue[0], currentValue[1], currentValue[2]
]
})
}
},
router_select_hosts_join_routers:
{
stmt_regex: "SELECT h.host_id, h.host_name FROM mysql_innodb_cluster_metadata.routers r JOIN mysql_innodb_cluster_metadata.hosts h ON r.host_id = h.host_id WHERE r.router_id = .*",
result: {
columns: [
{
"type": "STRING",
"name": "host_id"
},
{
"type": "STRING",
"name": "host_name"
}
],
rows: options["innodb_cluster_hosts"].map(function(currentValue) {
return [
currentValue[0], currentValue[1]
]
})
}
},
router_insert_into_hosts:
{
"stmt_regex": "^INSERT INTO mysql_innodb_cluster_metadata.hosts \\(host_name, location, attributes\\) VALUES \\('"
+ options.bootstrap_report_host_pattern + "',.*",
"ok": {
"last_insert_id": 1
}
},
router_insert_into_routers:
{
"stmt_regex": "^INSERT INTO mysql_innodb_cluster_metadata.routers.*",
"ok": {
"last_insert_id": 1
}
},
// delete all old accounts if necessarry (ConfigGenerator::delete_account_for_all_hosts())
router_delete_old_accounts:
{
"stmt_regex": "^SELECT host FROM mysql.user WHERE user = '.*'",
"result": {
"columns": [
{
"type": "LONGLONG",
"name": "COUNT..."
}
],
"rows": options["innodb_cluster_user_hosts"],
}
},
router_create_user:
{
"stmt_regex": "^CREATE USER 'mysql_router1_[0-9a-z]{12}'@"
+ options.user_host_pattern
+ " IDENTIFIED WITH mysql_native_password AS '\\*[0-9A-Z]{40}'",
"ok": {}
},
router_grant_on_metadata_db:
{
"stmt_regex": "^GRANT SELECT ON mysql_innodb_cluster_metadata.*"
+ options.user_host_pattern,
"ok": {}
},
router_grant_on_pfs_db:
{
"stmt_regex": "^GRANT SELECT ON performance_schema.*"
+ options.user_host_pattern,
"ok": {}
},
router_update_routers_in_metadata:
{
"stmt_regex": "^UPDATE mysql_innodb_cluster_metadata\\.routers.*",
"ok": {}
},
router_commit:
{
stmt: "COMMIT",
ok: {}
},
router_rollback:
{
stmt: "ROLLBACK",
ok: {}
},
router_replication_group_members:
{
stmt: "SELECT member_host, member_port FROM performance_schema.replication_group_members /*!80002 ORDER BY member_role */",
result: {
columns: [
{
"type": "STRING",
"name": "member_host"
},
{
"type": "LONG",
"name": "member_port"
}
],
rows: options["replication_group_members"].map(function(currentValue) {
return [
currentValue[0], currentValue[1],
]
}
)
}
},
router_drop_users:
{
stmt_regex: "^DROP USER mysql_router.*",
ok: {}
},
};
return statements[stmt_key];
}
/**
* create the response for commonly used statements
*
* @param {array} stmt_keys - statement keys
* @param {array} options - parameters
* @returns {object} object of 'statement text': response object
*/
exports.prepare_statement_responses = function(stmt_keys, options) {
return stmt_keys.reduce(function(acc, stmt_key) {
// lookup the results by stmt_key
var res = exports.get(stmt_key, options);
acc[res.stmt] = res;
return acc;
}, {});
}
/**
* create the response for commonly used regex statements
*
* @param {array} stmt_keys - statement keys
* @param {array} options - parameters
* @returns {object} object of 'statement text': response object
*/
exports.prepare_statement_responses_regex = function(stmt_keys, options) {
return stmt_keys.reduce(function(acc, stmt_key) {
// lookup the results by stmt_key
var res = exports.get(stmt_key, options);
acc[res.stmt_regex] = res;
return acc;
}, {});
}
/**
* create error-response for unknown statements
*
* @param {string} stmt statement text
* @returns error response
*/
exports.unknown_statement_response = function(stmt) {
return {
error: {
code: 1273,
sql_state: "HY001",
message: "Syntax Error at: " + stmt
}
}
}
/**
* checks if a given statment matches any stmt_regex in
* in the responses object
*
* @param {string} regex_stmt regex statement text
* @param {object} common_responses_regex object containing common responses
* @returns response if any matches the statmenet or undefined
*/
exports.handle_regex_stmt = function(regex_stmt, common_responses_regex) {
for (var stmt in common_responses_regex) {
if (regex_stmt.match(stmt))
return common_responses_regex[stmt];
}
return undefined;
};