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;
extern uint clustrix_port;
extern char *clustrix_socket;
static const char charset_name[] = "latin1";
static const char charset_name[] = "utf8";
enum clustrix_commands {
CLUSTRIX_WRITE_ROW = 1,
......@@ -195,6 +195,14 @@ int clustrix_connection::delete_table(String &stmt)
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,
uchar *packed_row, size_t packed_size)
{
......@@ -398,7 +406,8 @@ int clustrix_connection::discover_table_details(LEX_CSTRING *db,
{
DBUG_ENTER("clustrix_connection::discover_table_details");
int error_code = 0;
MYSQL_RES *results = NULL;
MYSQL_RES *results_oid = NULL;
MYSQL_RES *results_create = NULL;
MYSQL_ROW row;
String get_oid, show;
......@@ -411,6 +420,7 @@ int clustrix_connection::discover_table_details(LEX_CSTRING *db,
get_oid.append("' and r.name = '");
get_oid.append(name);
get_oid.append("'");
if (mysql_real_query(&clustrix_net, get_oid.c_ptr(), get_oid.length())) {
if ((error_code = mysql_errno(&clustrix_net))) {
DBUG_PRINT("mysql_real_query returns ", ("%d", error_code));
......@@ -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",
("rows: %llu, fields: %u", mysql_num_rows(results),
mysql_num_fields(results)));
("rows: %llu, fields: %u", mysql_num_rows(results_oid),
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;
goto error;
}
while((row = mysql_fetch_row(results))) {
while((row = mysql_fetch_row(results_oid))) {
DBUG_PRINT("row", ("%s", row[0]));
uchar *to = (uchar*)alloc_root(&share->mem_root, strlen(row[0]) + 1);
if (!to) {
......@@ -442,8 +452,6 @@ int clustrix_connection::discover_table_details(LEX_CSTRING *db,
share->tabledef_version.length = strlen(row[0]);
}
mysql_free_result(results);
/* get show create statement */
show.append("show create table ");
show.append(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",
("rows: %llu, fields: %u", mysql_num_rows(results),
mysql_num_fields(results)));
("rows: %llu, fields: %u", mysql_num_rows(results_create),
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;
goto error;
}
if (mysql_num_fields(results) != 2) {
if (mysql_num_fields(results_create) != 2) {
error_code = HA_ERR_CORRUPT_EVENT;
goto error;
}
while((row = mysql_fetch_row(results))) {
while((row = mysql_fetch_row(results_create))) {
DBUG_PRINT("row", ("%s - %s", row[0], row[1]));
error_code = share->init_from_sql_statement_string(thd, false, row[1],
strlen(row[1]));
}
error:
if (results)
mysql_free_result(results);
if (results_oid)
mysql_free_result(results_oid);
if (results_create)
mysql_free_result(results_create);
DBUG_RETURN(error_code);
}
......
......@@ -66,6 +66,7 @@ class clustrix_connection
int create_table(String &stmt);
int delete_table(String &stmt);
int rename_table(String &stmt);
int write_row(ulonglong clustrix_table_oid,
uchar *packed_row, size_t packed_size);
......
......@@ -148,7 +148,7 @@ int st_clustrixdb_trx::begin_trans()
/****************************************************************************
** 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 row_size = 0;
......@@ -161,6 +161,22 @@ size_t estimate_row_size(TABLE *table)
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
****************************************************************************/
......@@ -220,7 +236,7 @@ int ha_clustrixdb::create(const char *name, TABLE *form, HA_CREATE_INFO *info)
return error_code;
}
int ha_clustrixdb::delete_table(const char *name)
int ha_clustrixdb::delete_table(const char *path)
{
int error_code;
THD *thd = ha_thd();
......@@ -228,22 +244,63 @@ int ha_clustrixdb::delete_table(const char *name)
if (!trx)
return error_code;
// This block isn't UTF aware yet.
// The format contains './' in the beginning of a path.
char *dbname_end = (char*) name + 2;
char *dbname_end = (char*) path + 2;
while (*dbname_end != '/')
dbname_end++;
char decoded_tbname[FN_REFLEN];
decode_objectname(decoded_tbname, dbname_end + 1, FN_REFLEN);
String delete_cmd;
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(dbname_end + 1);
delete_cmd.append(decoded_tbname);
delete_cmd.append("`");
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)
{
DBUG_ENTER("ha_clustrixdb::open");
......
......@@ -63,6 +63,7 @@ class ha_clustrixdb : public handler
~ha_clustrixdb();
int create(const char *name, TABLE *form, HA_CREATE_INFO *info);
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 close(void);
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