Skip to content

Commit 95cca3d

Browse files
spetruniaGunnar Kudrjavets
authored andcommitted
Issue #17: Automatic per-index column families
Add support for INDEX idx(col1, ...) COMMENT '$per_index_cf'
1 parent 893d7fe commit 95cca3d

File tree

6 files changed

+178
-35
lines changed

6 files changed

+178
-35
lines changed

storage/rocksdb/ha_rocksdb.cc

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1207,13 +1207,16 @@ int ha_rocksdb::open(const char *name, int mode, uint test_if_locked)
12071207

12081208
uint key_len= table->key_info[table->s->primary_key].key_length;
12091209

1210-
const char *comment= table->key_info[table->s->primary_key].comment.str;
1210+
const char *comment= table->key_info[table->s->primary_key].comment.str;
1211+
const char *idx_name= table->key_info[table->s->primary_key].name;
12111212
rocksdb::ColumnFamilyHandle *cf_handle;
1212-
if (!(cf_handle= cf_manager.get_cf(comment)))
1213+
bool is_auto_cf;
1214+
if (!(cf_handle= cf_manager.get_cf(comment, fullname.c_ptr(), idx_name,
1215+
&is_auto_cf)))
12131216
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
12141217

12151218
pk_descr->setup(table); // move this into get_share() ??
1216-
pk_descr->set_cf_handle(cf_handle);
1219+
pk_descr->set_cf_handle(cf_handle, is_auto_cf);
12171220

12181221
uint packed_key_len= pk_descr->max_storage_fmt_length();
12191222

@@ -1229,11 +1232,13 @@ int ha_rocksdb::open(const char *name, int mode, uint test_if_locked)
12291232
continue;
12301233

12311234
comment= table->key_info[i].comment.str;
1232-
if (!(cf_handle= cf_manager.get_cf(comment)))
1235+
idx_name= table->key_info[i].name;
1236+
if (!(cf_handle= cf_manager.get_cf(comment, fullname.c_ptr(), idx_name,
1237+
&is_auto_cf)))
12331238
DBUG_RETURN(HA_ERR_INTERNAL_ERROR);
12341239

12351240
key_descr[i]->setup(table); // move this into get_share() ??
1236-
key_descr[i]->set_cf_handle(cf_handle);
1241+
key_descr[i]->set_cf_handle(cf_handle, is_auto_cf);
12371242

12381243
uint packed_len= key_descr[i]->max_storage_fmt_length();
12391244
if (packed_len > max_packed_sec_key_len)
@@ -1352,12 +1357,21 @@ int ha_rocksdb::create_key_defs(TABLE *table_arg, const char *db_table, uint len
13521357
NULL, and it means use the default column family.
13531358
*/
13541359
const char *comment= table_arg->key_info[i].comment.str;
1355-
cf_handle= cf_manager.get_or_create_cf(rdb, comment);
1360+
if (looks_like_per_index_cf_typo(comment))
1361+
{
1362+
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
1363+
"column family name looks like a typo of $per_index_cf");
1364+
goto error;
1365+
}
1366+
bool is_auto_cf;
1367+
cf_handle= cf_manager.get_or_create_cf(rdb, comment, db_table,
1368+
table_arg->key_info[i].name,
1369+
&is_auto_cf);
13561370
if (!cf_handle)
13571371
goto error;
13581372

13591373
if (!(key_descr[i]= new RDBSE_KEYDEF(ddl_manager.get_next_number(), i,
1360-
cf_handle)))
1374+
cf_handle, is_auto_cf)))
13611375
goto error;
13621376
}
13631377
pk_descr= key_descr[table_arg->s->primary_key];
@@ -2802,6 +2816,32 @@ int ha_rocksdb::rename_table(const char *from, const char *to)
28022816
if (rocksdb_normalize_tablename(to, &to_str))
28032817
return HA_ERR_INTERNAL_ERROR;
28042818

2819+
/* Check if any index has a per-index column family */
2820+
{
2821+
/*
2822+
We can't check this directly, because
2823+
1. the object that referred to the old table has been close()d.
2824+
2. this ha_rocksdb object has no connection to any table at all, it has
2825+
been just created with (TABLE*)NULL.
2826+
2827+
So, we have to find the old table in the ddl_manager (it's there because
2828+
it has been opened by this statement), and check is_auto_cf there.
2829+
*/
2830+
RDBSE_TABLE_DEF *tdef;
2831+
if (!(tdef= ddl_manager.find((uchar*)from_str.c_ptr(), from_str.length())))
2832+
return HA_ERR_INTERNAL_ERROR;
2833+
2834+
for (uint i= 0; i < tdef->n_keys; i++)
2835+
{
2836+
if (tdef->key_descr[i]->is_auto_cf)
2837+
{
2838+
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
2839+
"ALTER TABLE on table with per-index CF");
2840+
return HA_ERR_INTERNAL_ERROR;
2841+
}
2842+
}
2843+
}
2844+
28052845
if (ddl_manager.rename((uchar*)from_str.ptr(), from_str.length(),
28062846
(uchar*)to_str.ptr(), to_str.length(), rdb))
28072847
return HA_ERR_INTERNAL_ERROR;

storage/rocksdb/ha_rocksdb.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,27 @@
3333

3434
#include "rdb_applyiter.h"
3535

36+
37+
/*
38+
This is
39+
- the name of the default Column Family (the CF which stores indexes which didn't
40+
explicity specify which CF they are in)
41+
- the name used to set the default column family parameter for per-cf
42+
arguments.
43+
*/
3644
const char * const DEFAULT_CF_NAME= "default";
3745

46+
/*
47+
Column family name which means "put this index into its own column family".
48+
See get_per_index_cf_name.
49+
*/
50+
const char * const PER_INDEX_CF_NAME = "$per_index_cf";
51+
52+
inline bool looks_like_per_index_cf_typo(const char *name)
53+
{
54+
return (name && name[0]=='$' && strcmp(name, PER_INDEX_CF_NAME));
55+
}
56+
3857
//#ifdef HAVE_PSI_INTERFACE
3958
extern PSI_stage_info stage_waiting_on_row_lock;
4059

storage/rocksdb/rdb_cf_manager.cc

Lines changed: 86 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -49,55 +49,119 @@ void Column_family_manager::cleanup()
4949
}
5050

5151

52+
/*
53+
Generate Column Family name for per-index column families
54+
55+
@param res OUT Column Family name
56+
*/
57+
58+
void get_per_index_cf_name(const char *db_table_name, const char *index_name,
59+
std::string *res)
60+
{
61+
res->assign(db_table_name);
62+
res->append(".");
63+
res->append(index_name);
64+
}
65+
66+
67+
/*
68+
@brief
69+
Find column family by name. If it doesn't exist, create it
70+
71+
@detail
72+
See Column_family_manager::get_cf
73+
*/
5274
rocksdb::ColumnFamilyHandle*
53-
Column_family_manager::get_or_create_cf(rocksdb::DB *rdb, const char *name)
75+
Column_family_manager::get_or_create_cf(rocksdb::DB *rdb, const char *cf_name,
76+
const char *db_table_name,
77+
const char *index_name,
78+
bool *is_automatic)
5479
{
5580
rocksdb::ColumnFamilyHandle* cf_handle;
5681
ColumnFamilyHandleMap::iterator it;
5782

5883
mysql_mutex_lock(&cfm_mutex);
59-
if (name == NULL)
84+
*is_automatic= false;
85+
if (cf_name == NULL)
6086
{
6187
cf_handle= default_cf;
6288
}
63-
else if ((it= cf_map.find(name)) != cf_map.end())
64-
cf_handle= it->second;
6589
else
6690
{
67-
/* Create a Column Family. */
68-
std::string cf_name(name);
69-
rocksdb::ColumnFamilyOptions opts;
70-
get_cf_options(cf_name, &opts);
71-
72-
sql_print_information("RocksDB: creating column family %s", cf_name.c_str());
73-
sql_print_information(" write_buffer_size=%ld", opts.write_buffer_size);
74-
sql_print_information(" target_file_size_base=%d", opts.target_file_size_base);
75-
76-
rocksdb::Status s= rdb->CreateColumnFamily(opts, name, &cf_handle);
77-
if (s.ok())
78-
cf_map[cf_name]= cf_handle;
91+
std::string per_index_name;
92+
if (!strcmp(cf_name, PER_INDEX_CF_NAME))
93+
{
94+
get_per_index_cf_name(db_table_name, index_name, &per_index_name);
95+
cf_name= per_index_name.c_str();
96+
*is_automatic= true;
97+
}
98+
99+
if ((it= cf_map.find(cf_name)) != cf_map.end())
100+
cf_handle= it->second;
79101
else
80-
cf_handle= NULL;
102+
{
103+
/* Create a Column Family. */
104+
std::string cf_name_str(cf_name);
105+
rocksdb::ColumnFamilyOptions opts;
106+
get_cf_options(cf_name_str, &opts);
107+
108+
sql_print_information("RocksDB: creating column family %s", cf_name_str.c_str());
109+
sql_print_information(" write_buffer_size=%ld", opts.write_buffer_size);
110+
sql_print_information(" target_file_size_base=%d", opts.target_file_size_base);
111+
112+
rocksdb::Status s= rdb->CreateColumnFamily(opts, cf_name_str, &cf_handle);
113+
if (s.ok())
114+
cf_map[cf_name_str]= cf_handle;
115+
else
116+
cf_handle= NULL;
117+
}
81118
}
82119
mysql_mutex_unlock(&cfm_mutex);
83120

84121
return cf_handle;
85122
}
86123

87124

125+
/*
126+
Find column family by its cf_name.
127+
128+
@detail
129+
dbname.tablename and index_name are also parameters, because
130+
cf_name=PER_INDEX_CF_NAME means that column family name is a function
131+
of table/index name.
132+
133+
@param out is_automatic TRUE<=> column family name is auto-assigned based on
134+
db_table_name and index_name.
135+
*/
136+
88137
rocksdb::ColumnFamilyHandle*
89-
Column_family_manager::get_cf(const char *name)
138+
Column_family_manager::get_cf(const char *cf_name,
139+
const char *db_table_name,
140+
const char *index_name,
141+
bool *is_automatic)
90142
{
91143
rocksdb::ColumnFamilyHandle* cf_handle;
92144
ColumnFamilyHandleMap::iterator it;
93145

146+
*is_automatic= false;
94147
mysql_mutex_lock(&cfm_mutex);
95-
if (name == NULL)
148+
if (cf_name == NULL)
96149
cf_handle= default_cf;
97-
else if ((it= cf_map.find(name)) != cf_map.end())
98-
cf_handle= it->second;
99150
else
100-
cf_handle= NULL;
151+
{
152+
std::string per_index_name;
153+
if (!strcmp(cf_name, PER_INDEX_CF_NAME))
154+
{
155+
get_per_index_cf_name(db_table_name, index_name, &per_index_name);
156+
cf_name= per_index_name.c_str();
157+
*is_automatic= true;
158+
}
159+
160+
if ((it= cf_map.find(cf_name)) != cf_map.end())
161+
cf_handle= it->second;
162+
else
163+
cf_handle= NULL;
164+
}
101165
mysql_mutex_unlock(&cfm_mutex);
102166

103167
return cf_handle;

storage/rocksdb/rdb_cf_manager.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@
2222
*/
2323
void get_cf_options(const std::string &cf_name, rocksdb::ColumnFamilyOptions *opts);
2424

25+
void get_per_index_cf_name(const char *db_table_name, const char *index_name,
26+
std::string *res);
27+
2528
/*
2629
We need a column family manager. Its functions:
2730
- create column families (synchronized, don't create the same twice)
@@ -54,12 +57,22 @@ class Column_family_manager
5457
std::vector<rocksdb::ColumnFamilyHandle*> *handles);
5558
void cleanup();
5659

57-
/* Used by CREATE TABLE. name=NULL means use default column family */
60+
/*
61+
Used by CREATE TABLE.
62+
- cf_name=NULL means use default column family
63+
- cf_name=_auto_ means use 'dbname.tablename.indexname'
64+
*/
5865
rocksdb::ColumnFamilyHandle* get_or_create_cf(rocksdb::DB *rdb,
59-
const char *name);
66+
const char *cf_name,
67+
const char *db_table_name,
68+
const char *index_name,
69+
bool *is_automatic);
6070

6171
/* Used by table open */
62-
rocksdb::ColumnFamilyHandle* get_cf(const char *name);
72+
rocksdb::ColumnFamilyHandle* get_cf(const char *cf_name,
73+
const char *db_table_name,
74+
const char *index_name,
75+
bool *is_automatic);
6376

6477
// void drop_cf(); -- not implemented so far.
6578
};

storage/rocksdb/rdb_datadic.cc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -949,7 +949,8 @@ bool Table_ddl_manager::init(rocksdb::DB *rdb_dict)
949949
initialization requires that there is an open TABLE* where we could
950950
look at Field* objects and set max_length and other attributes
951951
*/
952-
tdef->key_descr[keyno]= new RDBSE_KEYDEF(index_number, keyno, NULL);
952+
tdef->key_descr[keyno]= new RDBSE_KEYDEF(index_number, keyno, NULL,
953+
false);
953954

954955
/* Keep track of what was the last index number we saw */
955956
if (max_number < index_number)

storage/rocksdb/rdb_datadic.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,10 @@ class RDBSE_KEYDEF
189189
}
190190

191191
RDBSE_KEYDEF(uint indexnr_arg, uint keyno_arg,
192-
rocksdb::ColumnFamilyHandle* cf_handle_arg) :
192+
rocksdb::ColumnFamilyHandle* cf_handle_arg, bool is_auto_cf_arg) :
193193
index_number(indexnr_arg),
194194
cf_handle(cf_handle_arg),
195+
is_auto_cf(is_auto_cf_arg),
195196
pk_part_no(NULL),
196197
pack_info(NULL),
197198
keyno(keyno_arg),
@@ -208,9 +209,11 @@ class RDBSE_KEYDEF
208209
};
209210

210211
void setup(TABLE *table);
211-
void set_cf_handle(rocksdb::ColumnFamilyHandle* cf_handle_arg)
212+
void set_cf_handle(rocksdb::ColumnFamilyHandle* cf_handle_arg,
213+
bool is_auto_cf_arg)
212214
{
213215
cf_handle= cf_handle_arg;
216+
is_auto_cf= is_auto_cf_arg;
214217
}
215218

216219
rocksdb::ColumnFamilyHandle *get_cf() { return cf_handle; }
@@ -223,6 +226,9 @@ class RDBSE_KEYDEF
223226
uchar index_number_storage_form[INDEX_NUMBER_SIZE];
224227

225228
rocksdb::ColumnFamilyHandle* cf_handle;
229+
public:
230+
bool is_auto_cf;
231+
private:
226232

227233
friend class RDBSE_TABLE_DEF; // for index_number above
228234

0 commit comments

Comments
 (0)