Merge branch '2.1' into develop

This commit is contained in:
Markus Mäkelä 2017-07-31 15:57:05 +03:00
commit 3eb99139f5
27 changed files with 389 additions and 58 deletions

View File

@ -9,7 +9,7 @@ command -v apt-get
if [ $? == 0 ]
then
# DEB-based distro
install_libdir=/usr/lib
sudo apt-get update
sudo apt-get install -y --force-yes dpkg-dev git wget \
@ -35,6 +35,7 @@ then
fi
else
## RPM-based distro
install_libdir=/usr/lib64
command -v yum
if [ $? != 0 ]
@ -142,7 +143,7 @@ fi
mkdir -p jansson/build
pushd jansson/build
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_C_FLAGS=-fPIC -DJANSSON_INSTALL_LIB_DIR=/usr/lib64
cmake .. -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_C_FLAGS=-fPIC -DJANSSON_INSTALL_LIB_DIR=$install_libdir
make
sudo make install
popd

View File

@ -21,6 +21,7 @@
* MaxScale now supports IPv6
For more details, please refer to:
* [MariaDB MaxScale 2.1.5 Release Notes](Release-Notes/MaxScale-2.1.5-Release-Notes.md)
* [MariaDB MaxScale 2.1.4 Release Notes](Release-Notes/MaxScale-2.1.4-Release-Notes.md)
* [MariaDB MaxScale 2.1.3 Release Notes](Release-Notes/MaxScale-2.1.3-Release-Notes.md)
* [MariaDB MaxScale 2.1.2 Release Notes](Release-Notes/MaxScale-2.1.2-Release-Notes.md)

View File

@ -65,8 +65,9 @@ use_priority=true
### `root_node_as_master`
This option controls whether the write master Galera node requires a
_wsrep_local_index_ value of 0. This option is enabled by default and was
introduced in MaxScale 2.1.0.
_wsrep_local_index_ value of 0. This option was introduced in MaxScale 2.1.0 and
it is disabled by default in versions 2.1.5 and newer. In versions 2.1.4 and
older, the option was enabled by default.
A Galera cluster will always have a node which has a _wsrep_local_index_ value
of 0. Based on this information, multiple MaxScale instances can always pick the

View File

@ -1,4 +1,4 @@
# MariaDB MaxScale 2.1.5 Release Notes
# MariaDB MaxScale 2.1.5 Release Notes -- 2017-07-31
Release 2.1.5 is a GA release.
@ -18,12 +18,32 @@ report at [Jira](https://jira.mariadb.org).
## Changed Features
### SSL CA Certificates
Before MaxScale 2.1.5, MaxScale would only use the first certificate file found
in the CA certificate file. In MaxScale 2.1.5, the first certificate is loaded
and the rest of the certificates on the file are stored in the chain store.
This change should not cause any changes in MaxScale's behavior.
### `root_node_as_master`
The galeramon parameter `root_node_as_master` is now disabled by default. The
option should be enabled when it is of great importance to know that all
MaxScale instances treat a shared Galera cluster in the same way.
### Schemarouter
Starting with MaxScale 2.1.5, the _schemarouter_ will prioritize the current
database over an explicit database if tables in the the current database are
used in a query.
### Dbfwfilter
The function type rule will now accept backtick quoted values. This allows
keywords such as `insert` and `function` to be used as values for a function
rule.
## New Features
### Schemarouter
@ -40,10 +60,25 @@ will still go to the central database.
## Bug fixes
[Here is a list of bugs fixed since the release of MaxScale 2.1.4.]
[Here is a list of bugs fixed in MaxScale 2.1.5.]
(https://jira.mariadb.org/issues/?jql=project%20%3D%20MXS%20AND%20issuetype%20%3D%20Bug%20AND%20status%20%3D%20Closed%20AND%20fixVersion%20%3D%202.1.5)
* [MXS-1335](https://jira.mariadb.org/browse/MXS-1335) root_node_as_master should not be enabled by default
* [MXS-1330](https://jira.mariadb.org/browse/MXS-1330) insertstream attempts to parse all buffers
* [MXS-1329](https://jira.mariadb.org/browse/MXS-1329) Using filters with SSL and keep alive can cause errors
* [MXS-1328](https://jira.mariadb.org/browse/MXS-1328) Strange behavior with routes between master / slaves
* [MXS-1326](https://jira.mariadb.org/browse/MXS-1326) Upgrade error on Ubuntu Xenial
* [MXS-1324](https://jira.mariadb.org/browse/MXS-1324) MaxScale 2.1.4 compiled without the avrorouter?
* [MXS-1323](https://jira.mariadb.org/browse/MXS-1323) Maxscale2.1.3 coredump
* [MXS-1319](https://jira.mariadb.org/browse/MXS-1319) Maxscale selecting extra whitespace while loading users
* [MXS-1318](https://jira.mariadb.org/browse/MXS-1318) Use SSL_CTX_use_certificate_chain_file in Maxscale to use CA signed certificates
* [MXS-1316](https://jira.mariadb.org/browse/MXS-1316) error using Kafka with binlog router
* [MXS-1313](https://jira.mariadb.org/browse/MXS-1313) Character set is not updated if servers are down
* [MXS-1312](https://jira.mariadb.org/browse/MXS-1312) Rule with only on_queries do not work
* [MXS-1311](https://jira.mariadb.org/browse/MXS-1311) Function type rule that blocks function results in syntax error
* [MXS-1310](https://jira.mariadb.org/browse/MXS-1310) schemarouter ignores local copy of duplicate schemas on JOIN
* [MXS-1309](https://jira.mariadb.org/browse/MXS-1309) ALTER TABLE detection is broken
* [MXS-1285](https://jira.mariadb.org/browse/MXS-1285) cannot stat `/usr/share/maxscale/upstart/maxscale.conf': No such file or directory
## Known Issues and Limitations

View File

@ -3,7 +3,7 @@
This document describes upgrading MaxScale from version 1.2.1 to 1.3.
The major changes can be found in the [changelog](../Changelog.md) and more
detailed information in the [release notes](../Release-Notes/MaxScale-1.3.0-Release-Notes.md).
detailed information in the MaxScale 1.3.0 release notes.
## Installation

View File

@ -3,10 +3,10 @@
This document describes upgrading MaxScale from version 1.3 to 1.4.
For more detailed information about MaxScale 1.4, please refer to:
* [MaxScale 1.4.3 release notes](../Release-Notes/MaxScale-1.4.3-Release-Notes.md)
* [MaxScale 1.4.2 release notes](../Release-Notes/MaxScale-1.4.2-Release-Notes.md)
* [MaxScale 1.4.1 release notes](../Release-Notes/MaxScale-1.4.1-Release-Notes.md)
* [MaxScale 1.4.0 release notes](../Release-Notes/MaxScale-1.4.0-Release-Notes.md)
* MaxScale 1.4.3 release notes
* MaxScale 1.4.2 release notes
* MaxScale 1.4.1 release notes
* MaxScale 1.4.0 release notes
## Installation

View File

@ -7,6 +7,7 @@ For more information about MariaDB MaxScale 2.1, please refer to the
[ChangeLog](../Changelog.md).
For a complete list of changes in MaxScale 2.1, refer to the
[MaxScale 2.1.5 Release Notes](../Release-Notes/MaxScale-2.1.5-Release-Notes.md).
[MaxScale 2.1.4 Release Notes](../Release-Notes/MaxScale-2.1.4-Release-Notes.md).
[MaxScale 2.1.3 Release Notes](../Release-Notes/MaxScale-2.1.3-Release-Notes.md).
[MaxScale 2.1.2 Release Notes](../Release-Notes/MaxScale-2.1.2-Release-Notes.md).

View File

@ -5,7 +5,7 @@
set(MAXSCALE_VERSION_MAJOR "2" CACHE STRING "Major version")
set(MAXSCALE_VERSION_MINOR "1" CACHE STRING "Minor version")
set(MAXSCALE_VERSION_PATCH "4" CACHE STRING "Patch version")
set(MAXSCALE_VERSION_PATCH "5" CACHE STRING "Patch version")
# This should only be incremented if a package is rebuilt
set(MAXSCALE_BUILD_NUMBER 1 CACHE STRING "Release number")

View File

@ -53,7 +53,7 @@ then
systemctl daemon-reload
fi
else
if [ -d "/etc/init/" ]
if [ -d "/etc/init/" ] && [ -f "@CMAKE_INSTALL_PREFIX@/@MAXSCALE_SHAREDIR@/upstart/maxscale.conf" ]
then
cp @CMAKE_INSTALL_PREFIX@/@MAXSCALE_SHAREDIR@/upstart/maxscale.conf /etc/init/
fi

View File

@ -3,7 +3,7 @@
# The first argument is the number of packages left after
# this one has been removed. If it is 0 then the package is being
# removed from the system.
if [ "$1" -eq 0 ]
if [ "$1" = "0" ] || [ "$1" = "remove" ]
then
if [ -f /etc/init.d/maxscale ]
then

View File

@ -302,6 +302,10 @@ add_test_executable(mxs1110_16mb.cpp mxs1110_16mb longblob_filters LABELS readwr
# Schemarouter implicit database detection
add_test_executable(mxs1310_implicit_db.cpp mxs1310_implicit_db mxs1310_implicit_db LABELS schemarouter REPL_BACKEND)
# Retry reads with persistent connections
add_test_executable(mxs1323_retry_read.cpp mxs1323_retry_read mxs1323 LABELS readwritesplit LIGHT REPL_BACKEND)
add_test_executable(mxs1323_stress.cpp mxs1323_stress mxs1323 LABELS readwritesplit REPL_BACKEND)
# INSERT extremelly big number of rows
add_test_executable(lots_of_rows.cpp lots_of_rows galera LABELS readwritesplit HEAVY GALERA_BACKEND)
@ -309,7 +313,7 @@ add_test_executable(lots_of_rows.cpp lots_of_rows galera LABELS readwritesplit H
add_test_script(mariadb_tests_hartmut mariadb_tests_hartmut.sh replication LABELS readwritesplit REPL_BACKEND)
# A set of MariaDB server tests executed against Maxscale RWSplit (Galera backend)
add_test_script(mariadb_tests_hartmut_galera mariadb_tests_hartmut.sh galera LABELS readwritesplit GALERA_BACKEND)
add_test_script(mariadb_tests_hartmut_galera mariadb_tests_hartmut.sh galera_hartmut LABELS readwritesplit GALERA_BACKEND)
# Creates a number of connections > max_connections setting
add_test_executable(max_connections.cpp max_connections replication LABELS MySQLAuth MySQLProtocol UNSTABLE HEAVY REPL_BACKEND)
@ -545,7 +549,7 @@ add_test_executable(rwsplit_multi_stmt.cpp rwsplit_multi_stmt rwsplit_multi_stmt
add_test_executable(rwsplit_read_only_trx.cpp rwsplit_read_only_trx rwsplit_read_only_trx LABELS readwritesplit REPL_BACKEND)
# Test replication-manager with MaxScale
add_test_executable(replication_manager.cpp replication_manager replication_manager LABELS maxscale REPL_BACKEND)
#add_test_executable(replication_manager.cpp replication_manager replication_manager LABELS maxscale REPL_BACKEND)
#add_test_executable_notest(replication_manager_2nodes.cpp replication_manager_2nodes replication_manager_2nodes LABELS maxscale REPL_BACKEND)
#add_test_executable_notest(replication_manager_3nodes.cpp replication_manager_3nodes replication_manager_3nodes LABELS maxscale REPL_BACKEND)

View File

@ -65,6 +65,7 @@ int main(int argc, char *argv[])
free(rows);
}
test.stop_timeout();
execute_query(test.repl->nodes[0], "DROP TABLE test.t1;RESET MASTER");
test.repl->fix_replication();

View File

@ -1,39 +1,18 @@
/**
* @file bug662.cpp regression case for bug 662 ("MaxScale hangs in startup if backend server is not responsive"), covers also bug680 ("RWSplit can't load DB user if backend is not available at MaxScale start")
*
* - block all Mariadb servers Firewall
* - restart MaxScale
* - check it took no more then 20 seconds
* - unblock Mariadb servers
* - sleep one minute
* - check if Maxscale is alive
* - Block all Mariadb servers
* - Restart MaxScale
* - Unblock Mariadb servers
* - Sleep and check if Maxscale is alive
*/
/*
Vilho Raatikka 2014-12-29 08:38:28 UTC
During startup, load_mysql_users tries to read the contents of the mysql.user table. If the chosen backend is not responsive, connection hangs for a long time.
Comment 1 Vilho Raatikka 2014-12-29 11:41:32 UTC
The issue causes long stalls for the executing thread whenever getUsers function is called and one or more backends are not responsive.
Comment 2 Vilho Raatikka 2014-12-29 11:50:10 UTC
dbusers.c: Added function for setting read, write and connection timeout values. Set default timeouts for getUsers. Defaults are listed in service.c
gateway.c:shutdown_server is called whenever MaxScale is to be shut down. Added call for service_shutdown to shutdown_server.
service.c:service_alloc: replaced malloc with calloc and removed unnecessary zero/NULL initialization statements as a consequence.
serviceStart: Exit serviceStartPort loop if shutdown flag is set for the service.
serviceStartAll: Exit serviceStart loop if shutdown flag is set for the service.
service.c: Added service_shutdown which sets shutdown flag for each service found in allServices list.
service.h: Added prototype for service_shutdown
*/
#include <iostream>
#include "testconnections.h"
#include "maxadmin_operations.h"
int main(int argc, char *argv[])
{
TestConnections * Test = new TestConnections(argc, argv);
Test->set_timeout(20);
int i;
Test->tprintf("Connecting to Maxscale %s\n", Test->maxscale_IP);
@ -44,6 +23,7 @@ int main(int argc, char *argv[])
for (i = 0; i < Test->repl->N; i++)
{
Test->set_timeout(30);
Test->tprintf("Setup firewall to block mysql on node %d\n", i);
Test->repl->block_node(i);
fflush(stdout);
@ -53,12 +33,12 @@ int main(int argc, char *argv[])
Test->tprintf("Restarting MaxScale");
Test->restart_maxscale();
Test->set_timeout(20);
Test->tprintf("Checking if MaxScale is alive by connecting to MaxAdmin\n");
Test->add_result(Test->execute_maxadmin_command((char* ) "show servers"), "Maxadmin execution failed.\n");
for (i = 0; i < Test->repl->N; i++)
{
Test->set_timeout(30);
Test->tprintf("Setup firewall back to allow mysql on node %d\n", i);
Test->repl->unblock_node(i);
fflush(stdout);
@ -68,13 +48,11 @@ int main(int argc, char *argv[])
Test->tprintf("Sleeping 30 seconds\n");
sleep(30);
Test->set_timeout(20);
Test->set_timeout(30);
Test->tprintf("Checking Maxscale is alive\n");
Test->check_maxscale_alive();
int rval = Test->global_result;
delete Test;
return rval;
//}
}

View File

@ -0,0 +1,89 @@
[maxscale]
threads=###threads###
log_info=1
[Galera Monitor]
type=monitor
module=galeramon
servers=server1,server2,server3,server4
user=maxskysql
passwd=skysql
monitor_interval=1000
root_node_as_master=false
[RW Split Router]
type=service
router=readwritesplit
servers=server1,server2,server3,server4
user=maxskysql
passwd=skysql
router_options=slave_selection_criteria=LEAST_GLOBAL_CONNECTIONS
max_slave_connections=1
[Read Connection Router Slave]
type=service
router=readconnroute
router_options=slave
servers=server1,server2,server3,server4
user=maxskysql
passwd=skysql
[Read Connection Router Master]
type=service
router=readconnroute
router_options=master
servers=server1,server2,server3,server4
user=maxskysql
passwd=skysql
[RW Split Listener]
type=listener
service=RW Split Router
protocol=MySQLClient
port=4006
[Read Connection Listener Slave]
type=listener
service=Read Connection Router Slave
protocol=MySQLClient
port=4009
[Read Connection Listener Master]
type=listener
service=Read Connection Router Master
protocol=MySQLClient
port=4008
[CLI]
type=service
router=cli
[CLI Listener]
type=listener
service=CLI
protocol=maxscaled
socket=default
[server1]
type=server
address=###galera_server_IP_1###
port=###galera_server_port_1###
protocol=MySQLBackend
[server2]
type=server
address=###galera_server_IP_2###
port=###galera_server_port_2###
protocol=MySQLBackend
[server3]
type=server
address=###galera_server_IP_3###
port=###galera_server_port_3###
protocol=MySQLBackend
[server4]
type=server
address=###galera_server_IP_4###
port=###galera_server_port_4###
protocol=MySQLBackend

View File

@ -0,0 +1,51 @@
[maxscale]
threads=###threads###
log_info=1
[MySQL Monitor]
type=monitor
module=mysqlmon
###repl51###
servers= server1,server2
user=maxskysql
passwd= skysql
monitor_interval=500
[RW Split Router]
type=service
router= readwritesplit
servers=server1,server2
user=maxskysql
passwd=skysql
[RW Split Listener]
type=listener
service=RW Split Router
protocol=MySQLClient
port=4006
[CLI]
type=service
router=cli
[CLI Listener]
type=listener
service=CLI
protocol=maxscaled
socket=default
[server1]
type=server
address=###node_server_IP_1###
port=###node_server_port_1###
protocol=MySQLBackend
persistpoolmax=10
persistmaxtime=300
[server2]
type=server
address=###node_server_IP_2###
port=###node_server_port_2###
protocol=MySQLBackend
persistpoolmax=10
persistmaxtime=300

View File

@ -14,6 +14,7 @@
#include "sql_const.h"
#include <climits>
#include <string>
#include <sstream>
#include <vector>
Mariadb_nodes::Mariadb_nodes(const char *pref, const char *test_cwd, bool verbose):
@ -918,6 +919,13 @@ int Mariadb_nodes::get_server_id(int index)
return id;
}
std::string Mariadb_nodes::get_server_id_str(int index)
{
std::stringstream ss;
ss << get_server_id(index);
return ss.str();
}
void Mariadb_nodes::generate_ssh_cmd(char *cmd, int node, const char *ssh, bool sudo)
{
if (strcmp(IP[node], "127.0.0.1") == 0)

View File

@ -16,6 +16,7 @@
#include "mariadb_func.h"
#include <errno.h>
#include <string>
/**
* @brief A class to handle backend nodes
@ -329,6 +330,7 @@ public:
* @return Node id of the server or -1 on error
*/
int get_server_id(int index);
std::string get_server_id_str(int index);
/**
* @brief Generate command line to execute command on the node via ssh

View File

@ -4,7 +4,7 @@
#
# TODO: Don't test correctness of routing with mysqltest
#
./non_native_setup $1
master_id=`echo "SELECT @@server_id" | mysql -u$node_user -p$node_password -h $node_000_network $ssl_options -P $node_000_port | tail -n1`
echo "--disable_query_log" > Hartmut_tests/maxscale-mysqltest/testconf.inc
echo "SET @TMASTER_ID=$master_id;" >> Hartmut_tests/maxscale-mysqltest/testconf.inc

View File

@ -207,7 +207,7 @@ int compare_expected(TestConnections * Test, const char * sql, my_ulonglong exp_
my_ulonglong *rows = new my_ulonglong[30];
my_ulonglong i;
Test->set_timeout(10);
Test->set_timeout(30);
execute_query_num_of_rows(Test->conn_rwsplit, sql, rows, &i);
Test->tprintf("Result sets number is %llu\n", i);
@ -245,7 +245,7 @@ int compare_stmt_expected(TestConnections * Test, MYSQL_STMT * stmt, my_ulonglon
my_ulonglong *rows = new my_ulonglong[30];
my_ulonglong i;
Test->set_timeout(10);
Test->set_timeout(30);
execute_stmt_num_of_rows(stmt, rows, &i);
Test->tprintf("Result sets number is %llu\n", i);
@ -290,7 +290,7 @@ int main(int argc, char *argv[])
MYSQL_STMT * stmt;
TestConnections * Test = new TestConnections(argc, argv);
Test->set_timeout(10);
Test->set_timeout(30);
Test->connect_rwsplit();
create_t1(Test->conn_rwsplit);

View File

@ -0,0 +1,50 @@
/**
* Test for MXS-1323.
* - Check that retried reads work with persistent connections
*/
#include "testconnections.h"
void* async_block(void* data)
{
TestConnections *test = (TestConnections*)data;
sleep(5);
test->tprintf("Blocking slave");
test->repl->block_node(1);
return NULL;
}
std::string do_query(TestConnections& test)
{
MYSQL* conn = test.open_rwsplit_connection();
const char* query = "SELECT SLEEP(10), @@server_id";
char output[512] = "";
find_field(conn, query, "@@server_id", output);
mysql_close(conn);
return std::string(output);
}
int main(int argc, char *argv[])
{
TestConnections test(argc, argv);
char server_id[2][1024];
test.repl->connect();
std::string master = test.repl->get_server_id_str(0);
std::string slave = test.repl->get_server_id_str(1);
test.repl->close_connections();
test.set_timeout(60);
test.add_result(do_query(test) != slave, "The slave should respond to the first query");
pthread_t thr;
pthread_create(&thr, NULL, async_block, &test);
test.add_result(do_query(test) != master, "The master should respond to the second query");
pthread_join(thr, NULL);
test.repl->unblock_node(1);
return test.global_result;
}

View File

@ -0,0 +1,81 @@
/**
* Test for MXS-1323.
* - Check that retried reads work with persistent connections
*/
#include "testconnections.h"
#include <sstream>
static bool running = true;
void* async_query(void* data)
{
TestConnections *test = (TestConnections*)data;
while (running && test->global_result == 0)
{
MYSQL* conn = test->open_rwsplit_connection();
for (int i = 0; i < 50 && running && test->global_result == 0; i++)
{
const char* query = "SET @a = (SELECT SLEEP(1))";
test->try_query(conn, query);
}
mysql_close(conn);
}
return NULL;
}
#define NUM_THR 5
int main(int argc, char *argv[])
{
TestConnections test(argc, argv);
pthread_t query_thr[NUM_THR];
std::stringstream ss;
ss << "CREATE OR REPLACE TABLE test.t1 (id INT)";
test.connect_maxscale();
test.try_query(test.conn_rwsplit, ss.str().c_str());
ss.str("");
ss << "INSERT INTO test.t1 VALUES (0)";
for (int i = 1; i <= 10000; i++)
{
ss << ",(" << i << ")";
}
test.try_query(test.conn_rwsplit, ss.str().c_str());
test.close_maxscale_connections();
if (test.global_result)
{
return test.global_result;
}
for (int i = 0; i < NUM_THR; i++)
{
pthread_create(&query_thr[i], NULL, async_query, &test);
}
for (int i = 0; i < 3 && test.global_result == 0; i++)
{
test.tprintf("Round %d", i + 1);
test.repl->block_node(1);
sleep(5);
test.repl->unblock_node(1);
sleep(5);
}
running = false;
for (int i = 0; i < NUM_THR; i++)
{
test.set_timeout(10);
pthread_join(query_thr[i], NULL);
}
return test.global_result;
}

View File

@ -369,6 +369,16 @@ static const char* BUILTIN_FUNCTIONS[] =
"to_base64",
"weight_string",
/*
* Regex functions
* https://mariadb.com/kb/en/mariadb/regular-expressions-functions/
*/
"regexp",
"regexp_instr",
"regexp_replace",
"regexp_substr",
"rlike",
/*
* http://dev.mysql.com/doc/refman/5.7/en/row-subqueries.html
*/

View File

@ -77,3 +77,5 @@ ROLLBACK TO SAVEPOINT id;
ROLLBACK WORK TO id;
ROLLBACK TO id;
RELEASE SAVEPOINT id;
SELECT her FROM (SELECT @@server_id as her) as t WHERE her REGEXP '.*';

View File

@ -606,7 +606,8 @@ static bool extract_insert_target(GWBUF *buffer, char* target, int len)
{
bool rval = false;
if (qc_get_operation(buffer) == QUERY_OP_INSERT &&
if (MYSQL_GET_COMMAND(GWBUF_DATA(buffer)) == MYSQL_COM_QUERY &&
qc_get_operation(buffer) == QUERY_OP_INSERT &&
only_implicit_values(buffer))
{
int n_tables = 0;

View File

@ -85,7 +85,7 @@ MXS_MODULE* MXS_CREATE_MODULE()
{"disable_master_failback", MXS_MODULE_PARAM_BOOL, "false"},
{"available_when_donor", MXS_MODULE_PARAM_BOOL, "false"},
{"disable_master_role_setting", MXS_MODULE_PARAM_BOOL, "false"},
{"root_node_as_master", MXS_MODULE_PARAM_BOOL, "true"},
{"root_node_as_master", MXS_MODULE_PARAM_BOOL, "false"},
{"use_priority", MXS_MODULE_PARAM_BOOL, "false"},
{
"script",

View File

@ -15,11 +15,11 @@ import (
"database/sql"
"encoding/json"
"flag"
"fmt"
"log"
"os"
"regexp"
"strconv"
"fmt"
)
import _ "github.com/go-sql-driver/mysql"
@ -45,8 +45,10 @@ The "user" and "password" flags are required.
// Avro field
type Field struct {
Name string `json:"name"`
Type string `json:"type"`
Name string `json:"name"`
Type string `json:"type"`
RealType string `json:"real_type"`
Length int `json:"length"`
}
// Avro schema
@ -68,13 +70,20 @@ func LogObject(obj interface{}) {
}
var field_re *regexp.Regexp
var length_re *regexp.Regexp
// Convert the SQL type to the appropriate Avro type
func (f *Field) ToAvroType() {
orig := f.Type
f.Type = field_re.ReplaceAllString(f.Type, "")
f.Length = -1
f.RealType = f.Type
switch f.Type {
case "date", "datetime", "time", "timestamp", "year", "tinytext", "text",
"mediumtext", "longtext", "char", "varchar", "enum", "set":
"mediumtext", "longtext", "char", "varchar":
f.Type = "string"
f.Length, _ = strconv.Atoi(length_re.ReplaceAllString(orig, "$1"))
case "enum", "set":
f.Type = "string"
case "tinyblob", "blob", "mediumblob", "longblob", "binary", "varbinary":
f.Type = "bytes"
@ -127,11 +136,18 @@ func StoreSchema(db *sql.DB, schema, table string) {
func main() {
var err error
field_re, err = regexp.Compile("[(].*")
if err != nil {
log.Fatal("Error: ", err)
}
flag.Usage = PrintUsage;
length_re, err = regexp.Compile(".*[(](.*)[)].*")
if err != nil {
log.Fatal("Error: ", err)
}
flag.Usage = PrintUsage
flag.Parse()
if len(*user) == 0 || len(*passwd) == 0 {

View File

@ -401,8 +401,7 @@ static bool handle_error_new_connection(RWSplit *inst,
* to the client.
*/
GWBUF *stored = NULL;
const SERVER *target;
const SERVER *target = NULL;
if (!session_take_stmt(backend_dcb->session, &stored, &target) ||
target != backend->backend()->server ||
!reroute_stored_statement(*rses, backend, stored))