network_mysqld_table *network_mysqld_table_new() { network_mysqld_table *tbl; tbl = g_new0(network_mysqld_table, 1); tbl->db_name = g_string_new(NULL); tbl->table_name = g_string_new(NULL); tbl->fields = network_mysqld_proto_fielddefs_new(); return tbl; }
/** * parse the result-set of the query * * @return if this is not a result-set we return -1 */ static int parse_resultset_fields(proxy_resultset_t *res) { GList *chunk; g_return_val_if_fail(res->result_queue != NULL, -1); if (res->fields) return 0; /* parse the fields */ res->fields = network_mysqld_proto_fielddefs_new(); if (!res->fields) return -1; chunk = network_mysqld_proto_get_fielddefs(res->result_queue->head, res->fields); /* no result-set found */ if (!chunk) return -1; /* skip the end-of-fields chunk */ res->rows_chunk_head = chunk->next; return 0; }
static GPtrArray *create_fields(PyObject *resultset){ assert(resultset); if(!PyDict_Check(resultset)){ PyErr_SetString(PyExc_ValueError, "response.resultset must be a dict"); return NULL; } PyObject *res_fields = PyDict_GetItemString(resultset, "fields"); if(!res_fields){ PyErr_SetString(PyExc_KeyError, "resultset has no key named 'fields'!"); return NULL; } if(!PySequence_Check(res_fields)){ PyErr_SetString(PyExc_ValueError, "proxy.response.resultset.fields " "should be eigher a list or a tuple"); return NULL; } GPtrArray *fields = network_mysqld_proto_fielddefs_new(); int i; for(i = 0; i < PySequence_Size(res_fields); i++){ PyObject *item = PySequence_GetItem(res_fields, i); if(!item){ network_mysqld_proto_fielddefs_free(fields); g_critical("Create item failed"); return NULL; } MYSQL_FIELD *field = create_field(item); Py_DECREF(item); if(!field){ network_mysqld_proto_fielddefs_free(fields); g_critical("Create fields failed"); return NULL; } g_ptr_array_add(fields, field); } return fields; }
int plugin_debug_con_handle_stmt(chassis *chas, network_mysqld_con *con, GString *s) { gsize i, j; GPtrArray *fields; GPtrArray *rows; GPtrArray *row; switch(s->str[NET_HEADER_SIZE]) { case COM_QUERY: fields = NULL; rows = NULL; row = NULL; /* support the basic commands sent by the mysql shell */ if (0 == g_ascii_strncasecmp(s->str + NET_HEADER_SIZE + 1, C("select @@version_comment limit 1"))) { MYSQL_FIELD *field; fields = network_mysqld_proto_fielddefs_new(); field = network_mysqld_proto_fielddef_new(); field->name = g_strdup("@@version_comment"); field->type = FIELD_TYPE_VAR_STRING; g_ptr_array_add(fields, field); rows = g_ptr_array_new(); row = g_ptr_array_new(); g_ptr_array_add(row, g_strdup("MySQL Enterprise Agent")); g_ptr_array_add(rows, row); network_mysqld_con_send_resultset(con->client, fields, rows); } else if (0 == g_ascii_strncasecmp(s->str + NET_HEADER_SIZE + 1, C("select USER()"))) { MYSQL_FIELD *field; fields = network_mysqld_proto_fielddefs_new(); field = network_mysqld_proto_fielddef_new(); field->name = g_strdup("USER()"); field->type = FIELD_TYPE_VAR_STRING; g_ptr_array_add(fields, field); rows = g_ptr_array_new(); row = g_ptr_array_new(); g_ptr_array_add(row, g_strdup("root")); g_ptr_array_add(rows, row); network_mysqld_con_send_resultset(con->client, fields, rows); } else { #if 0 MYSQL_FIELD *field = NULL; lua_State *L = chas->priv->sc->L; if (0 == luaL_loadstring(L, s->str + NET_HEADER_SIZE + 1) && 0 == lua_pcall(L, 0, 1, 0)) { /* let's see what is on the stack * - scalars are turned into strings * return "foo" * - 1-dim tables are turned into a single-row result-set * return { foo = "bar", baz = "foz" } * - 2-dim tables are turned into a multi-row result-set * return { { foo = "bar" }, { "foz" } } */ switch (lua_type(L, -1)) { case LUA_TTABLE: /* take the names from the fields */ fields = network_mysqld_proto_fielddefs_new(); lua_pushnil(L); while (lua_next(L, -2) != 0) { if (lua_istable(L, -1)) { /* 2-dim table * * we only only take the keys from the first row * afterwards we ignore them */ lua_pushnil(L); while (lua_next(L, -2) != 0) { if (!rows) { /* this is the 1st round, add the keys */ lua_table_key_to_mysql_field(L, fields); } if (!row) row = g_ptr_array_new(); if (lua_isboolean(L, -1)) { g_ptr_array_add(row, g_strdup(lua_toboolean(L, -1) ? "TRUE" : "FALSE")); } else if (lua_isnumber(L, -1)) { g_ptr_array_add(row, g_strdup_printf("%.0f", lua_tonumber(L, -1))); } else { g_ptr_array_add(row, g_strdup(lua_tostring(L, -1))); } lua_pop(L, 1); /* pop the value, but keep the key on the stack */ } if (!rows) rows = g_ptr_array_new(); g_ptr_array_add(rows, row); row = NULL; } else { /* 1-dim table */ lua_table_key_to_mysql_field(L, fields); if (!row) row = g_ptr_array_new(); if (lua_isboolean(L, -1)) { g_ptr_array_add(row, g_strdup(lua_toboolean(L, -1) ? "TRUE" : "FALSE")); } else if (lua_isnumber(L, -1)) { g_ptr_array_add(row, g_strdup_printf("%.0f", lua_tonumber(L, -1))); } else { g_ptr_array_add(row, g_strdup(lua_tostring(L, -1))); } } lua_pop(L, 1); /* pop the value, but keep the key on the stack */ } if (row) { /* in 1-dim we have to append the row to the result-set, * in 2-dim this is already done and row is NULL */ if (!rows) rows = g_ptr_array_new(); g_ptr_array_add(rows, row); } break; default: /* a scalar value */ fields = network_mysqld_proto_fielddefs_new(); field = network_mysqld_proto_fielddef_new(); field->name = g_strdup("lua"); field->type = FIELD_TYPE_VAR_STRING; g_ptr_array_add(fields, field); rows = g_ptr_array_new(); row = g_ptr_array_new(); g_ptr_array_add(row, g_strdup(lua_tostring(L, -1))); g_ptr_array_add(rows, row); break; } lua_pop(L, 1); /* get rid of the result */ network_mysqld_con_send_resultset(con->client, fields, rows); } /* if we don't have fields for the resultset, we should have a * error-msg on the stack */ if (!fields) { size_t err_len = 0; const char *err; err = lua_tolstring(L, -1, &err_len); network_mysqld_con_send_error(con->client, err, err_len); lua_pop(L, 1); } #endif } /* clean up */ if (fields) { network_mysqld_proto_fielddefs_free(fields); fields = NULL; } if (rows) { for (i = 0; i < rows->len; i++) { row = rows->pdata[i]; for (j = 0; j < row->len; j++) { g_free(row->pdata[j]); } g_ptr_array_free(row, TRUE); } g_ptr_array_free(rows, TRUE); rows = NULL; } break; case COM_QUIT: break; case COM_INIT_DB: network_mysqld_con_send_ok(con->client); break; default: network_mysqld_con_send_error(con->client, C("unknown COM_*")); break; } return 0; }
static int network_mysqld_con_handle_stmt(chassis G_GNUC_UNUSED *chas, network_mysqld_con *con, GString *s) { gsize i, j; GPtrArray *fields; GPtrArray *rows; GPtrArray *row; switch(s->str[NET_HEADER_SIZE]) { case COM_QUERY: fields = NULL; rows = NULL; row = NULL; if (0 == g_ascii_strncasecmp(s->str + NET_HEADER_SIZE + 1, C("select @@version_comment limit 1"))) { MYSQL_FIELD *field; fields = network_mysqld_proto_fielddefs_new(); field = network_mysqld_proto_fielddef_new(); field->name = g_strdup("@@version_comment"); field->type = FIELD_TYPE_VAR_STRING; g_ptr_array_add(fields, field); rows = g_ptr_array_new(); row = g_ptr_array_new(); g_ptr_array_add(row, g_strdup("MySQL Enterprise Agent")); g_ptr_array_add(rows, row); network_mysqld_con_send_resultset(con->client, fields, rows); } else if (0 == g_ascii_strncasecmp(s->str + NET_HEADER_SIZE + 1, C("select USER()"))) { MYSQL_FIELD *field; fields = network_mysqld_proto_fielddefs_new(); field = network_mysqld_proto_fielddef_new(); field->name = g_strdup("USER()"); field->type = FIELD_TYPE_VAR_STRING; g_ptr_array_add(fields, field); rows = g_ptr_array_new(); row = g_ptr_array_new(); g_ptr_array_add(row, g_strdup("root")); g_ptr_array_add(rows, row); network_mysqld_con_send_resultset(con->client, fields, rows); } else { network_mysqld_con_send_error(con->client, C("(master-server) query not known")); } /* clean up */ if (fields) { network_mysqld_proto_fielddefs_free(fields); fields = NULL; } if (rows) { for (i = 0; i < rows->len; i++) { row = rows->pdata[i]; for (j = 0; j < row->len; j++) { g_free(row->pdata[j]); } g_ptr_array_free(row, TRUE); } g_ptr_array_free(rows, TRUE); rows = NULL; } break; case COM_QUIT: break; case COM_INIT_DB: network_mysqld_con_send_ok(con->client); break; default: network_mysqld_con_send_error(con->client, C("unknown COM_*")); break; } return 0; }
/** * test if we parse all the fields of a COM_STMT_EXECUTE result correctly */ static void t_com_stmt_execute_result_from_packet(void) { network_mysqld_eof_packet_t *eof; network_mysqld_proto_fielddefs_t *coldefs; network_mysqld_proto_fielddef_t *coldef; network_mysqld_resultset_row_t *row; network_mysqld_type_t *field; GString *data; guint64 field_count; int packet_id = 0; /* response for a * SELECT ? AS col2, CONCAT(?, ?) AS col1 * with * 1: NULL * 2: STRING bar * 3: STRING foo */ strings packets[] = { { C("\x01\x00\x00\x01\x02") }, { C("\x1a\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x04\x63\x6f\x6c\x32\x00\x0c\x3f\x00\x00\x00\x00\x00\xfe\x80\x00\x00\x00\x00") }, { C("\x1a\x00\x00\x03\x03\x64\x65\x66\x00\x00\x00\x04\x63\x6f\x6c\x31\x00\x0c\x08\x00\x06\x00\x00\x00\xfd\x00\x00\x1f\x00\x00") }, { C("\x05\x00\x00\x04\xfe\x00\x00\x02\x00") }, { C("\x09\x00\x00\x05\x00\x04\x06" "barfoo") }, { C("\x05\x00\x00\x06\xfe\x00\x00\x02\x00") } }; network_packet packet; /* the field-count */ packet_id = 0; packet.data = g_string_new_len(packets[packet_id].s, packets[packet_id].s_len); packet.offset = 0; g_assert_cmpint(0, ==, network_mysqld_proto_skip_network_header(&packet)); g_assert_cmpint(0, ==, network_mysqld_proto_get_lenenc_int(&packet, &field_count)); g_assert_cmpint(2, ==, field_count); g_assert_cmpint(packet.offset, ==, packet.data->len); /* is everything parsed */ g_string_free(packet.data, TRUE); /* the colum defs */ packet_id++; packet.data = g_string_new_len(packets[packet_id].s, packets[packet_id].s_len); packet.offset = 0; coldefs = network_mysqld_proto_fielddefs_new(); coldef = network_mysqld_proto_fielddef_new(); g_assert_cmpint(0, ==, network_mysqld_proto_skip_network_header(&packet)); g_assert_cmpint(0, ==, network_mysqld_proto_get_fielddef(&packet, coldef, CLIENT_PROTOCOL_41)); g_ptr_array_add(coldefs, coldef); g_assert_cmpint(packet.offset, ==, packet.data->len); /* is everything parsed */ g_string_free(packet.data, TRUE); /* the string column */ packet_id++; packet.data = g_string_new_len(packets[packet_id].s, packets[packet_id].s_len); packet.offset = 0; coldef = network_mysqld_proto_fielddef_new(); g_assert_cmpint(0, ==, network_mysqld_proto_skip_network_header(&packet)); g_assert_cmpint(0, ==, network_mysqld_proto_get_fielddef(&packet, coldef, CLIENT_PROTOCOL_41)); g_ptr_array_add(coldefs, coldef); g_assert_cmpint(packet.offset, ==, packet.data->len); /* is everything parsed */ g_string_free(packet.data, TRUE); /* the EOF */ packet_id++; packet.data = g_string_new_len(packets[packet_id].s, packets[packet_id].s_len); packet.offset = 0; eof = network_mysqld_eof_packet_new(); g_assert_cmpint(0, ==, network_mysqld_proto_skip_network_header(&packet)); g_assert_cmpint(0, ==, network_mysqld_proto_get_eof_packet(&packet, eof)); network_mysqld_eof_packet_free(eof); g_assert_cmpint(packet.offset, ==, packet.data->len); /* is everything parsed */ g_string_free(packet.data, TRUE); /* the row */ packet_id++; packet.data = g_string_new_len(packets[packet_id].s, packets[packet_id].s_len); packet.offset = 0; row = network_mysqld_resultset_row_new(); g_assert_cmpint(0, ==, network_mysqld_proto_skip_network_header(&packet)); g_assert_cmpint(0, ==, network_mysqld_proto_get_binary_row(&packet, coldefs, row)); /* check if the 1st field is NULL */ field = g_ptr_array_index(row, 0); g_assert(field); g_assert_cmpint(TRUE, ==, field->is_null); /* check if the 2nd field is "barfoo" */ field = g_ptr_array_index(row, 1); g_assert(field); g_assert_cmpint(MYSQL_TYPE_VAR_STRING, ==, field->type); g_assert_cmpint(FALSE, ==, field->is_null); /* FIXME: find a way to test this without touching the internal representation */ data = field->data; g_assert(data); g_assert_cmpint(data->len, ==, 6); g_assert_cmpstr(data->str, ==, "barfoo"); network_mysqld_resultset_row_free(row); g_assert_cmpint(packet.offset, ==, packet.data->len); /* is everything parsed */ g_string_free(packet.data, TRUE); packet_id++; packet.data = g_string_new_len(packets[packet_id].s, packets[packet_id].s_len); packet.offset = 0; eof = network_mysqld_eof_packet_new(); g_assert_cmpint(0, ==, network_mysqld_proto_skip_network_header(&packet)); g_assert_cmpint(0, ==, network_mysqld_proto_get_eof_packet(&packet, eof)); network_mysqld_eof_packet_free(eof); g_assert_cmpint(packet.offset, ==, packet.data->len); /* is everything parsed */ g_string_free(packet.data, TRUE); network_mysqld_proto_fielddefs_free(coldefs); }