Commit ab09e22a authored by Roman Nozdrin's avatar Roman Nozdrin Committed by Sergei Petrunia

CLX-3 Add support for UTF-8 encoded object names in SQL statements.

        Add support for RENAME TABLE.

        Fixed a double free bug in discover_table_details.
parent 20629a52
...@@ -19,7 +19,7 @@ extern char *clustrix_password; ...@@ -19,7 +19,7 @@ extern char *clustrix_password;
extern uint clustrix_port; extern uint clustrix_port;
extern char *clustrix_socket; extern char *clustrix_socket;
static const char charset_name[] = "latin1"; static const char charset_name[] = "utf8";
enum clustrix_commands { enum clustrix_commands {
CLUSTRIX_WRITE_ROW = 1, CLUSTRIX_WRITE_ROW = 1,
...@@ -195,6 +195,14 @@ int clustrix_connection::delete_table(String &stmt) ...@@ -195,6 +195,14 @@ int clustrix_connection::delete_table(String &stmt)
return error_code; return error_code;
} }
int clustrix_connection::rename_table(String &stmt)
{
int error_code = mysql_real_query(&clustrix_net, stmt.ptr(), stmt.length());
if (error_code)
return mysql_errno(&clustrix_net);
return error_code;
}
int clustrix_connection::write_row(ulonglong clustrix_table_oid, int clustrix_connection::write_row(ulonglong clustrix_table_oid,
uchar *packed_row, size_t packed_size) uchar *packed_row, size_t packed_size)
{ {
...@@ -398,7 +406,8 @@ int clustrix_connection::discover_table_details(LEX_CSTRING *db, ...@@ -398,7 +406,8 @@ int clustrix_connection::discover_table_details(LEX_CSTRING *db,
{ {
DBUG_ENTER("clustrix_connection::discover_table_details"); DBUG_ENTER("clustrix_connection::discover_table_details");
int error_code = 0; int error_code = 0;
MYSQL_RES *results = NULL; MYSQL_RES *results_oid = NULL;
MYSQL_RES *results_create = NULL;
MYSQL_ROW row; MYSQL_ROW row;
String get_oid, show; String get_oid, show;
...@@ -411,6 +420,7 @@ int clustrix_connection::discover_table_details(LEX_CSTRING *db, ...@@ -411,6 +420,7 @@ int clustrix_connection::discover_table_details(LEX_CSTRING *db,
get_oid.append("' and r.name = '"); get_oid.append("' and r.name = '");
get_oid.append(name); get_oid.append(name);
get_oid.append("'"); get_oid.append("'");
if (mysql_real_query(&clustrix_net, get_oid.c_ptr(), get_oid.length())) { if (mysql_real_query(&clustrix_net, get_oid.c_ptr(), get_oid.length())) {
if ((error_code = mysql_errno(&clustrix_net))) { if ((error_code = mysql_errno(&clustrix_net))) {
DBUG_PRINT("mysql_real_query returns ", ("%d", error_code)); DBUG_PRINT("mysql_real_query returns ", ("%d", error_code));
...@@ -419,17 +429,17 @@ int clustrix_connection::discover_table_details(LEX_CSTRING *db, ...@@ -419,17 +429,17 @@ int clustrix_connection::discover_table_details(LEX_CSTRING *db,
} }
} }
results = mysql_store_result(&clustrix_net); results_oid = mysql_store_result(&clustrix_net);
DBUG_PRINT("oid results", DBUG_PRINT("oid results",
("rows: %llu, fields: %u", mysql_num_rows(results), ("rows: %llu, fields: %u", mysql_num_rows(results_oid),
mysql_num_fields(results))); mysql_num_fields(results_oid)));
if (mysql_num_rows(results) != 1) { if (mysql_num_rows(results_oid) != 1) {
error_code = HA_ERR_NO_SUCH_TABLE; error_code = HA_ERR_NO_SUCH_TABLE;
goto error; goto error;
} }
while((row = mysql_fetch_row(results))) { while((row = mysql_fetch_row(results_oid))) {
DBUG_PRINT("row", ("%s", row[0])); DBUG_PRINT("row", ("%s", row[0]));
uchar *to = (uchar*)alloc_root(&share->mem_root, strlen(row[0]) + 1); uchar *to = (uchar*)alloc_root(&share->mem_root, strlen(row[0]) + 1);
if (!to) { if (!to) {
...@@ -442,8 +452,6 @@ int clustrix_connection::discover_table_details(LEX_CSTRING *db, ...@@ -442,8 +452,6 @@ int clustrix_connection::discover_table_details(LEX_CSTRING *db,
share->tabledef_version.length = strlen(row[0]); share->tabledef_version.length = strlen(row[0]);
} }
mysql_free_result(results);
/* get show create statement */ /* get show create statement */
show.append("show create table "); show.append("show create table ");
show.append(db); show.append(db);
...@@ -457,30 +465,33 @@ int clustrix_connection::discover_table_details(LEX_CSTRING *db, ...@@ -457,30 +465,33 @@ int clustrix_connection::discover_table_details(LEX_CSTRING *db,
} }
} }
results = mysql_store_result(&clustrix_net); results_create = mysql_store_result(&clustrix_net);
DBUG_PRINT("show table results", DBUG_PRINT("show table results",
("rows: %llu, fields: %u", mysql_num_rows(results), ("rows: %llu, fields: %u", mysql_num_rows(results_create),
mysql_num_fields(results))); mysql_num_fields(results_create)));
if (mysql_num_rows(results) != 1) { if (mysql_num_rows(results_create) != 1) {
error_code = HA_ERR_NO_SUCH_TABLE; error_code = HA_ERR_NO_SUCH_TABLE;
goto error; goto error;
} }
if (mysql_num_fields(results) != 2) { if (mysql_num_fields(results_create) != 2) {
error_code = HA_ERR_CORRUPT_EVENT; error_code = HA_ERR_CORRUPT_EVENT;
goto error; goto error;
} }
while((row = mysql_fetch_row(results))) { while((row = mysql_fetch_row(results_create))) {
DBUG_PRINT("row", ("%s - %s", row[0], row[1])); DBUG_PRINT("row", ("%s - %s", row[0], row[1]));
error_code = share->init_from_sql_statement_string(thd, false, row[1], error_code = share->init_from_sql_statement_string(thd, false, row[1],
strlen(row[1])); strlen(row[1]));
} }
error: error:
if (results) if (results_oid)
mysql_free_result(results); mysql_free_result(results_oid);
if (results_create)
mysql_free_result(results_create);
DBUG_RETURN(error_code); DBUG_RETURN(error_code);
} }
......
...@@ -66,6 +66,7 @@ class clustrix_connection ...@@ -66,6 +66,7 @@ class clustrix_connection
int create_table(String &stmt); int create_table(String &stmt);
int delete_table(String &stmt); int delete_table(String &stmt);
int rename_table(String &stmt);
int write_row(ulonglong clustrix_table_oid, int write_row(ulonglong clustrix_table_oid,
uchar *packed_row, size_t packed_size); uchar *packed_row, size_t packed_size);
......
...@@ -148,7 +148,7 @@ int st_clustrixdb_trx::begin_trans() ...@@ -148,7 +148,7 @@ int st_clustrixdb_trx::begin_trans()
/**************************************************************************** /****************************************************************************
** Utility functions ** Utility functions
****************************************************************************/ ****************************************************************************/
// This is a wastefull aproach but better then fixed sized buffer.RALLEL // This is a wastefull aproach but better then fixed sized buffer.
size_t estimate_row_size(TABLE *table) size_t estimate_row_size(TABLE *table)
{ {
size_t row_size = 0; size_t row_size = 0;
...@@ -161,6 +161,22 @@ size_t estimate_row_size(TABLE *table) ...@@ -161,6 +161,22 @@ size_t estimate_row_size(TABLE *table)
return row_size; return row_size;
} }
/**
* @brief
* Decodes object name.
*
* @details
* Replaces the encoded object name in the path with a decoded variant,
* e.g if path contains ./test/d@0024. This f() makes it ./test/d$
*
* Used in delete and rename DDL processing.
**/
void decode_objectname(char *buf, const char *path, size_t buf_size)
{
size_t new_path_len = filename_to_tablename(path, buf, buf_size);
buf[new_path_len] = '\0';
}
/**************************************************************************** /****************************************************************************
** Class ha_clustrixdb ** Class ha_clustrixdb
****************************************************************************/ ****************************************************************************/
...@@ -220,7 +236,7 @@ int ha_clustrixdb::create(const char *name, TABLE *form, HA_CREATE_INFO *info) ...@@ -220,7 +236,7 @@ int ha_clustrixdb::create(const char *name, TABLE *form, HA_CREATE_INFO *info)
return error_code; return error_code;
} }
int ha_clustrixdb::delete_table(const char *name) int ha_clustrixdb::delete_table(const char *path)
{ {
int error_code; int error_code;
THD *thd = ha_thd(); THD *thd = ha_thd();
...@@ -228,22 +244,63 @@ int ha_clustrixdb::delete_table(const char *name) ...@@ -228,22 +244,63 @@ int ha_clustrixdb::delete_table(const char *name)
if (!trx) if (!trx)
return error_code; return error_code;
// This block isn't UTF aware yet.
// The format contains './' in the beginning of a path. // The format contains './' in the beginning of a path.
char *dbname_end = (char*) name + 2; char *dbname_end = (char*) path + 2;
while (*dbname_end != '/') while (*dbname_end != '/')
dbname_end++; dbname_end++;
char decoded_tbname[FN_REFLEN];
decode_objectname(decoded_tbname, dbname_end + 1, FN_REFLEN);
String delete_cmd; String delete_cmd;
delete_cmd.append("DROP TABLE `"); delete_cmd.append("DROP TABLE `");
delete_cmd.append(name + 2, dbname_end - name - 2); delete_cmd.append(path + 2, dbname_end - path - 2);
delete_cmd.append("`.`"); delete_cmd.append("`.`");
delete_cmd.append(dbname_end + 1); delete_cmd.append(decoded_tbname);
delete_cmd.append("`"); delete_cmd.append("`");
return trx->clustrix_net->delete_table(delete_cmd); return trx->clustrix_net->delete_table(delete_cmd);
} }
int ha_clustrixdb::rename_table(const char* from, const char* to)
{
int error_code;
THD *thd = ha_thd();
st_clustrixdb_trx *trx = get_trx(thd, &error_code);
if (!trx)
return error_code;
// The format contains './' in the beginning of a path.
char *from_dbname_end = (char*) from + 2;
while (*from_dbname_end != '/')
from_dbname_end++;
char decoded_from_tbname[FN_REFLEN];
decode_objectname(decoded_from_tbname, from_dbname_end + 1, FN_REFLEN);
char *to_dbname_end = (char*) to + 2;
while (*to_dbname_end != '/')
to_dbname_end++;
char decoded_to_tbname[FN_REFLEN];
decode_objectname(decoded_to_tbname, to_dbname_end + 1, FN_REFLEN);
String rename_cmd;
rename_cmd.append("RENAME TABLE `");
rename_cmd.append(from + 2, from_dbname_end - from - 2);
rename_cmd.append("`.`");
rename_cmd.append(decoded_from_tbname);
rename_cmd.append("` TO `");
rename_cmd.append(to + 2, to_dbname_end - to - 2);
rename_cmd.append("`.`");
rename_cmd.append(decoded_to_tbname);
rename_cmd.append("`;");
return trx->clustrix_net->rename_table(rename_cmd);
}
int ha_clustrixdb::open(const char *name, int mode, uint test_if_locked) int ha_clustrixdb::open(const char *name, int mode, uint test_if_locked)
{ {
DBUG_ENTER("ha_clustrixdb::open"); DBUG_ENTER("ha_clustrixdb::open");
......
...@@ -63,6 +63,7 @@ class ha_clustrixdb : public handler ...@@ -63,6 +63,7 @@ class ha_clustrixdb : public handler
~ha_clustrixdb(); ~ha_clustrixdb();
int create(const char *name, TABLE *form, HA_CREATE_INFO *info); int create(const char *name, TABLE *form, HA_CREATE_INFO *info);
int delete_table(const char *name); int delete_table(const char *name);
int rename_table(const char* from, const char* to);
int open(const char *name, int mode, uint test_if_locked); int open(const char *name, int mode, uint test_if_locked);
int close(void); int close(void);
int reset(); int reset();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment