MXS-1929: Take ResultSet into use

Replaced the previous RESULTSET with the new implementation. As the new
ResultSet doesn't have a JSON streaming capability, the MaxInfo JSON
interface has been removed. This should not be a big problem as the REST
API offers the same information in a more secure and structured way.
This commit is contained in:
Markus Mäkelä
2018-07-31 10:03:07 +03:00
parent 8ababa1d39
commit ec420332ea
26 changed files with 216 additions and 1002 deletions

View File

@ -14,7 +14,7 @@
#include <maxscale/cppdefs.hh>
#include <map>
#include <maxscale/resultset.h>
#include <maxscale/resultset.hh>
#include "routersession.hh"
namespace maxscale
@ -161,10 +161,6 @@ public:
void handle_statement(RouterSession* pSession, GWBUF* pStatement);
virtual RESULT_ROW* create_row(RESULTSET* pResult_set);
static RESULT_ROW* create_row(RESULTSET* pResult_set, void* pThis);
int m_counter;
bool m_created;
};

View File

@ -218,13 +218,10 @@ void ResultSetBackend::handle_statement(RouterSession* pSession, GWBUF* pStateme
if (op == QUERY_OP_SELECT)
{
RESULTSET* pResult_set = resultset_create(ResultSetBackend::create_row, this);
resultset_add_column(pResult_set, "a", 4, COL_TYPE_VARCHAR);
std::unique_ptr<ResultSet> set = ResultSet::create({"a"});
set->add_row({std::to_string(++m_counter)});
ResultSetDCB dcb;
resultset_stream_mysql(pResult_set, &dcb);
resultset_free(pResult_set);
set->write(&dcb);
enqueue_response(pSession, dcb.create_response());
}
@ -234,29 +231,6 @@ void ResultSetBackend::handle_statement(RouterSession* pSession, GWBUF* pStateme
}
}
RESULT_ROW* ResultSetBackend::create_row(RESULTSET* pResult_set)
{
RESULT_ROW* pRow = NULL;
if (!m_created)
{
pRow = resultset_make_row(pResult_set);
char buffer[32];
sprintf(buffer, "%d", ++m_counter);
resultset_row_set(pRow, 0, buffer);
m_created = true;
}
return pRow;
}
//static
RESULT_ROW* ResultSetBackend::create_row(RESULTSET* pResult_set, void* pThis)
{
return static_cast<ResultSetBackend*>(pThis)->create_row(pResult_set);
}
} // mock
} // maxscale

View File

@ -40,7 +40,7 @@
#include <maxscale/protocol.h>
#include <maxscale/modinfo.h>
#include <maxscale/log_manager.h>
#include <maxscale/resultset.h>
#include <maxscale/resultset.hh>
#define ISspace(x) isspace((int)(x))
#define HTTP_SERVER_STRING "MaxScale(c) v.1.0.0"
@ -285,7 +285,7 @@ static int httpd_read_event(DCB* dcb)
}
if (strcmp(url, "/services") == 0)
{
RESULTSET *set, *seviceGetList();
ResultSet *set, *seviceGetList();
if ((set = serviceGetList()) != NULL)
{
resultset_stream_json(set, dcb);

View File

@ -35,6 +35,7 @@
#include <maxscale/service.h>
#include <maxscale/sqlite3.h>
#include <maxscale/thread.h>
#include <maxscale/mysql_binlog.h>
MXS_BEGIN_DECLS
@ -67,9 +68,6 @@ MXS_BEGIN_DECLS
#define BLR_REPORT_REP_HEADER 0x02
#define BLR_CHECK_ONLY 0x04
/* MariaDB GTID string len */
#define GTID_MAX_LEN 42
/* GTID slite3 query buffer size */
#define GTID_SQL_BUFFER_SIZE 1024

View File

@ -61,7 +61,7 @@
#include "../../../core/internal/maxscale.h"
#include "../../../core/internal/modules.h"
#include "../../../core/internal/monitor.h"
#include "../../../core/internal/poll.h"
#include "../../../core/internal/poll.hh"
#include "../../../core/internal/session.h"
#include "../../../core/internal/filter.hh"

View File

@ -45,9 +45,9 @@
#include <maxscale/dcb.h>
#include <maxscale/maxscale.h>
#include <maxscale/log_manager.h>
#include <maxscale/resultset.h>
#include <maxscale/resultset.hh>
#include <maxscale/version.h>
#include <maxscale/resultset.h>
#include <maxscale/resultset.hh>
#include <maxscale/secrets.h>
#include <maxscale/users.h>
#include <maxscale/protocol/mysql.h>
@ -55,14 +55,14 @@
#include "../../../core/internal/modules.h"
#include "../../../core/internal/monitor.h"
#include "../../../core/internal/session.h"
#include "../../../core/internal/poll.h"
#include "../../../core/internal/session.hh"
#include "../../../core/internal/poll.hh"
extern char *create_hex_sha1_sha1_passwd(char *passwd);
static int maxinfo_statistics(INFO_INSTANCE *, INFO_SESSION *, GWBUF *);
static int maxinfo_ping(INFO_INSTANCE *, INFO_SESSION *, GWBUF *);
static int maxinfo_execute_query(INFO_INSTANCE *, INFO_SESSION *, char *);
static int handle_url(INFO_INSTANCE *instance, INFO_SESSION *router_session, GWBUF *queue);
static int maxinfo_send_ok(DCB *dcb);
/* The router entry points */
@ -310,7 +310,8 @@ execute(MXS_ROUTER *rinstance, MXS_ROUTER_SESSION *router_session, GWBUF *queue)
if (GWBUF_TYPE(queue) == GWBUF_TYPE_HTTP)
{
return handle_url(instance, session, queue);
gwbuf_free(queue);
return 0;
}
if (session->queue)
{
@ -461,29 +462,6 @@ maxinfo_ping(INFO_INSTANCE *router, INFO_SESSION *session, GWBUF *queue)
return session->dcb->func.write(session->dcb, ret);
}
/**
* Populate the version comment with the MaxScale version
*
* @param result The result set
* @param data Pointer to int which is row count
* @return The populated row
*/
static RESULT_ROW *
version_comment(RESULTSET *result, void *data)
{
int *context = (int *)data;
RESULT_ROW *row;
if (*context == 0)
{
(*context)++;
row = resultset_make_row(result);
resultset_row_set(row, 0, MAXSCALE_VERSION);
return row;
}
return NULL;
}
/**
* The hardwired select @@vercom response
*
@ -492,43 +470,9 @@ version_comment(RESULTSET *result, void *data)
static void
respond_vercom(DCB *dcb)
{
RESULTSET *result;
int context = 0;
if ((result = resultset_create(version_comment, &context)) == NULL)
{
maxinfo_send_error(dcb, 0, "No resources available");
return;
}
resultset_add_column(result, "@@version_comment", 40, COL_TYPE_VARCHAR);
resultset_stream_mysql(result, dcb);
resultset_free(result);
}
/**
* Populate the version comment with the MaxScale version
*
* @param result The result set
* @param data Pointer to int which is row count
* @return The populated row
*/
static RESULT_ROW *
starttime_row(RESULTSET *result, void *data)
{
int *context = (int *)data;
RESULT_ROW *row;
struct tm tm;
static char buf[40];
if (*context == 0)
{
(*context)++;
row = resultset_make_row(result);
sprintf(buf, "%u", (unsigned int)maxscale_started());
resultset_row_set(row, 0, buf);
return row;
}
return NULL;
std::unique_ptr<ResultSet> set = ResultSet::create({"@@version_comment"});
set->add_row({MAXSCALE_VERSION});
set->write(dcb);
}
/**
@ -539,17 +483,9 @@ starttime_row(RESULTSET *result, void *data)
static void
respond_starttime(DCB *dcb)
{
RESULTSET *result;
int context = 0;
if ((result = resultset_create(starttime_row, &context)) == NULL)
{
maxinfo_send_error(dcb, 0, "No resources available");
return;
}
resultset_add_column(result, "starttime", 40, COL_TYPE_VARCHAR);
resultset_stream_mysql(result, dcb);
resultset_free(result);
std::unique_ptr<ResultSet> set = ResultSet::create({"starttime"});
set->add_row({std::to_string(maxscale_started())});
set->write(dcb);
}
/**
@ -651,72 +587,16 @@ maxinfo_execute_query(INFO_INSTANCE *instance, INFO_SESSION *session, char *sql)
* Session all result set
* @return A resultset for all sessions
*/
static RESULTSET *
maxinfoSessionsAll()
static std::unique_ptr<ResultSet> maxinfoSessionsAll()
{
return sessionGetList(SESSION_LIST_ALL);
return sessionGetList();
}
/**
* Client session result set
* @return A resultset for all sessions
*/
static RESULTSET *
maxinfoClientSessions()
static std::unique_ptr<ResultSet> maxinfoClientSessions()
{
return sessionGetList(SESSION_LIST_CONNECTION);
}
typedef RESULTSET *(*RESULTSETFUNC)();
/**
* Table that maps a URI to a function to call to
* to obtain the result set related to that URI
*/
static struct uri_table
{
const char *uri;
RESULTSETFUNC func;
} supported_uri[] =
{
{ "/services", serviceGetList },
{ "/listeners", serviceGetListenerList },
{ "/modules", moduleGetList },
{ "/monitors", monitor_get_list },
{ "/sessions", maxinfoSessionsAll },
{ "/clients", maxinfoClientSessions },
{ "/servers", serverGetList },
{ "/variables", maxinfo_variables },
{ "/status", maxinfo_status },
{ "/event/times", eventTimesGetList },
{ NULL, NULL }
};
/**
* We have data from the client, this is a HTTP URL
*
* @param instance The router instance
* @param session The router session returned from the newSession call
* @param queue The queue of data buffers to route
* @return The number of bytes sent
*/
static int
handle_url(INFO_INSTANCE *instance, INFO_SESSION *session, GWBUF *queue)
{
char *uri;
int i;
RESULTSET *set;
uri = (char *)GWBUF_DATA(queue);
for (i = 0; supported_uri[i].uri; i++)
{
if (strcmp(uri, supported_uri[i].uri) == 0)
{
set = (*supported_uri[i].func)();
resultset_stream_json(set, session->dcb);
resultset_free(set);
}
}
gwbuf_free(queue);
return 1;
return sessionGetList();
}

View File

@ -136,7 +136,7 @@ extern void maxinfo_free_tree(MAXINFO_TREE *);
extern void maxinfo_execute(DCB *, MAXINFO_TREE *);
extern void maxinfo_send_error(DCB *, int, const char *);
extern void maxinfo_send_parse_error(DCB *, char *, PARSE_ERROR);
extern ResultSet *maxinfo_variables();
extern ResultSet *maxinfo_status();
extern std::unique_ptr<ResultSet> maxinfo_variables();
extern std::unique_ptr<ResultSet> maxinfo_status();
#endif

View File

@ -39,7 +39,7 @@
#include <maxscale/maxscale.h>
#include <maxscale/modinfo.h>
#include <maxscale/modutil.h>
#include <maxscale/resultset.h>
#include <maxscale/resultset.hh>
#include <maxscale/router.h>
#include <maxscale/server.hh>
#include <maxscale/service.h>
@ -47,10 +47,13 @@
#include <maxscale/version.h>
#include "../../../core/internal/maxscale.h"
#include "../../../core/internal/modules.h"
#include "../../../core/internal/modules.hh"
#include "../../../core/internal/monitor.h"
#include "../../../core/internal/poll.h"
#include "../../../core/internal/session.h"
#include "../../../core/internal/monitor.hh"
#include "../../../core/internal/poll.hh"
#include "../../../core/internal/session.hh"
#include "../../../core/internal/server.hh"
#include "../../../core/internal/service.hh"
static void exec_show(DCB *dcb, MAXINFO_TREE *tree);
static void exec_select(DCB *dcb, MAXINFO_TREE *tree);
@ -117,15 +120,7 @@ maxinfo_execute(DCB *dcb, MAXINFO_TREE *tree)
static void
exec_show_services(DCB *dcb, MAXINFO_TREE *tree)
{
RESULTSET *set;
if ((set = serviceGetList()) == NULL)
{
return;
}
resultset_stream_mysql(set, dcb);
resultset_free(set);
serviceGetList()->write(dcb);
}
/**
@ -137,15 +132,7 @@ exec_show_services(DCB *dcb, MAXINFO_TREE *tree)
static void
exec_show_listeners(DCB *dcb, MAXINFO_TREE *tree)
{
RESULTSET *set;
if ((set = serviceGetListenerList()) == NULL)
{
return;
}
resultset_stream_mysql(set, dcb);
resultset_free(set);
serviceGetListenerList()->write(dcb);
}
/**
@ -157,15 +144,7 @@ exec_show_listeners(DCB *dcb, MAXINFO_TREE *tree)
static void
exec_show_sessions(DCB *dcb, MAXINFO_TREE *tree)
{
RESULTSET *set;
if ((set = sessionGetList(SESSION_LIST_ALL)) == NULL)
{
return;
}
resultset_stream_mysql(set, dcb);
resultset_free(set);
sessionGetList()->write(dcb);
}
/**
@ -177,15 +156,7 @@ exec_show_sessions(DCB *dcb, MAXINFO_TREE *tree)
static void
exec_show_clients(DCB *dcb, MAXINFO_TREE *tree)
{
RESULTSET *set;
if ((set = sessionGetList(SESSION_LIST_CONNECTION)) == NULL)
{
return;
}
resultset_stream_mysql(set, dcb);
resultset_free(set);
sessionGetList()->write(dcb);
}
/**
@ -197,15 +168,7 @@ exec_show_clients(DCB *dcb, MAXINFO_TREE *tree)
static void
exec_show_servers(DCB *dcb, MAXINFO_TREE *tree)
{
RESULTSET *set;
if ((set = serverGetList()) == NULL)
{
return;
}
resultset_stream_mysql(set, dcb);
resultset_free(set);
serverGetList()->write(dcb);
}
/**
@ -217,15 +180,7 @@ exec_show_servers(DCB *dcb, MAXINFO_TREE *tree)
static void
exec_show_modules(DCB *dcb, MAXINFO_TREE *tree)
{
RESULTSET *set;
if ((set = moduleGetList()) == NULL)
{
return;
}
resultset_stream_mysql(set, dcb);
resultset_free(set);
moduleGetList()->write(dcb);
}
/**
@ -237,15 +192,7 @@ exec_show_modules(DCB *dcb, MAXINFO_TREE *tree)
static void
exec_show_monitors(DCB *dcb, MAXINFO_TREE *tree)
{
RESULTSET *set;
if ((set = monitor_get_list()) == NULL)
{
return;
}
resultset_stream_mysql(set, dcb);
resultset_free(set);
monitor_get_list()->write(dcb);
}
/**
@ -257,15 +204,7 @@ exec_show_monitors(DCB *dcb, MAXINFO_TREE *tree)
static void
exec_show_eventTimes(DCB *dcb, MAXINFO_TREE *tree)
{
RESULTSET *set;
if ((set = eventTimesGetList()) == NULL)
{
return;
}
resultset_stream_mysql(set, dcb);
resultset_free(set);
eventTimesGetList()->write(dcb);
}
/**
@ -845,11 +784,25 @@ static struct
{ NULL, 0, NULL }
};
typedef struct
std::string value_to_string(int type, STATSFUNC func)
{
int index;
const char *like;
} VARCONTEXT;
std::string value;
if (type == VT_STRING)
{
if (char* str = (char*)func())
{
value = str;
}
}
else
{
value = std::to_string((int64_t)func());
}
return value;
}
/**
* Callback function to populate rows of the show variable
* command
@ -857,44 +810,15 @@ typedef struct
* @param data The context point
* @return The next row or NULL if end of rows
*/
static RESULT_ROW *
variable_row(RESULTSET *result, void *data)
static void variable_row(std::unique_ptr<ResultSet>& set, const char* like)
{
VARCONTEXT *context = (VARCONTEXT *)data;
RESULT_ROW *row;
char buf[80];
if (variables[context->index].name)
for (int i = 0; variables[i].name; i++)
{
if (context->like &&
maxinfo_pattern_match(context->like,
variables[context->index].name))
if (!like || !maxinfo_pattern_match(like, variables[i].name))
{
context->index++;
return variable_row(result, data);
set->add_row({variables[i].name, value_to_string(variables[i].type, variables[i].func)});
}
row = resultset_make_row(result);
resultset_row_set(row, 0, variables[context->index].name);
switch (variables[context->index].type)
{
case VT_STRING:
resultset_row_set(row, 1,
(char *)(*variables[context->index].func)());
break;
case VT_INT:
snprintf(buf, 80, "%ld",
(long)(*variables[context->index].func)());
resultset_row_set(row, 1, buf);
break;
default:
ss_dassert(!true);
}
context->index++;
return row;
}
// We only get to this point once all variables have been printed
MXS_FREE(data);
return NULL;
}
/**
@ -906,34 +830,9 @@ variable_row(RESULTSET *result, void *data)
static void
exec_show_variables(DCB *dcb, MAXINFO_TREE *filter)
{
RESULTSET *result;
VARCONTEXT *context;
if ((context = static_cast<VARCONTEXT*>(MXS_MALLOC(sizeof(VARCONTEXT)))) == NULL)
{
return;
}
if (filter)
{
context->like = filter->value;
}
else
{
context->like = NULL;
}
context->index = 0;
if ((result = resultset_create(variable_row, context)) == NULL)
{
maxinfo_send_error(dcb, 0, "No resources available");
MXS_FREE(context);
return;
}
resultset_add_column(result, "Variable_name", 40, COL_TYPE_VARCHAR);
resultset_add_column(result, "Value", 40, COL_TYPE_VARCHAR);
resultset_stream_mysql(result, dcb);
resultset_free(result);
std::unique_ptr<ResultSet> set = ResultSet::create({"Variable_name", "Value"});
variable_row(set, filter ? filter->value : NULL);
set->write(dcb);
}
/**
@ -941,26 +840,11 @@ exec_show_variables(DCB *dcb, MAXINFO_TREE *filter)
*
* @return Variables as a result set
*/
RESULTSET *
maxinfo_variables()
std::unique_ptr<ResultSet> maxinfo_variables()
{
RESULTSET *result;
VARCONTEXT *context;
if ((context = static_cast<VARCONTEXT*>(MXS_MALLOC(sizeof(VARCONTEXT)))) == NULL)
{
return NULL;
}
context->like = NULL;
context->index = 0;
if ((result = resultset_create(variable_row, context)) == NULL)
{
MXS_FREE(context);
return NULL;
}
resultset_add_column(result, "Variable_name", 40, COL_TYPE_VARCHAR);
resultset_add_column(result, "Value", 40, COL_TYPE_VARCHAR);
return result;
std::unique_ptr<ResultSet> set = ResultSet::create({"Variable_name", "Value"});
variable_row(set, NULL);
return set;
}
/**
@ -1129,44 +1013,15 @@ static struct
* @param data The context point
* @return The next row or NULL if end of rows
*/
static RESULT_ROW *
status_row(RESULTSET *result, void *data)
static void status_row(std::unique_ptr<ResultSet>& set, const char* like)
{
VARCONTEXT *context = (VARCONTEXT *)data;
RESULT_ROW *row;
char buf[80];
if (status[context->index].name)
for (int i = 0; status[i].name; i++)
{
if (context->like &&
maxinfo_pattern_match(context->like,
status[context->index].name))
if (!like || !maxinfo_pattern_match(like, status[i].name))
{
context->index++;
return status_row(result, data);
set->add_row({status[i].name, value_to_string(status[i].type, status[i].func)});
}
row = resultset_make_row(result);
resultset_row_set(row, 0, status[context->index].name);
switch (status[context->index].type)
{
case VT_STRING:
resultset_row_set(row, 1,
(char *)(*status[context->index].func)());
break;
case VT_INT:
snprintf(buf, 80, "%" PRId64,
(int64_t)(*status[context->index].func)());
resultset_row_set(row, 1, buf);
break;
default:
ss_dassert(!true);
}
context->index++;
return row;
}
// We only get to this point once all status elements have been printed
MXS_FREE(data);
return NULL;
}
/**
@ -1175,37 +1030,11 @@ status_row(RESULTSET *result, void *data)
* @param dcb The DCB connected to the client
* @param filter A potential like clause or NULL
*/
static void
exec_show_status(DCB *dcb, MAXINFO_TREE *filter)
static void exec_show_status(DCB *dcb, MAXINFO_TREE *filter)
{
RESULTSET *result;
VARCONTEXT *context;
if ((context = static_cast<VARCONTEXT*>(MXS_MALLOC(sizeof(VARCONTEXT)))) == NULL)
{
return;
}
if (filter)
{
context->like = filter->value;
}
else
{
context->like = NULL;
}
context->index = 0;
if ((result = resultset_create(status_row, context)) == NULL)
{
maxinfo_send_error(dcb, 0, "No resources available");
MXS_FREE(context);
return;
}
resultset_add_column(result, "Variable_name", 40, COL_TYPE_VARCHAR);
resultset_add_column(result, "Value", 40, COL_TYPE_VARCHAR);
resultset_stream_mysql(result, dcb);
resultset_free(result);
std::unique_ptr<ResultSet> set = ResultSet::create({"Variable_name", "Value"});
status_row(set, filter ? filter->value : NULL);
set->write(dcb);
}
/**
@ -1213,29 +1042,13 @@ exec_show_status(DCB *dcb, MAXINFO_TREE *filter)
*
* @return The show status data as a result set
*/
RESULTSET *
maxinfo_status()
std::unique_ptr<ResultSet> maxinfo_status()
{
RESULTSET *result;
VARCONTEXT *context;
if ((context = static_cast<VARCONTEXT*>(MXS_MALLOC(sizeof(VARCONTEXT)))) == NULL)
{
return NULL;
}
context->like = NULL;
context->index = 0;
if ((result = resultset_create(status_row, context)) == NULL)
{
MXS_FREE(context);
return NULL;
}
resultset_add_column(result, "Variable_name", 40, COL_TYPE_VARCHAR);
resultset_add_column(result, "Value", 40, COL_TYPE_VARCHAR);
return result;
std::unique_ptr<ResultSet> set = ResultSet::create({"Variable_name", "Value"});
status_row(set, NULL);
return set;
}
/**
* Execute a select command parse tree and return the result set
* or runtime error

View File

@ -21,6 +21,7 @@
#include <maxscale/modutil.h>
#include <maxscale/poll.h>
#include <maxscale/query_classifier.h>
#include <maxscale/resultset.hh>
namespace schemarouter
{
@ -883,24 +884,6 @@ bool detect_show_shards(GWBUF* query)
return rval;
}
/**
* Callback for the shard list result set creation
*/
RESULT_ROW* shard_list_cb(struct resultset* rset, void* data)
{
ServerMap* pContent = (ServerMap*)data;
RESULT_ROW* rval = resultset_make_row(rset);
if (rval)
{
resultset_row_set(rval, 0, pContent->begin()->first.c_str());
resultset_row_set(rval, 1, pContent->begin()->second->name);
pContent->erase(pContent->begin());
}
return rval;
}
/**
* Send a result set of all shards and their locations to the client.
* @param rses Router client session
@ -908,22 +891,18 @@ RESULT_ROW* shard_list_cb(struct resultset* rset, void* data)
*/
bool SchemaRouterSession::send_shards()
{
bool rval = false;
std::unique_ptr<ResultSet> set = ResultSet::create({"Database", "Server"});
ServerMap pContent;
m_shard.get_content(pContent);
RESULTSET* rset = resultset_create(shard_list_cb, &pContent);
if (rset)
for (auto&& a : pContent)
{
resultset_add_column(rset, "Database", MYSQL_DATABASE_MAXLEN, COL_TYPE_VARCHAR);
resultset_add_column(rset, "Server", MYSQL_DATABASE_MAXLEN, COL_TYPE_VARCHAR);
resultset_stream_mysql(rset, m_client);
resultset_free(rset);
rval = true;
set->add_row({a.first, a.second->name});
}
return rval;
set->write(m_client);
return true;
}
/**
@ -1677,34 +1656,6 @@ enum route_target get_shard_route_target(uint32_t qtype)
return target;
}
/**
* Callback for the database list streaming.
* @param rset Result set which is being processed
* @param data Pointer to struct string_array containing the database names
* @return New resultset row or NULL if no more data is available. If memory allocation
* failed, NULL is returned.
*/
RESULT_ROW *result_set_cb(struct resultset * rset, void *data)
{
RESULT_ROW *row = resultset_make_row(rset);
std::list<std::string>* arr = (std::list<std::string>*) data;
if (row)
{
if (arr->size() > 0 && resultset_row_set(row, 0, arr->begin()->c_str()))
{
arr->erase(arr->begin());
}
else
{
resultset_free_row(row);
row = NULL;
}
}
return row;
}
/**
* Generates a custom SHOW DATABASES result set from all the databases in the
* hashtable. Only backend servers that are up and in a proper state are listed
@ -1727,15 +1678,15 @@ bool SchemaRouterSession::send_databases()
list.push_back(db);
}
}
RESULTSET* resultset = resultset_create(result_set_cb, &list);
if (resultset_add_column(resultset, "Database", MYSQL_DATABASE_MAXLEN,
COL_TYPE_VARCHAR))
std::unique_ptr<ResultSet> set = ResultSet::create({"Table"});
for (auto&& a : list)
{
resultset_stream_mysql(resultset, m_client);
rval = true;
set->add_row({a});
}
resultset_free(resultset);
set->write(m_client);
return rval;
}
@ -1779,18 +1730,19 @@ bool SchemaRouterSession::send_tables(GWBUF* pPacket)
list.push_back(table);
}
}
if (!list.empty())
{
RESULTSET* resultset = resultset_create(result_set_cb, &list);
std::unique_ptr<ResultSet> set = ResultSet::create({"Table"});
if (resultset_add_column(resultset, "Table", MYSQL_DATABASE_MAXLEN,
COL_TYPE_VARCHAR))
for (auto&& a : list)
{
resultset_stream_mysql(resultset, m_client);
rval = true;
set->add_row({a});
}
resultset_free(resultset);
set->write(m_client);
}
MXS_FREE(query);
return rval;
}