Added support for fine-grained query classification which is needed for configurable support for user- and system variable execution. This is partial implementation to task MAX-242. Tests passed with make -C server/modules/routing/readwritesplit/test but this is intermediate commit.
This commit is contained in:
@ -406,9 +406,9 @@ return_here:
|
|||||||
* restrictive, for example, QUERY_TYPE_READ is smaller than QUERY_TYPE_WRITE.
|
* restrictive, for example, QUERY_TYPE_READ is smaller than QUERY_TYPE_WRITE.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
static u_int16_t set_query_type(
|
static u_int32_t set_query_type(
|
||||||
u_int16_t* qtype,
|
u_int32_t* qtype,
|
||||||
u_int16_t new_type)
|
u_int32_t new_type)
|
||||||
{
|
{
|
||||||
*qtype = MAX(*qtype, new_type);
|
*qtype = MAX(*qtype, new_type);
|
||||||
return *qtype;
|
return *qtype;
|
||||||
@ -434,7 +434,7 @@ static skygw_query_type_t resolve_query_type(
|
|||||||
THD* thd)
|
THD* thd)
|
||||||
{
|
{
|
||||||
skygw_query_type_t qtype = QUERY_TYPE_UNKNOWN;
|
skygw_query_type_t qtype = QUERY_TYPE_UNKNOWN;
|
||||||
u_int16_t type = QUERY_TYPE_UNKNOWN;
|
u_int32_t type = QUERY_TYPE_UNKNOWN;
|
||||||
int set_autocommit_stmt = -1; /*< -1 no, 0 disable, 1 enable */
|
int set_autocommit_stmt = -1; /*< -1 no, 0 disable, 1 enable */
|
||||||
LEX* lex;
|
LEX* lex;
|
||||||
Item* item;
|
Item* item;
|
||||||
@ -501,27 +501,51 @@ static skygw_query_type_t resolve_query_type(
|
|||||||
type |= QUERY_TYPE_DISABLE_AUTOCOMMIT;
|
type |= QUERY_TYPE_DISABLE_AUTOCOMMIT;
|
||||||
type |= QUERY_TYPE_BEGIN_TRX;
|
type |= QUERY_TYPE_BEGIN_TRX;
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* REVOKE ALL, ASSIGN_TO_KEYCACHE,
|
|
||||||
* PRELOAD_KEYS, FLUSH, RESET, CREATE|ALTER|DROP SERVER
|
|
||||||
*/
|
|
||||||
if (lex->option_type == OPT_GLOBAL)
|
if (lex->option_type == OPT_GLOBAL)
|
||||||
{
|
{
|
||||||
type |= QUERY_TYPE_GLOBAL_WRITE;
|
/**
|
||||||
goto return_qtype;
|
* SHOW syntax http://dev.mysql.com/doc/refman/5.6/en/show.html
|
||||||
|
*/
|
||||||
|
if (lex->sql_command == SQLCOM_SHOW_VARIABLES)
|
||||||
|
{
|
||||||
|
type |= QUERY_TYPE_GSYSVAR_READ;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* SET syntax http://dev.mysql.com/doc/refman/5.6/en/set-statement.html
|
||||||
|
*/
|
||||||
|
else if (lex->sql_command == SQLCOM_SET_OPTION)
|
||||||
|
{
|
||||||
|
type |= QUERY_TYPE_GSYSVAR_WRITE;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* REVOKE ALL, ASSIGN_TO_KEYCACHE,
|
||||||
|
* PRELOAD_KEYS, FLUSH, RESET, CREATE|ALTER|DROP SERVER
|
||||||
|
*/
|
||||||
|
else
|
||||||
|
{
|
||||||
|
type |= QUERY_TYPE_GSYSVAR_WRITE;
|
||||||
|
}
|
||||||
|
goto return_qtype;
|
||||||
}
|
}
|
||||||
else if (lex->option_type == OPT_SESSION)
|
else if (lex->option_type == OPT_SESSION)
|
||||||
{
|
{
|
||||||
/** SHOW commands are all reads to one backend */
|
/**
|
||||||
|
* SHOW syntax http://dev.mysql.com/doc/refman/5.6/en/show.html
|
||||||
|
*/
|
||||||
if (lex->sql_command == SQLCOM_SHOW_VARIABLES)
|
if (lex->sql_command == SQLCOM_SHOW_VARIABLES)
|
||||||
{
|
{
|
||||||
type |= QUERY_TYPE_SESSION_READ;
|
type |= QUERY_TYPE_SYSVAR_READ;
|
||||||
}
|
}
|
||||||
else
|
/**
|
||||||
|
* SET syntax http://dev.mysql.com/doc/refman/5.6/en/set-statement.html
|
||||||
|
*/
|
||||||
|
else if (lex->sql_command == SQLCOM_SET_OPTION)
|
||||||
{
|
{
|
||||||
type |= QUERY_TYPE_SESSION_WRITE;
|
/** Either user- or system variable write */
|
||||||
|
type |= QUERY_TYPE_SESSION_WRITE;
|
||||||
}
|
}
|
||||||
goto return_qtype;
|
goto return_qtype;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 1:ALTER TABLE, TRUNCATE, REPAIR, OPTIMIZE, ANALYZE, CHECK.
|
* 1:ALTER TABLE, TRUNCATE, REPAIR, OPTIMIZE, ANALYZE, CHECK.
|
||||||
@ -538,31 +562,26 @@ static skygw_query_type_t resolve_query_type(
|
|||||||
if (thd->variables.sql_log_bin == 0 &&
|
if (thd->variables.sql_log_bin == 0 &&
|
||||||
force_data_modify_op_replication)
|
force_data_modify_op_replication)
|
||||||
{
|
{
|
||||||
|
/** Not replicated */
|
||||||
type |= QUERY_TYPE_SESSION_WRITE;
|
type |= QUERY_TYPE_SESSION_WRITE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
type |= QUERY_TYPE_WRITE;
|
/** Written to binlog, that is, replicated except tmp tables */
|
||||||
|
type |= QUERY_TYPE_WRITE; /*< to master */
|
||||||
|
|
||||||
if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE &&
|
if (lex->create_info.options & HA_LEX_CREATE_TMP_TABLE &&
|
||||||
lex->sql_command == SQLCOM_CREATE_TABLE)
|
lex->sql_command == SQLCOM_CREATE_TABLE)
|
||||||
{
|
{
|
||||||
type |= QUERY_TYPE_CREATE_TMP_TABLE;
|
type |= QUERY_TYPE_CREATE_TMP_TABLE; /*< remember in router */
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
goto return_qtype;
|
goto return_qtype;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Try to catch session modifications here */
|
/** Try to catch session modifications here */
|
||||||
switch (lex->sql_command) {
|
switch (lex->sql_command) {
|
||||||
case SQLCOM_SET_OPTION: /*< SET commands. */
|
/** fallthrough */
|
||||||
if (lex->option_type == OPT_GLOBAL)
|
|
||||||
{
|
|
||||||
type |= QUERY_TYPE_GLOBAL_WRITE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/**<! fall through */
|
|
||||||
case SQLCOM_CHANGE_DB:
|
case SQLCOM_CHANGE_DB:
|
||||||
case SQLCOM_DEALLOCATE_PREPARE:
|
case SQLCOM_DEALLOCATE_PREPARE:
|
||||||
type |= QUERY_TYPE_SESSION_WRITE;
|
type |= QUERY_TYPE_SESSION_WRITE;
|
||||||
@ -599,15 +618,23 @@ static skygw_query_type_t resolve_query_type(
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#if defined(UPDATE_VAR_SUPPORT)
|
||||||
if (QTYPE_LESS_RESTRICTIVE_THAN_WRITE(type)) {
|
if (QTYPE_LESS_RESTRICTIVE_THAN_WRITE(type))
|
||||||
|
#endif
|
||||||
|
if (QUERY_IS_TYPE(qtype, QUERY_TYPE_UNKNOWN) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_LOCAL_READ) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_READ) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_READ) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_SYSVAR_READ) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_GSYSVAR_READ))
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* These values won't change qtype more restrictive than write.
|
* These values won't change qtype more restrictive than write.
|
||||||
* UDFs and procedures could possibly cause session-wide write,
|
* UDFs and procedures could possibly cause session-wide write,
|
||||||
* but unless their content is replicated this is a limitation
|
* but unless their content is replicated this is a limitation
|
||||||
* of this implementation.
|
* of this implementation.
|
||||||
* In other words : UDFs and procedures are not allowed to
|
* In other words : UDFs and procedures are not allowed to
|
||||||
* perform writes which are not replicated but nede to repeat
|
* perform writes which are not replicated but need to repeat
|
||||||
* in every node.
|
* in every node.
|
||||||
* It is not sure if such statements exist. vraa 25.10.13
|
* It is not sure if such statements exist. vraa 25.10.13
|
||||||
*/
|
*/
|
||||||
@ -628,7 +655,9 @@ static skygw_query_type_t resolve_query_type(
|
|||||||
|
|
||||||
if (itype == Item::SUBSELECT_ITEM) {
|
if (itype == Item::SUBSELECT_ITEM) {
|
||||||
continue;
|
continue;
|
||||||
} else if (itype == Item::FUNC_ITEM) {
|
}
|
||||||
|
else if (itype == Item::FUNC_ITEM)
|
||||||
|
{
|
||||||
int func_qtype = QUERY_TYPE_UNKNOWN;
|
int func_qtype = QUERY_TYPE_UNKNOWN;
|
||||||
/**
|
/**
|
||||||
* Item types:
|
* Item types:
|
||||||
@ -710,23 +739,39 @@ static skygw_query_type_t resolve_query_type(
|
|||||||
break;
|
break;
|
||||||
/** System session variable */
|
/** System session variable */
|
||||||
case Item_func::GSYSVAR_FUNC:
|
case Item_func::GSYSVAR_FUNC:
|
||||||
/** User-defined variable read */
|
func_qtype |= QUERY_TYPE_SYSVAR_READ;
|
||||||
case Item_func::GUSERVAR_FUNC:
|
|
||||||
/** User-defined variable modification */
|
|
||||||
case Item_func::SUSERVAR_FUNC:
|
|
||||||
func_qtype |= QUERY_TYPE_SESSION_READ;
|
|
||||||
LOGIF(LD, (skygw_log_write(
|
LOGIF(LD, (skygw_log_write(
|
||||||
LOGFILE_DEBUG,
|
LOGFILE_DEBUG,
|
||||||
"%lu [resolve_query_type] "
|
"%lu [resolve_query_type] "
|
||||||
"functype SUSERVAR_FUNC, could be "
|
"functype GSYSVAR_FUNC, system "
|
||||||
"executed in MaxScale.",
|
"variable read.",
|
||||||
|
pthread_self())));
|
||||||
|
break;
|
||||||
|
/** User-defined variable read */
|
||||||
|
case Item_func::GUSERVAR_FUNC:
|
||||||
|
func_qtype |= QUERY_TYPE_USERVAR_READ;
|
||||||
|
LOGIF(LD, (skygw_log_write(
|
||||||
|
LOGFILE_DEBUG,
|
||||||
|
"%lu [resolve_query_type] "
|
||||||
|
"functype GUSERVAR_FUNC, user "
|
||||||
|
"variable read.",
|
||||||
|
pthread_self())));
|
||||||
|
break;
|
||||||
|
/** User-defined variable modification */
|
||||||
|
case Item_func::SUSERVAR_FUNC:
|
||||||
|
func_qtype |= QUERY_TYPE_SESSION_WRITE;
|
||||||
|
LOGIF(LD, (skygw_log_write(
|
||||||
|
LOGFILE_DEBUG,
|
||||||
|
"%lu [resolve_query_type] "
|
||||||
|
"functype SUSERVAR_FUNC, user "
|
||||||
|
"variable write.",
|
||||||
pthread_self())));
|
pthread_self())));
|
||||||
break;
|
break;
|
||||||
case Item_func::UNKNOWN_FUNC:
|
case Item_func::UNKNOWN_FUNC:
|
||||||
if (item->name != NULL &&
|
if (item->name != NULL &&
|
||||||
strcmp(item->name, "last_insert_id()") == 0)
|
strcmp(item->name, "last_insert_id()") == 0)
|
||||||
{
|
{
|
||||||
func_qtype |= QUERY_TYPE_SESSION_READ;
|
func_qtype |= QUERY_TYPE_MASTER_READ;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -757,6 +802,7 @@ static skygw_query_type_t resolve_query_type(
|
|||||||
/**< Set new query type */
|
/**< Set new query type */
|
||||||
type |= set_query_type(&type, func_qtype);
|
type |= set_query_type(&type, func_qtype);
|
||||||
}
|
}
|
||||||
|
#if defined(UPDATE_VAR_SUPPORT)
|
||||||
/**
|
/**
|
||||||
* Write is as restrictive as it gets due functions,
|
* Write is as restrictive as it gets due functions,
|
||||||
* so break.
|
* so break.
|
||||||
@ -764,8 +810,9 @@ static skygw_query_type_t resolve_query_type(
|
|||||||
if ((type & QUERY_TYPE_WRITE) == QUERY_TYPE_WRITE) {
|
if ((type & QUERY_TYPE_WRITE) == QUERY_TYPE_WRITE) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
} /**< for */
|
} /**< for */
|
||||||
} /**< if */
|
} /**< if */
|
||||||
return_qtype:
|
return_qtype:
|
||||||
qtype = (skygw_query_type_t)type;
|
qtype = (skygw_query_type_t)type;
|
||||||
return qtype;
|
return qtype;
|
||||||
|
|||||||
@ -25,29 +25,39 @@ Copyright SkySQL Ab
|
|||||||
|
|
||||||
EXTERN_C_BLOCK_BEGIN
|
EXTERN_C_BLOCK_BEGIN
|
||||||
|
|
||||||
|
bool allow_var_writes_to_slaves = false;
|
||||||
|
bool allow_var_reads_from_slaves = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Query type for skygateway.
|
* Query type for skygateway.
|
||||||
* The meaninful difference is where operation is done and whether master data
|
* The meaninful difference is where operation is done and whether master data
|
||||||
* is modified
|
* is modified
|
||||||
*/
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
QUERY_TYPE_UNKNOWN = 0x0000, /*< Initial value, can't be tested bitwisely */
|
QUERY_TYPE_UNKNOWN = 0x000000, /*< Initial value, can't be tested bitwisely */
|
||||||
QUERY_TYPE_LOCAL_READ = 0x0001, /*< Read non-database data, execute in MaxScale */
|
QUERY_TYPE_LOCAL_READ = 0x000001, /*< Read non-database data, execute in MaxScale:any */
|
||||||
QUERY_TYPE_READ = 0x0002, /*< No updates */
|
QUERY_TYPE_READ = 0x000002, /*< Read database data:any */
|
||||||
QUERY_TYPE_WRITE = 0x0004, /*< Master data will be modified */
|
QUERY_TYPE_WRITE = 0x000004, /*< Master data will be modified:master */
|
||||||
QUERY_TYPE_SESSION_WRITE = 0x0008, /*< Session data will be modified */
|
QUERY_TYPE_MASTER_READ = 0x000008, /*< Read from the master:master */
|
||||||
QUERY_TYPE_GLOBAL_WRITE = 0x0010, /*< Global system variable modification */
|
QUERY_TYPE_SESSION_WRITE = 0x000010, /*< Session data will be modified:master or all */
|
||||||
QUERY_TYPE_BEGIN_TRX = 0x0020, /*< BEGIN or START TRANSACTION */
|
/** Not implemented yet */
|
||||||
QUERY_TYPE_ENABLE_AUTOCOMMIT = 0x0040, /*< SET autocommit=1 */
|
// QUERY_TYPE_USERVAR_WRITE = 0x000020, /*< Write a user variable:master or all */
|
||||||
QUERY_TYPE_DISABLE_AUTOCOMMIT = 0x0080, /*< SET autocommit=0 */
|
QUERY_TYPE_USERVAR_READ = 0x000040, /*< Read a user variable:master or any */
|
||||||
QUERY_TYPE_ROLLBACK = 0x0100, /*< ROLLBACK */
|
QUERY_TYPE_SYSVAR_READ = 0x000080, /*< Read a system variable:master or any */
|
||||||
QUERY_TYPE_COMMIT = 0x0200, /*< COMMIT */
|
/** Not implemented yet */
|
||||||
QUERY_TYPE_PREPARE_NAMED_STMT = 0x0400, /*< Prepared stmt with name from user */
|
// QUERY_TYPE_SYSVAR_WRITE = 0x000100, /*< Write a system variable:master or all */
|
||||||
QUERY_TYPE_PREPARE_STMT = 0x0800, /*< Prepared stmt with id provided by server */
|
QUERY_TYPE_GSYSVAR_READ = 0x000200, /*< Read global system variable:master or any */
|
||||||
QUERY_TYPE_EXEC_STMT = 0x1000, /*< Execute prepared statement */
|
QUERY_TYPE_GSYSVAR_WRITE = 0x000400, /*< Write global system variable:master or all */
|
||||||
QUERY_TYPE_SESSION_READ = 0x2000, /*< Read session data (from master 31.8.14) */
|
QUERY_TYPE_BEGIN_TRX = 0x000800, /*< BEGIN or START TRANSACTION */
|
||||||
QUERY_TYPE_CREATE_TMP_TABLE = 0x4000, /*< Create temporary table */
|
QUERY_TYPE_ENABLE_AUTOCOMMIT = 0x001000, /*< SET autocommit=1 */
|
||||||
QUERY_TYPE_READ_TMP_TABLE = 0x8000 /*< Read temporary table */
|
QUERY_TYPE_DISABLE_AUTOCOMMIT = 0x002000, /*< SET autocommit=0 */
|
||||||
|
QUERY_TYPE_ROLLBACK = 0x004000, /*< ROLLBACK */
|
||||||
|
QUERY_TYPE_COMMIT = 0x008000, /*< COMMIT */
|
||||||
|
QUERY_TYPE_PREPARE_NAMED_STMT = 0x010000, /*< Prepared stmt with name from user:all */
|
||||||
|
QUERY_TYPE_PREPARE_STMT = 0x020000, /*< Prepared stmt with id provided by server:all */
|
||||||
|
QUERY_TYPE_EXEC_STMT = 0x040000, /*< Execute prepared statement:master or any */
|
||||||
|
QUERY_TYPE_CREATE_TMP_TABLE = 0x080000, /*< Create temporary table:master (could be all) */
|
||||||
|
QUERY_TYPE_READ_TMP_TABLE = 0x100000 /*< Read temporary table:master (could be any) */
|
||||||
} skygw_query_type_t;
|
} skygw_query_type_t;
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -1118,103 +1118,144 @@ static route_target_t get_route_target (
|
|||||||
HINT* hint)
|
HINT* hint)
|
||||||
{
|
{
|
||||||
route_target_t target;
|
route_target_t target;
|
||||||
|
/**
|
||||||
if (QUERY_IS_TYPE(qtype, QUERY_TYPE_SESSION_WRITE) ||
|
* These queries are not affected by hints
|
||||||
QUERY_IS_TYPE(qtype, QUERY_TYPE_PREPARE_STMT) ||
|
*/
|
||||||
QUERY_IS_TYPE(qtype, QUERY_TYPE_PREPARE_NAMED_STMT))
|
if (!trx_active &&
|
||||||
{
|
(QUERY_IS_TYPE(qtype, QUERY_TYPE_SESSION_WRITE) ||
|
||||||
/** hints don't affect on routing */
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_PREPARE_STMT) ||
|
||||||
target = TARGET_ALL;
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_PREPARE_NAMED_STMT) ||
|
||||||
}
|
/** Configured to allow writing variables to all nodes */
|
||||||
/**
|
(allow_var_writes_to_slaves &&
|
||||||
* Read-only statements to slave or to master can be re-routed after
|
(QUERY_IS_TYPE(qtype, QUERY_TYPE_SESSION_WRITE) ||
|
||||||
* the hints
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_GSYSVAR_WRITE)))))
|
||||||
*/
|
{
|
||||||
else if ((QUERY_IS_TYPE(qtype, QUERY_TYPE_READ) ||
|
/** hints don't affect on routing */
|
||||||
QUERY_IS_TYPE(qtype, QUERY_TYPE_SESSION_READ)) &&
|
target = TARGET_ALL;
|
||||||
!trx_active)
|
}
|
||||||
{
|
/**
|
||||||
if (QUERY_IS_TYPE(qtype, QUERY_TYPE_READ))
|
* Hints may affect on routing of the following queries
|
||||||
|
*/
|
||||||
|
else if (!trx_active &&
|
||||||
|
(QUERY_IS_TYPE(qtype, QUERY_TYPE_READ) || /*< any SELECT */
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_READ)|| /*< read user var */
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_SYSVAR_READ) || /*< read sys var */
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_EXEC_STMT) || /*< prepared stmt exec */
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_GSYSVAR_READ))) /*< read global sys var */
|
||||||
|
{
|
||||||
|
/** First set expected targets before evaluating hints */
|
||||||
|
if (QUERY_IS_TYPE(qtype, QUERY_TYPE_READ) ||
|
||||||
|
/** Configured to allow reading variables from slaves */
|
||||||
|
(allow_var_reads_from_slaves &&
|
||||||
|
(QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_READ) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_SYSVAR_READ) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_GSYSVAR_READ))))
|
||||||
{
|
{
|
||||||
target = TARGET_SLAVE;
|
target = TARGET_SLAVE;
|
||||||
}
|
}
|
||||||
else
|
else if (QUERY_IS_TYPE(qtype, QUERY_TYPE_EXEC_STMT) ||
|
||||||
|
/** Configured not to allow reading variables from slaves */
|
||||||
|
(!allow_var_reads_from_slaves &&
|
||||||
|
(QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_READ) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_SYSVAR_READ))))
|
||||||
{
|
{
|
||||||
target = TARGET_MASTER;
|
target = TARGET_MASTER;
|
||||||
}
|
}
|
||||||
/** process routing hints */
|
|
||||||
while (hint != NULL)
|
/** process routing hints */
|
||||||
{
|
while (hint != NULL)
|
||||||
if (hint->type == HINT_ROUTE_TO_MASTER)
|
{
|
||||||
{
|
if (hint->type == HINT_ROUTE_TO_MASTER)
|
||||||
target = TARGET_MASTER; /*< override */
|
{
|
||||||
LOGIF(LT, (skygw_log_write(
|
target = TARGET_MASTER; /*< override */
|
||||||
LOGFILE_TRACE,
|
LOGIF(LT, (skygw_log_write(
|
||||||
"Hint: route to master.")));
|
LOGFILE_TRACE,
|
||||||
break;
|
"Hint: route to master.")));
|
||||||
}
|
break;
|
||||||
else if (hint->type == HINT_ROUTE_TO_NAMED_SERVER)
|
}
|
||||||
{
|
else if (hint->type == HINT_ROUTE_TO_NAMED_SERVER)
|
||||||
|
{
|
||||||
/**
|
/**
|
||||||
* Searching for a named server. If it can't be
|
* Searching for a named server. If it can't be
|
||||||
* found, the oroginal target is chosen.
|
* found, the oroginal target is chosen.
|
||||||
*/
|
*/
|
||||||
target |= TARGET_NAMED_SERVER;
|
target |= TARGET_NAMED_SERVER;
|
||||||
LOGIF(LT, (skygw_log_write(
|
LOGIF(LT, (skygw_log_write(
|
||||||
LOGFILE_TRACE,
|
LOGFILE_TRACE,
|
||||||
"Hint: route to named server : ")));
|
"Hint: route to named server : ")));
|
||||||
}
|
}
|
||||||
else if (hint->type == HINT_ROUTE_TO_UPTODATE_SERVER)
|
else if (hint->type == HINT_ROUTE_TO_UPTODATE_SERVER)
|
||||||
{
|
{
|
||||||
/** not implemented */
|
/** not implemented */
|
||||||
}
|
}
|
||||||
else if (hint->type == HINT_ROUTE_TO_ALL)
|
else if (hint->type == HINT_ROUTE_TO_ALL)
|
||||||
{
|
{
|
||||||
/** not implemented */
|
/** not implemented */
|
||||||
}
|
}
|
||||||
else if (hint->type == HINT_PARAMETER)
|
else if (hint->type == HINT_PARAMETER)
|
||||||
{
|
{
|
||||||
if (strncasecmp(
|
if (strncasecmp(
|
||||||
(char *)hint->data,
|
(char *)hint->data,
|
||||||
"max_slave_replication_lag",
|
"max_slave_replication_lag",
|
||||||
strlen("max_slave_replication_lag")) == 0)
|
strlen("max_slave_replication_lag")) == 0)
|
||||||
{
|
{
|
||||||
target |= TARGET_RLAG_MAX;
|
target |= TARGET_RLAG_MAX;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LOGIF(LT, (skygw_log_write(
|
LOGIF(LT, (skygw_log_write(
|
||||||
LOGFILE_TRACE,
|
LOGFILE_TRACE,
|
||||||
"Error : Unknown hint parameter "
|
"Error : Unknown hint parameter "
|
||||||
"'%s' when 'max_slave_replication_lag' "
|
"'%s' when 'max_slave_replication_lag' "
|
||||||
"was expected.",
|
"was expected.",
|
||||||
(char *)hint->data)));
|
(char *)hint->data)));
|
||||||
LOGIF(LE, (skygw_log_write_flush(
|
LOGIF(LE, (skygw_log_write_flush(
|
||||||
LOGFILE_ERROR,
|
LOGFILE_ERROR,
|
||||||
"Error : Unknown hint parameter "
|
"Error : Unknown hint parameter "
|
||||||
"'%s' when 'max_slave_replication_lag' "
|
"'%s' when 'max_slave_replication_lag' "
|
||||||
"was expected.",
|
"was expected.",
|
||||||
(char *)hint->data)));
|
(char *)hint->data)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (hint->type == HINT_ROUTE_TO_SLAVE)
|
else if (hint->type == HINT_ROUTE_TO_SLAVE)
|
||||||
{
|
{
|
||||||
target = TARGET_SLAVE;
|
target = TARGET_SLAVE;
|
||||||
LOGIF(LT, (skygw_log_write(
|
LOGIF(LT, (skygw_log_write(
|
||||||
LOGFILE_TRACE,
|
LOGFILE_TRACE,
|
||||||
"Hint: route to slave.")));
|
"Hint: route to slave.")));
|
||||||
}
|
}
|
||||||
hint = hint->next;
|
hint = hint->next;
|
||||||
} /*< while (hint != NULL) */
|
} /*< while (hint != NULL) */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/** hints don't affect on routing */
|
/** hints don't affect on routing */
|
||||||
target = TARGET_MASTER;
|
ss_dassert(trx_active ||
|
||||||
}
|
(QUERY_IS_TYPE(qtype, QUERY_TYPE_WRITE) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_MASTER_READ) ||
|
||||||
return target;
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_SESSION_WRITE) ||
|
||||||
|
(QUERY_IS_TYPE(qtype, QUERY_TYPE_USERVAR_READ) &&
|
||||||
|
!allow_var_writes_to_slaves) ||
|
||||||
|
(QUERY_IS_TYPE(qtype, QUERY_TYPE_SYSVAR_READ) &&
|
||||||
|
!allow_var_writes_to_slaves) ||
|
||||||
|
(QUERY_IS_TYPE(qtype, QUERY_TYPE_GSYSVAR_READ) &&
|
||||||
|
!allow_var_writes_to_slaves) ||
|
||||||
|
(QUERY_IS_TYPE(qtype, QUERY_TYPE_GSYSVAR_WRITE) &&
|
||||||
|
!allow_var_writes_to_slaves) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_BEGIN_TRX) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_ENABLE_AUTOCOMMIT) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_DISABLE_AUTOCOMMIT) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_ROLLBACK) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_COMMIT) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_EXEC_STMT) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_CREATE_TMP_TABLE) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_READ_TMP_TABLE) ||
|
||||||
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_UNKNOWN)));
|
||||||
|
target = TARGET_MASTER;
|
||||||
|
}
|
||||||
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the query is a DROP TABLE... query and
|
* Check if the query is a DROP TABLE... query and
|
||||||
* if it targets a temporary table, remove it from the hashtable.
|
* if it targets a temporary table, remove it from the hashtable.
|
||||||
@ -1597,11 +1638,9 @@ static int routeQuery(
|
|||||||
break;
|
break;
|
||||||
} /**< switch by packet type */
|
} /**< switch by packet type */
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the query has anything to do with temporary tables.
|
* Check if the query has anything to do with temporary tables.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
qtype = is_read_tmp_table(instance,router_session,querybuf,qtype);
|
qtype = is_read_tmp_table(instance,router_session,querybuf,qtype);
|
||||||
check_create_tmp_table(instance,router_session,querybuf,qtype);
|
check_create_tmp_table(instance,router_session,querybuf,qtype);
|
||||||
check_drop_tmp_table(instance,router_session,querybuf,qtype);
|
check_drop_tmp_table(instance,router_session,querybuf,qtype);
|
||||||
@ -1620,7 +1659,7 @@ static int routeQuery(
|
|||||||
{
|
{
|
||||||
router_cli_ses->rses_transaction_active = true;
|
router_cli_ses->rses_transaction_active = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (!router_cli_ses->rses_transaction_active &&
|
else if (!router_cli_ses->rses_transaction_active &&
|
||||||
QUERY_IS_TYPE(qtype, QUERY_TYPE_BEGIN_TRX))
|
QUERY_IS_TYPE(qtype, QUERY_TYPE_BEGIN_TRX))
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user