/** * Handle the proxy.response to con. * proxy.response * .type can be either ERR, OK or RAW * .resultset (in case of OK) * .fields * .rows * .errmsg (in case of ERR) * .packet (in case of nil) * Note: if error occurred, should set the error string. */ int network_mysqld_con_python_handle_proxy_response(network_mysqld_con *con, PyObject *proxy){ assert(proxy); PyObject *response = PyObject_GetAttrString(proxy, "response"); //Note: the response is fetched through the tp_getset, and is a new reference. assert(response); Py_DECREF(response); PyObject *res_type = PyObject_GetAttrString(response, "type"); if(!res_type){ network_mysqld_con_send_error(con->client, C("Cannot get proxy.response.type")); return -1; } int res_type_int = PyInt_AsLong(res_type); Py_DECREF(res_type); switch(res_type_int){ case MYSQLD_PACKET_OK:{ PyObject *resultset = PyObject_GetAttrString(response, "resultset"); if(!resultset){ PyErr_Clear(); guint64 affected_rows = 0; guint64 insert_id = 0; PyObject *ar = PyObject_GetAttrString(response, "affected_rows"); if(!ar) PyErr_Clear(); else if(PyLong_Check(ar)) affected_rows = PyLong_AsLong(ar); else if(PyInt_Check(ar)) affected_rows = PyInt_AsLong(ar); Py_XDECREF(ar); PyObject *ii = PyObject_GetAttrString(response, "insert_id"); if(!ii) PyErr_Clear(); else if(PyLong_Check(ii)) insert_id = PyLong_AsLong(ii); else if(PyInt_Check(ii)) insert_id = PyInt_AsLong(ii); Py_XDECREF(ii); network_mysqld_con_send_ok_full(con->client, affected_rows, insert_id, 0x0002, 0); } else{ Py_DECREF(resultset); GPtrArray *fields = create_fields(resultset); if(!fields){ network_mysqld_con_send_error(con->client, C("Cannot get proxy.response.resultset.fields!")); PyErr_Print(); PyErr_Clear(); return -1; } if(fields->len <= 0){ network_mysqld_con_send_error(con->client, C("Size of proxy.response.resultset.fields is 0")); network_mysqld_proto_fielddefs_free(fields); return -1; } GPtrArray *rows = create_rows(resultset); if(!rows){ network_mysqld_con_send_error(con->client, C("Cannot get proxy.response.resultset.rows")); PyErr_Print(); network_mysqld_proto_fielddefs_free(fields); return -1; } network_mysqld_con_send_resultset(con->client, fields, rows); if (fields) { network_mysqld_proto_fielddefs_free(fields); fields = NULL; } if (rows) { guint i; for (i = 0; i < rows->len; i++) { GPtrArray *row = rows->pdata[i]; guint j; for (j = 0; j < row->len; j++) if (row->pdata[j]) g_free(row->pdata[j]); g_ptr_array_free(row, TRUE); } g_ptr_array_free(rows, TRUE); rows = NULL; } } break;} case MYSQLD_PACKET_ERR:{ gint errcode = ER_UNKNOWN_ERROR; /** let's call ourself Dynamic SQL ... 07000 is "dynamic SQL error" */ const gchar *sqlstate = "07000"; gchar *errmsg = NULL; PyObject *err_code = PyObject_GetAttrString(response, "errcode"); if(!err_code) //Here use the default error code: ER_UNKNOWN_ERROR PyErr_Clear(); else{ errcode = PyInt_AsLong(err_code); Py_DECREF(err_code); } PyObject *sql_state = PyObject_GetAttrString(response, "sqlstate"); if(!sql_state) //Here use the default sql state: 07000 PyErr_Clear(); else{ sqlstate = PyString_AsString(sql_state); Py_DECREF(sql_state); } PyObject *err_msg = PyObject_GetAttrString(response, "errmsg"); if(!err_msg){ PyErr_Clear(); network_mysqld_con_send_error(con->client, C("(python) proxy.response.errmsg is nil")); } else{ errmsg = PyString_AsString(err_msg); Py_DECREF(err_msg); network_mysqld_con_send_error_full(con->client, errmsg, strlen(errmsg), errcode, sqlstate); } break;} case MYSQLD_PACKET_RAW:{ PyObject *packets = PyObject_GetAttrString(response, "packets"); if(!packets) goto queue_reset; int i; for(i = 0; i < PySequence_Size(packets); i++){ PyObject *item = PySequence_GetItem(packets, i); //If invalid items doesn't influces valid ones before them. if(!item) goto queue_reset; if(!PyString_Check(item)){ PyErr_SetString(PyExc_ValueError, "proxy.response.packets' " "items should be strings."); Py_DECREF(item); Py_DECREF(packets); goto queue_reset; } network_mysqld_queue_append(con->client, con->client->send_queue, PyString_AsString(item), PyString_Size(item)); Py_DECREF(item); } Py_DECREF(packets); queue_reset: /* reset the packet-id checks */ network_mysqld_queue_reset(con->client); break;} default: g_critical("Now the response type is unknown: %d", res_type_int); return -1; } return 0; }
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; }