static MYSQL_FIELD *create_field(PyObject *item){
	assert(item);
	// each item should be a two-size tuple or list.
	if(!PySequence_Check(item) || PySequence_Size(item) != 2){
		PyErr_FormatObject(PyExc_ValueError, "field item %s should be a two-size "
				"sequence.", item);
		return NULL;
	}
	PyObject *item_type = PySequence_GetItem(item, 1);
	PyObject *item_name = PySequence_GetItem(item, 0);
	if(!item_type || !PyInt_Check(item_type)){
		PyErr_SetString(PyExc_ValueError, "field type should be a int");
		Py_XDECREF(item_type);
		return NULL;
	}
	if(!item_name || !PyString_Check(item_name)){
		PyErr_SetString(PyExc_ValueError, "field name should be a string");
		Py_XDECREF(item_name);
		return NULL;
	}
	MYSQL_FIELD *field = network_mysqld_proto_fielddef_new();
	//TODO check the type value.
	field->type = PyInt_AsLong(item_type);
	field->name = g_strdup(PyString_AsString(item_name));
	field->flags = PRI_KEY_FLAG;
	field->length = 32;

	Py_DECREF(item_type);
	Py_DECREF(item_name);
	return field;
}
Esempio n. 2
0
static int lua_table_key_to_mysql_field(lua_State *L, GPtrArray *fields) {
	MYSQL_FIELD *field = NULL;

	field = network_mysqld_proto_fielddef_new();
	if (lua_isstring(L, -2) && !lua_isnumber(L, -2)) {
		/* is-string is true for strings AND numbers
		 * but a tostring() is changing a number into a 
		 * string and that trashes the lua_next() call
		 */
		field->name = g_strdup(lua_tostring(L, -2));
	} else if (lua_isnumber(L, -2)) {
		field->name = g_strdup_printf("%ld", lua_tointeger(L, -2));
	} else {
		/* we don't know how to convert the key */
		field->name = g_strdup("(hmm)");
	}
	field->type = FIELD_TYPE_VAR_STRING; /* STRING matches all values */
	g_ptr_array_add(fields, field);

	return 0;
}
Esempio n. 3
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;
}
Esempio n. 4
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;
}
Esempio n. 5
0
/**
 * test if we parse all the fields of a COM_STMT_PREPARE-ok response correctly
 */
static void t_com_stmt_prepare_ok_from_packet(void) {
	network_mysqld_stmt_prepare_ok_packet_t *cmd;
	network_mysqld_eof_packet_t *eof;
	network_mysqld_proto_fielddef_t *coldef;

	/* a response for the COM_STMT_PREPARE command
	 *
	 * the OK part with stmt-id and so on is in the first packet. The others are
	 * the field-defs, a EOF, the param-defs, and the last EOF */
	strings packets[] = {
		{ C("\x0c\x00\x00\x01\x00\x01\x00\x00\x00\x01\x00\x02\x00\x00\x00\x00") }, /* the PREPARE OK packet */
		{ C("\x17\x00\x00\x02\x03\x64\x65\x66\x00\x00\x00\x01\x3f\x00\x0c\x3f\x00\x00\x00\x00\x00\xfd\x80\x00\x00\x00\x00") }, /* column-def: param 1 */
		{ C("\x17\x00\x00\x03\x03\x64\x65\x66\x00\x00\x00\x01\x3f\x00\x0c\x3f\x00\x00\x00\x00\x00\xfd\x80\x00\x00\x00\x00") }, /* column-def: param 2 */
		{ C("\x05\x00\x00\x04\xfe\x00\x00\x02\x00") }, /* the seperator */
		{ C("\x1a\x00\x00\x05\x03\x64\x65\x66\x00\x00\x00\x04\x63\x6f\x6c\x31\x00\x0c\x3f\x00\x00\x00\x00\x00\xfd\x80\x00\x1f\x00\x00") }, /* column-def: result-col 1 */
		{ C("\x05\x00\x00\x06\xfe\x00\x00\x02\x00") } /* the terminator */
	};
	network_packet packet;

	packet.data = g_string_new_len(packets[0].s, packets[0].s_len);
	packet.offset = 0;

	cmd = network_mysqld_stmt_prepare_ok_packet_new();
	g_assert_cmpint(0, ==, network_mysqld_proto_skip_network_header(&packet));
	g_assert_cmpint(0, ==, network_mysqld_proto_get_stmt_prepare_ok_packet(&packet, cmd));
	g_assert_cmpint(1, ==, cmd->stmt_id);
	g_assert_cmpint(1, ==, cmd->num_columns);
	g_assert_cmpint(2, ==, cmd->num_params);
	g_assert_cmpint(0, ==, cmd->warnings);
	
	network_mysqld_stmt_prepare_ok_packet_free(cmd);

	g_assert_cmpint(packet.offset, ==, packet.data->len); /* is everything parsed */
	g_string_free(packet.data, TRUE);

	packet.data = g_string_new_len(packets[1].s, packets[1].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));

	network_mysqld_proto_fielddef_free(coldef);

	g_assert_cmpint(packet.offset, ==, packet.data->len); /* is everything parsed */
	g_string_free(packet.data, TRUE);


	packet.data = g_string_new_len(packets[2].s, packets[2].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));
	network_mysqld_proto_fielddef_free(coldef);

	g_assert_cmpint(packet.offset, ==, packet.data->len); /* is everything parsed */
	g_string_free(packet.data, TRUE);


	packet.data = g_string_new_len(packets[3].s, packets[3].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);


	packet.data = g_string_new_len(packets[4].s, packets[4].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));
	network_mysqld_proto_fielddef_free(coldef);

	g_assert_cmpint(packet.offset, ==, packet.data->len); /* is everything parsed */
	g_string_free(packet.data, TRUE);


	packet.data = g_string_new_len(packets[5].s, packets[5].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);
}
Esempio n. 6
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);
}