MDEV-506 Cassandra dynamic columns access
This commit is contained in:
parent
7327cd9717
commit
245298f25d
@ -39,6 +39,12 @@
|
||||
*/
|
||||
#define MAX_DYNAMIC_COLUMN_LENGTH 0X1FFFFFFFL
|
||||
|
||||
/*
|
||||
Limits of implementation
|
||||
*/
|
||||
#define MAX_NAME_LENGTH 255
|
||||
#define MAX_TOTAL_NAME_LENGTH 65535
|
||||
|
||||
/* NO and OK is the same used just to show semantics */
|
||||
#define ER_DYNCOL_NO ER_DYNCOL_OK
|
||||
|
||||
@ -50,7 +56,8 @@ enum enum_dyncol_func_result
|
||||
ER_DYNCOL_LIMIT= -2, /* Some limit reached */
|
||||
ER_DYNCOL_RESOURCE= -3, /* Out of resourses */
|
||||
ER_DYNCOL_DATA= -4, /* Incorrect input data */
|
||||
ER_DYNCOL_UNKNOWN_CHARSET= -5 /* Unknown character set */
|
||||
ER_DYNCOL_UNKNOWN_CHARSET= -5, /* Unknown character set */
|
||||
ER_DYNCOL_TRUNCATED= 2 /* OK, but data was truncated */
|
||||
};
|
||||
|
||||
typedef DYNAMIC_STRING DYNAMIC_COLUMN;
|
||||
@ -81,6 +88,7 @@ struct st_dynamic_column_value
|
||||
struct {
|
||||
LEX_STRING value;
|
||||
CHARSET_INFO *charset;
|
||||
my_bool nonfreeable;
|
||||
} string;
|
||||
struct {
|
||||
decimal_digit_t buffer[DECIMAL_BUFF_LENGTH];
|
||||
@ -108,6 +116,13 @@ dynamic_column_create_many_fmt(DYNAMIC_COLUMN *str,
|
||||
uchar *column_keys,
|
||||
DYNAMIC_COLUMN_VALUE *values,
|
||||
my_bool names);
|
||||
enum enum_dyncol_func_result
|
||||
dynamic_column_create_many_internal_fmt(DYNAMIC_COLUMN *str,
|
||||
uint column_count,
|
||||
void *column_keys,
|
||||
DYNAMIC_COLUMN_VALUE *values,
|
||||
my_bool new_str,
|
||||
my_bool string_keys);
|
||||
|
||||
enum enum_dyncol_func_result
|
||||
dynamic_column_update(DYNAMIC_COLUMN *org, uint column_nr,
|
||||
@ -163,6 +178,21 @@ dynamic_column_json(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json);
|
||||
#define dynamic_column_initialize(A) memset((A), 0, sizeof(*(A)))
|
||||
#define dynamic_column_column_free(V) dynstr_free(V)
|
||||
|
||||
/* conversion of values to 3 base types */
|
||||
enum enum_dyncol_func_result
|
||||
dynamic_column_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val,
|
||||
CHARSET_INFO *cs, my_bool quote);
|
||||
enum enum_dyncol_func_result
|
||||
dynamic_column_val_long(longlong *ll, DYNAMIC_COLUMN_VALUE *val);
|
||||
enum enum_dyncol_func_result
|
||||
dynamic_column_val_double(double *dbl, DYNAMIC_COLUMN_VALUE *val);
|
||||
|
||||
|
||||
enum enum_dyncol_func_result
|
||||
dynamic_column_vals(DYNAMIC_COLUMN *str,
|
||||
DYNAMIC_ARRAY *names, DYNAMIC_ARRAY *vals,
|
||||
char **free_names);
|
||||
|
||||
/***************************************************************************
|
||||
Internal functions, don't use if you don't know what you are doing...
|
||||
***************************************************************************/
|
||||
|
@ -365,8 +365,9 @@ CREATE TABLE t2 (rowkey bigint PRIMARY KEY, datecol bigint) ENGINE=CASSANDRA
|
||||
thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf4';
|
||||
select * from t2;
|
||||
rowkey datecol
|
||||
1 1346189025000
|
||||
10 1346189026000
|
||||
1 1346192625000
|
||||
10 1346192626000
|
||||
delete from t2;
|
||||
drop table t2;
|
||||
#
|
||||
# Check whether changing parameters with ALTER TABLE works.
|
||||
@ -407,3 +408,141 @@ new-rowkey12 data1-value3 454
|
||||
rowkey11 updated-1 34543
|
||||
delete from t1;
|
||||
drop table t1;
|
||||
#
|
||||
# Dynamic columns support
|
||||
#
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol blob DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
drop table t2;
|
||||
#error: dynamic column is not a blob
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol char(36) DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
ERROR 42000: Incorrect column specifier for column 'uuidcol'
|
||||
#error: double dynamic column
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol blob DYNAMIC_COLUMN_STORAGE=1, textcol blob DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
ERROR 42000: Incorrect column specifier for column 'textcol'
|
||||
#
|
||||
# Dynamic column read
|
||||
#
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol char(36)) ENGINE=CASSANDRA
|
||||
thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
delete from t2;
|
||||
insert into t2 values(1,'9b5658dc-f32f-11e1-94cd-f46d046e9f09');
|
||||
insert into t2 values(2,'9b5658dc-f32f-11e1-94cd-f46d046e9f0a');
|
||||
drop table t2;
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
select rowkey, column_list(dyn), column_get(dyn, 'uuidcol' as char) from t2;
|
||||
rowkey column_list(dyn) column_get(dyn, 'uuidcol' as char)
|
||||
1 `uuidcol` 9b5658dc-f32f-11e1-94cd-f46d046e9f09
|
||||
2 `uuidcol` 9b5658dc-f32f-11e1-94cd-f46d046e9f0a
|
||||
drop table t2;
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol char(36)) ENGINE=CASSANDRA
|
||||
thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
delete from t2;
|
||||
drop table t2;
|
||||
#
|
||||
# Dynamic column insert
|
||||
#
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
insert into t2 values (1, column_create("dyn1", 1, "dyn2", "two"));
|
||||
select rowkey, column_json(dyn) from t2;
|
||||
rowkey column_json(dyn)
|
||||
1 [{"dyn1":"1"},{"dyn2":"two"}]
|
||||
delete from t2;
|
||||
drop table t2;
|
||||
# bigint
|
||||
CREATE TABLE t1 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf2';
|
||||
insert into t1 values (1, column_create("dyn1", 1, "dyn2", "two", 'a', 254324));
|
||||
insert into t1 values (2, column_create("dyn1", 1, "dyn2", "two", 'a', 2543));
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
rowkey column_json(dyn)
|
||||
1 [{"a":254324},{"dyn1":"1"},{"dyn2":"two"}]
|
||||
2 [{"a":2543},{"dyn1":"1"},{"dyn2":"two"}]
|
||||
delete from t1;
|
||||
drop table t1;
|
||||
# int
|
||||
CREATE TABLE t1 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf3';
|
||||
insert into t1 values (1, column_create("dyn1", 1, "dyn2", "two", 'intcol', 254324));
|
||||
insert into t1 values (2, column_create("dyn1", 1, "dyn2", "two", 'intcol', 2543));
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
rowkey column_json(dyn)
|
||||
1 [{"dyn1":"1"},{"dyn2":"two"},{"intcol":254324}]
|
||||
2 [{"dyn1":"1"},{"dyn2":"two"},{"intcol":2543}]
|
||||
delete from t1;
|
||||
drop table t1;
|
||||
# timestamp
|
||||
CREATE TABLE t1 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf4';
|
||||
insert into t1 values (1, column_create("dyn1", 1, "dyn2", "two", 'datecol', 254324));
|
||||
insert into t1 values (2, column_create("dyn1", 1, "dyn2", "two", 'datecol', 2543));
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
rowkey column_json(dyn)
|
||||
1 [{"dyn1":"1"},{"dyn2":"two"},{"datecol":254324}]
|
||||
2 [{"dyn1":"1"},{"dyn2":"two"},{"datecol":2543}]
|
||||
delete from t1;
|
||||
drop table t1;
|
||||
# boolean
|
||||
CREATE TABLE t1 (rowkey int PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf7';
|
||||
insert into t1 values (1, column_create("dyn1", 1, "dyn2", "two", 'boolcol', 254324));
|
||||
insert into t1 values (2, column_create("dyn1", 1, "dyn2", "two", 'boolcol', 0));
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
rowkey column_json(dyn)
|
||||
1 [{"dyn1":"1"},{"dyn2":"two"},{"boolcol":1}]
|
||||
2 [{"dyn1":"1"},{"dyn2":"two"},{"boolcol":0}]
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
rowkey column_json(dyn)
|
||||
1 [{"dyn1":"1"},{"dyn2":"two"},{"boolcol":1}]
|
||||
2 [{"dyn1":"1"},{"dyn2":"two"},{"boolcol":0}]
|
||||
update t1 set dyn=column_add(dyn, "dyn2", null, "dyn3", "3");
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
rowkey column_json(dyn)
|
||||
1 [{"dyn1":"1"},{"dyn3":"3"},{"boolcol":1}]
|
||||
2 [{"dyn1":"1"},{"dyn3":"3"},{"boolcol":0}]
|
||||
update t1 set dyn=column_add(dyn, "dyn1", null) where rowkey= 1;
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
rowkey column_json(dyn)
|
||||
1 [{"dyn3":"3"},{"boolcol":1}]
|
||||
2 [{"dyn1":"1"},{"dyn3":"3"},{"boolcol":0}]
|
||||
update t1 set dyn=column_add(dyn, "dyn3", null, "a", "ddd");
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
rowkey column_json(dyn)
|
||||
1 [{"a":"ddd"},{"boolcol":1}]
|
||||
2 [{"a":"ddd"},{"dyn1":"1"},{"boolcol":0}]
|
||||
update t1 set dyn=column_add(dyn, "12345678901234", "ddd");
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
rowkey column_json(dyn)
|
||||
1 [{"a":"ddd"},{"boolcol":1},{"12345678901234":"ddd"}]
|
||||
2 [{"a":"ddd"},{"dyn1":"1"},{"boolcol":0},{"12345678901234":"ddd"}]
|
||||
update t1 set dyn=column_add(dyn, "12345678901234", null);
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
rowkey column_json(dyn)
|
||||
1 [{"a":"ddd"},{"boolcol":1}]
|
||||
2 [{"a":"ddd"},{"dyn1":"1"},{"boolcol":0}]
|
||||
update t1 set dyn=column_add(dyn, 'boolcol', null) where rowkey= 2;
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
rowkey column_json(dyn)
|
||||
1 [{"a":"ddd"},{"boolcol":1}]
|
||||
2 [{"a":"ddd"},{"dyn1":"1"}]
|
||||
update t1 set rowkey= 3, dyn=column_add(dyn, "dyn1", null, 'boolcol', 0) where rowkey= 2;
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
rowkey column_json(dyn)
|
||||
1 [{"a":"ddd"},{"boolcol":1}]
|
||||
3 [{"a":"ddd"},{"boolcol":0}]
|
||||
delete from t1;
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (rowkey varchar(10) PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cfd1';
|
||||
select * from t1;
|
||||
ERROR HY000: Internal error: 'Unable to convert value for field `dyn` from Cassandra's data format. Name length exceed limit of 255: 'very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_ver'
|
||||
drop table t1;
|
||||
CREATE TABLE t1 (rowkey int PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes)
|
||||
ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cfd2';
|
||||
DELETE FROM t1;
|
||||
insert into t1 values (1, column_create("dyn", 1));
|
||||
select rowkey, column_list(dyn) from t1;
|
||||
rowkey column_list(dyn)
|
||||
1 `dyn`
|
||||
delete from t1;
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE t1 (rowkey int PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes)
|
||||
ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cfd2';
|
||||
insert into t1 values (1,'9b5658dc-f32f-11e1-94cd-f46d046e9f0a');
|
||||
ERROR HY000: Encountered illegal format of dynamic column string
|
||||
delete from t1;
|
||||
DROP TABLE t1;
|
||||
|
@ -89,6 +89,24 @@ The following options may be given as the first argument:
|
||||
--bulk-insert-buffer-size=#
|
||||
Size of tree cache used in bulk insert optimisation. Note
|
||||
that this is a limit per thread!
|
||||
--cassandra[=name] Enable or disable CASSANDRA plugin. Possible values are
|
||||
ON, OFF, FORCE (don't start if the plugin fails to load).
|
||||
--cassandra-default-thrift-host=name
|
||||
Default host for Cassandra thrift connections
|
||||
--cassandra-failure-retries=#
|
||||
Number of times to retry Cassandra calls that failed due
|
||||
to timeouts or network communication problems. The
|
||||
default, 0, means not to retry.
|
||||
--cassandra-insert-batch-size=#
|
||||
Number of rows in an INSERT batch
|
||||
--cassandra-multiget-batch-size=#
|
||||
Number of rows in a multiget(MRR) batch
|
||||
--cassandra-read-consistency=name
|
||||
Cassandra consistency level to use for read operations
|
||||
--cassandra-rnd-batch-size=#
|
||||
Number of rows in an rnd_read (full scan) batch
|
||||
--cassandra-write-consistency=name
|
||||
Cassandra consistency level to use for write operations
|
||||
--character-set-client-handshake
|
||||
Don't ignore client side character set value sent during
|
||||
handshake.
|
||||
@ -863,6 +881,14 @@ binlog-optimize-thread-scheduling TRUE
|
||||
binlog-row-event-max-size 1024
|
||||
binlog-stmt-cache-size 32768
|
||||
bulk-insert-buffer-size 8388608
|
||||
cassandra ON
|
||||
cassandra-default-thrift-host (No default value)
|
||||
cassandra-failure-retries 0
|
||||
cassandra-insert-batch-size 100
|
||||
cassandra-multiget-batch-size 100
|
||||
cassandra-read-consistency ONE
|
||||
cassandra-rnd-batch-size 10000
|
||||
cassandra-write-consistency ONE
|
||||
character-set-client-handshake TRUE
|
||||
character-set-filesystem binary
|
||||
character-set-server latin1
|
||||
|
@ -94,6 +94,18 @@ CREATE COLUMN FAMILY cf10
|
||||
WITH comparator = UTF8Type
|
||||
AND key_validation_class=UTF8Type
|
||||
AND default_validation_class = UTF8Type;
|
||||
|
||||
CREATE COLUMN FAMILY cfd1
|
||||
WITH comparator = UTF8Type
|
||||
AND key_validation_class=UTF8Type
|
||||
AND default_validation_class = UTF8Type;
|
||||
SET cfd1['1']['very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_very_long_name']='1';
|
||||
|
||||
CREATE COLUMN FAMILY cfd2
|
||||
WITH comparator = UTF8Type
|
||||
AND key_validation_class=Int32Type
|
||||
AND default_validation_class = UTF8Type;
|
||||
|
||||
EOF
|
||||
|
||||
--error 0,1,2
|
||||
@ -463,7 +475,7 @@ drop table t2;
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, datecol bigint) ENGINE=CASSANDRA
|
||||
thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf4';
|
||||
select * from t2;
|
||||
|
||||
delete from t2;
|
||||
drop table t2;
|
||||
|
||||
--echo #
|
||||
@ -511,6 +523,118 @@ select * from t1;
|
||||
delete from t1;
|
||||
drop table t1;
|
||||
|
||||
--echo #
|
||||
--echo # Dynamic columns support
|
||||
--echo #
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol blob DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
drop table t2;
|
||||
|
||||
--echo #error: dynamic column is not a blob
|
||||
--error ER_WRONG_FIELD_SPEC
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol char(36) DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
|
||||
--echo #error: double dynamic column
|
||||
--error ER_WRONG_FIELD_SPEC
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol blob DYNAMIC_COLUMN_STORAGE=1, textcol blob DYNAMIC_COLUMN_STORAGE=1) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
|
||||
--echo #
|
||||
--echo # Dynamic column read
|
||||
--echo #
|
||||
#prepare data
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol char(36)) ENGINE=CASSANDRA
|
||||
thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
delete from t2;
|
||||
insert into t2 values(1,'9b5658dc-f32f-11e1-94cd-f46d046e9f09');
|
||||
insert into t2 values(2,'9b5658dc-f32f-11e1-94cd-f46d046e9f0a');
|
||||
drop table t2;
|
||||
|
||||
#test dynamic column read
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
select rowkey, column_list(dyn), column_get(dyn, 'uuidcol' as char) from t2;
|
||||
drop table t2;
|
||||
|
||||
#cleanup data
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, uuidcol char(36)) ENGINE=CASSANDRA
|
||||
thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
delete from t2;
|
||||
drop table t2;
|
||||
|
||||
--echo #
|
||||
--echo # Dynamic column insert
|
||||
--echo #
|
||||
CREATE TABLE t2 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf5';
|
||||
insert into t2 values (1, column_create("dyn1", 1, "dyn2", "two"));
|
||||
select rowkey, column_json(dyn) from t2;
|
||||
delete from t2;
|
||||
drop table t2;
|
||||
--echo # bigint
|
||||
CREATE TABLE t1 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf2';
|
||||
insert into t1 values (1, column_create("dyn1", 1, "dyn2", "two", 'a', 254324));
|
||||
insert into t1 values (2, column_create("dyn1", 1, "dyn2", "two", 'a', 2543));
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
delete from t1;
|
||||
drop table t1;
|
||||
--echo # int
|
||||
CREATE TABLE t1 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf3';
|
||||
insert into t1 values (1, column_create("dyn1", 1, "dyn2", "two", 'intcol', 254324));
|
||||
insert into t1 values (2, column_create("dyn1", 1, "dyn2", "two", 'intcol', 2543));
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
delete from t1;
|
||||
drop table t1;
|
||||
--echo # timestamp
|
||||
CREATE TABLE t1 (rowkey bigint PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf4';
|
||||
insert into t1 values (1, column_create("dyn1", 1, "dyn2", "two", 'datecol', 254324));
|
||||
insert into t1 values (2, column_create("dyn1", 1, "dyn2", "two", 'datecol', 2543));
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
delete from t1;
|
||||
drop table t1;
|
||||
--echo # boolean
|
||||
CREATE TABLE t1 (rowkey int PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cf7';
|
||||
insert into t1 values (1, column_create("dyn1", 1, "dyn2", "two", 'boolcol', 254324));
|
||||
insert into t1 values (2, column_create("dyn1", 1, "dyn2", "two", 'boolcol', 0));
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
update t1 set dyn=column_add(dyn, "dyn2", null, "dyn3", "3");
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
update t1 set dyn=column_add(dyn, "dyn1", null) where rowkey= 1;
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
update t1 set dyn=column_add(dyn, "dyn3", null, "a", "ddd");
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
update t1 set dyn=column_add(dyn, "12345678901234", "ddd");
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
update t1 set dyn=column_add(dyn, "12345678901234", null);
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
update t1 set dyn=column_add(dyn, 'boolcol', null) where rowkey= 2;
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
update t1 set rowkey= 3, dyn=column_add(dyn, "dyn1", null, 'boolcol', 0) where rowkey= 2;
|
||||
select rowkey, column_json(dyn) from t1;
|
||||
delete from t1;
|
||||
drop table t1;
|
||||
|
||||
CREATE TABLE t1 (rowkey varchar(10) PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes) ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cfd1';
|
||||
--error ER_INTERNAL_ERROR
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
# MDEV-560
|
||||
CREATE TABLE t1 (rowkey int PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes)
|
||||
ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cfd2';
|
||||
DELETE FROM t1;
|
||||
insert into t1 values (1, column_create("dyn", 1));
|
||||
select rowkey, column_list(dyn) from t1;
|
||||
# Cleanup
|
||||
delete from t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
# MDEV-561 (incorrect format data to dynamic column)
|
||||
CREATE TABLE t1 (rowkey int PRIMARY KEY, dyn blob DYNAMIC_COLUMN_STORAGE=yes)
|
||||
ENGINE=CASSANDRA thrift_host='localhost' keyspace='mariadbtest2' column_family = 'cfd2';
|
||||
--error ER_DYN_COL_WRONG_FORMAT
|
||||
insert into t1 values (1,'9b5658dc-f32f-11e1-94cd-f46d046e9f0a');
|
||||
delete from t1;
|
||||
DROP TABLE t1;
|
||||
|
||||
|
||||
############################################################################
|
||||
## Cassandra cleanup
|
||||
############################################################################
|
||||
|
@ -68,6 +68,8 @@ uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
|
||||
|
||||
#define MAX_OFFSET_LENGTH 5
|
||||
|
||||
#define DYNCOL_NUM_CHAR 6
|
||||
|
||||
my_bool dynamic_column_has_names(DYNAMIC_COLUMN *str)
|
||||
{
|
||||
if (str->length < 1)
|
||||
@ -211,7 +213,7 @@ static my_bool check_limit_num(const void *val)
|
||||
|
||||
static my_bool check_limit_str(const void *val)
|
||||
{
|
||||
return (*((LEX_STRING **)val))->length > 255;
|
||||
return (*((LEX_STRING **)val))->length > MAX_NAME_LENGTH;
|
||||
}
|
||||
|
||||
|
||||
@ -288,7 +290,7 @@ my_bool put_header_entry_str(DYN_HEADER *hdr,
|
||||
size_t offset)
|
||||
{
|
||||
LEX_STRING *column_name= (LEX_STRING *)column_key;
|
||||
DBUG_ASSERT(column_name->length <= 255);
|
||||
DBUG_ASSERT(column_name->length <= MAX_NAME_LENGTH);
|
||||
hdr->entry[0]= column_name->length;
|
||||
DBUG_ASSERT(hdr->name - hdr->nmpool < (long) 0x10000L);
|
||||
int2store(hdr->entry + 1, hdr->name - hdr->nmpool);
|
||||
@ -1381,6 +1383,9 @@ dynamic_new_column_store(DYNAMIC_COLUMN *str,
|
||||
DYNCOL_SYZERESERVE))
|
||||
goto err;
|
||||
}
|
||||
if (!column_count)
|
||||
return ER_DYNCOL_OK;
|
||||
|
||||
bzero(str->str, fmt->fixed_hdr);
|
||||
str->length= fmt->fixed_hdr;
|
||||
|
||||
@ -1501,7 +1506,7 @@ calc_var_sizes(DYN_HEADER *hdr,
|
||||
@return ER_DYNCOL_* return code
|
||||
*/
|
||||
|
||||
static enum enum_dyncol_func_result
|
||||
enum enum_dyncol_func_result
|
||||
dynamic_column_create_many_internal_fmt(DYNAMIC_COLUMN *str,
|
||||
uint column_count,
|
||||
void *column_keys,
|
||||
@ -1761,7 +1766,7 @@ static my_bool
|
||||
find_column(DYN_HEADER *hdr, uint numkey, LEX_STRING *strkey)
|
||||
{
|
||||
LEX_STRING nmkey;
|
||||
char nmkeybuff[6]; /* to fit max 2 bytes number */
|
||||
char nmkeybuff[DYNCOL_NUM_CHAR]; /* to fit max 2 bytes number */
|
||||
DBUG_ASSERT(hdr->header != NULL);
|
||||
|
||||
if (hdr->header + hdr->header_size > hdr->data_end)
|
||||
@ -2169,10 +2174,10 @@ dynamic_column_list_str(DYNAMIC_COLUMN *str, DYNAMIC_ARRAY *array_of_lexstr)
|
||||
if (header.format == DYNCOL_FMT_NUM)
|
||||
{
|
||||
uint nm= uint2korr(read);
|
||||
tmp.str= my_malloc(6, MYF(0));
|
||||
tmp.str= my_malloc(DYNCOL_NUM_CHAR, MYF(0));
|
||||
if (!tmp.str)
|
||||
return ER_DYNCOL_RESOURCE;
|
||||
tmp.length= snprintf(tmp.str, 6, "%u", nm);
|
||||
tmp.length= snprintf(tmp.str, DYNCOL_NUM_CHAR, "%u", nm);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2208,7 +2213,7 @@ find_place(DYN_HEADER *hdr, void *key, my_bool string_keys)
|
||||
uint mid, start, end, val;
|
||||
int flag;
|
||||
LEX_STRING str;
|
||||
char buff[6];
|
||||
char buff[DYNCOL_NUM_CHAR];
|
||||
my_bool need_conversion= ((string_keys ? DYNCOL_FMT_STR : DYNCOL_FMT_NUM) !=
|
||||
hdr->format);
|
||||
LINT_INIT(flag); /* 100 % safe */
|
||||
@ -2425,7 +2430,7 @@ dynamic_column_update_copy(DYNAMIC_COLUMN *str, PLAN *plan,
|
||||
size_t offs;
|
||||
uint nm;
|
||||
DYNAMIC_COLUMN_TYPE tp;
|
||||
char buff[6];
|
||||
char buff[DYNCOL_NUM_CHAR];
|
||||
|
||||
if (hdr->format == DYNCOL_FMT_NUM)
|
||||
{
|
||||
@ -3438,7 +3443,7 @@ end:
|
||||
|
||||
enum enum_dyncol_func_result
|
||||
dynamic_column_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val,
|
||||
my_bool quote)
|
||||
CHARSET_INFO *cs, my_bool quote)
|
||||
{
|
||||
char buff[40];
|
||||
int len;
|
||||
@ -3468,24 +3473,22 @@ dynamic_column_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val,
|
||||
char *alloc= NULL;
|
||||
char *from= val->x.string.value.str;
|
||||
uint bufflen;
|
||||
my_bool conv= !my_charset_same(val->x.string.charset,
|
||||
&my_charset_utf8_general_ci);
|
||||
my_bool conv= !my_charset_same(val->x.string.charset, cs);
|
||||
my_bool rc;
|
||||
len= val->x.string.value.length;
|
||||
bufflen= (len * (conv ? my_charset_utf8_general_ci.mbmaxlen : 1));
|
||||
bufflen= (len * (conv ? cs->mbmaxlen : 1));
|
||||
if (dynstr_realloc(str, bufflen))
|
||||
return ER_DYNCOL_RESOURCE;
|
||||
|
||||
// guaranty UTF-8 string for value
|
||||
if (!my_charset_same(val->x.string.charset,
|
||||
&my_charset_utf8_general_ci))
|
||||
if (!my_charset_same(val->x.string.charset, cs))
|
||||
{
|
||||
uint dummy_errors;
|
||||
if (!quote)
|
||||
{
|
||||
/* convert to the destination */
|
||||
str->length+= copy_and_convert_extended(str->str, bufflen,
|
||||
&my_charset_utf8_general_ci,
|
||||
cs,
|
||||
from, len,
|
||||
val->x.string.charset,
|
||||
&dummy_errors);
|
||||
@ -3494,8 +3497,7 @@ dynamic_column_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val,
|
||||
if ((alloc= (char *)my_malloc(bufflen, MYF(0))))
|
||||
{
|
||||
len=
|
||||
copy_and_convert_extended(alloc, bufflen,
|
||||
&my_charset_utf8_general_ci,
|
||||
copy_and_convert_extended(alloc, bufflen, cs,
|
||||
from, len, val->x.string.charset,
|
||||
&dummy_errors);
|
||||
from= alloc;
|
||||
@ -3543,6 +3545,155 @@ dynamic_column_val_str(DYNAMIC_STRING *str, DYNAMIC_COLUMN_VALUE *val,
|
||||
return(ER_DYNCOL_OK);
|
||||
}
|
||||
|
||||
|
||||
enum enum_dyncol_func_result
|
||||
dynamic_column_val_long(longlong *ll, DYNAMIC_COLUMN_VALUE *val)
|
||||
{
|
||||
enum enum_dyncol_func_result rc= ER_DYNCOL_OK;
|
||||
*ll= 0;
|
||||
switch (val->type) {
|
||||
case DYN_COL_INT:
|
||||
*ll= val->x.long_value;
|
||||
break;
|
||||
case DYN_COL_UINT:
|
||||
*ll= (longlong)val->x.ulong_value;
|
||||
if (val->x.ulong_value > ULONGLONG_MAX)
|
||||
rc= ER_DYNCOL_TRUNCATED;
|
||||
break;
|
||||
case DYN_COL_DOUBLE:
|
||||
*ll= (longlong)val->x.double_value;
|
||||
if (((double) *ll) != val->x.double_value)
|
||||
rc= ER_DYNCOL_TRUNCATED;
|
||||
break;
|
||||
case DYN_COL_STRING:
|
||||
{
|
||||
longlong i= 0, sign= 1;
|
||||
char *src= val->x.string.value.str;
|
||||
uint len= val->x.string.value.length;
|
||||
|
||||
while (len && my_isspace(&my_charset_latin1, *src)) src++,len--;
|
||||
|
||||
if (len)
|
||||
{
|
||||
if (*src == '-')
|
||||
{
|
||||
sign= -1;
|
||||
src++;
|
||||
} else if (*src == '-')
|
||||
src++;
|
||||
while(len && my_isdigit(&my_charset_latin1, *src))
|
||||
{
|
||||
i= i * 10 + (*src - '0');
|
||||
src++;
|
||||
}
|
||||
}
|
||||
else
|
||||
rc= ER_DYNCOL_TRUNCATED;
|
||||
if (len)
|
||||
rc= ER_DYNCOL_TRUNCATED;
|
||||
*ll= i * sign;
|
||||
break;
|
||||
}
|
||||
case DYN_COL_DECIMAL:
|
||||
if (decimal2longlong(&val->x.decimal.value, ll) != E_DEC_OK)
|
||||
rc= ER_DYNCOL_TRUNCATED;
|
||||
break;
|
||||
case DYN_COL_DATETIME:
|
||||
*ll= (val->x.time_value.year * 10000000000L +
|
||||
val->x.time_value.month * 100000000L +
|
||||
val->x.time_value.day * 1000000 +
|
||||
val->x.time_value.hour * 10000 +
|
||||
val->x.time_value.minute * 100 +
|
||||
val->x.time_value.second) *
|
||||
(val->x.time_value.neg ? -1 : 1);
|
||||
break;
|
||||
case DYN_COL_DATE:
|
||||
*ll= (val->x.time_value.year * 10000 +
|
||||
val->x.time_value.month * 100 +
|
||||
val->x.time_value.day) *
|
||||
(val->x.time_value.neg ? -1 : 1);
|
||||
break;
|
||||
case DYN_COL_TIME:
|
||||
*ll= (val->x.time_value.hour * 10000 +
|
||||
val->x.time_value.minute * 100 +
|
||||
val->x.time_value.second) *
|
||||
(val->x.time_value.neg ? -1 : 1);
|
||||
break;
|
||||
case DYN_COL_NULL:
|
||||
rc= ER_DYNCOL_TRUNCATED;
|
||||
break;
|
||||
default:
|
||||
return(ER_DYNCOL_FORMAT);
|
||||
}
|
||||
return(rc);
|
||||
}
|
||||
|
||||
|
||||
enum enum_dyncol_func_result
|
||||
dynamic_column_val_double(double *dbl, DYNAMIC_COLUMN_VALUE *val)
|
||||
{
|
||||
enum enum_dyncol_func_result rc= ER_DYNCOL_OK;
|
||||
*dbl= 0;
|
||||
switch (val->type) {
|
||||
case DYN_COL_INT:
|
||||
*dbl= (double)val->x.long_value;
|
||||
if (((longlong) *dbl) != val->x.long_value)
|
||||
rc= ER_DYNCOL_TRUNCATED;
|
||||
break;
|
||||
case DYN_COL_UINT:
|
||||
*dbl= (double)val->x.ulong_value;
|
||||
if (((ulonglong) *dbl) != val->x.ulong_value)
|
||||
rc= ER_DYNCOL_TRUNCATED;
|
||||
break;
|
||||
case DYN_COL_DOUBLE:
|
||||
*dbl= val->x.double_value;
|
||||
break;
|
||||
case DYN_COL_STRING:
|
||||
{
|
||||
char *str, *end;
|
||||
if ((str= malloc(val->x.string.value.length + 1)))
|
||||
return ER_DYNCOL_RESOURCE;
|
||||
memcpy(str, val->x.string.value.str, val->x.string.value.length);
|
||||
str[val->x.string.value.length]= '\0';
|
||||
*dbl= strtod(str, &end);
|
||||
if (*end != '\0')
|
||||
rc= ER_DYNCOL_TRUNCATED;
|
||||
}
|
||||
case DYN_COL_DECIMAL:
|
||||
if (decimal2double(&val->x.decimal.value, dbl) != E_DEC_OK)
|
||||
rc= ER_DYNCOL_TRUNCATED;
|
||||
break;
|
||||
case DYN_COL_DATETIME:
|
||||
*dbl= (double)(val->x.time_value.year * 10000000000L +
|
||||
val->x.time_value.month * 100000000L +
|
||||
val->x.time_value.day * 1000000 +
|
||||
val->x.time_value.hour * 10000 +
|
||||
val->x.time_value.minute * 100 +
|
||||
val->x.time_value.second) *
|
||||
(val->x.time_value.neg ? -1 : 1);
|
||||
break;
|
||||
case DYN_COL_DATE:
|
||||
*dbl= (double)(val->x.time_value.year * 10000 +
|
||||
val->x.time_value.month * 100 +
|
||||
val->x.time_value.day) *
|
||||
(val->x.time_value.neg ? -1 : 1);
|
||||
break;
|
||||
case DYN_COL_TIME:
|
||||
*dbl= (double)(val->x.time_value.hour * 10000 +
|
||||
val->x.time_value.minute * 100 +
|
||||
val->x.time_value.second) *
|
||||
(val->x.time_value.neg ? -1 : 1);
|
||||
break;
|
||||
case DYN_COL_NULL:
|
||||
rc= ER_DYNCOL_TRUNCATED;
|
||||
break;
|
||||
default:
|
||||
return(ER_DYNCOL_FORMAT);
|
||||
}
|
||||
return(rc);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Convert to JSON
|
||||
|
||||
@ -3602,10 +3753,11 @@ dynamic_column_json(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json)
|
||||
if (header.format == DYNCOL_FMT_NUM)
|
||||
{
|
||||
uint nm= uint2korr(header.entry);
|
||||
if (dynstr_realloc(json, 6 + 3))
|
||||
if (dynstr_realloc(json, DYNCOL_NUM_CHAR + 3))
|
||||
goto err;
|
||||
json->str[json->length++]= '"';
|
||||
json->length+= (snprintf(json->str + json->length, 6, "%u", nm));
|
||||
json->length+= (snprintf(json->str + json->length,
|
||||
DYNCOL_NUM_CHAR, "%u", nm));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -3619,7 +3771,8 @@ dynamic_column_json(DYNAMIC_COLUMN *str, DYNAMIC_STRING *json)
|
||||
}
|
||||
json->str[json->length++]= '"';
|
||||
json->str[json->length++]= ':';
|
||||
if ((rc= dynamic_column_val_str(json, &val, TRUE)) < 0 ||
|
||||
if ((rc= dynamic_column_val_str(json, &val,
|
||||
&my_charset_utf8_general_ci, TRUE)) < 0 ||
|
||||
dynstr_append_mem(json, "}", 1))
|
||||
goto err;
|
||||
}
|
||||
@ -3631,3 +3784,99 @@ err:
|
||||
json->length= 0;
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Convert to DYNAMIC_COLUMN_VALUE values and names (LEX_STING) dynamic array
|
||||
|
||||
@param str The packed string
|
||||
@param names Where to put names
|
||||
@param vals Where to put values
|
||||
@param free_names pointer to free names buffer if there is it.
|
||||
|
||||
@return ER_DYNCOL_* return code
|
||||
*/
|
||||
|
||||
enum enum_dyncol_func_result
|
||||
dynamic_column_vals(DYNAMIC_COLUMN *str,
|
||||
DYNAMIC_ARRAY *names, DYNAMIC_ARRAY *vals,
|
||||
char **free_names)
|
||||
{
|
||||
DYN_HEADER header;
|
||||
char *nm;
|
||||
uint i;
|
||||
enum enum_dyncol_func_result rc;
|
||||
|
||||
*free_names= 0;
|
||||
bzero(names, sizeof(DYNAMIC_ARRAY)); /* In case of errors */
|
||||
bzero(vals, sizeof(DYNAMIC_ARRAY)); /* In case of errors */
|
||||
if (str->length == 0)
|
||||
return ER_DYNCOL_OK; /* no columns */
|
||||
|
||||
if ((rc= init_read_hdr(&header, str)) < 0)
|
||||
return rc;
|
||||
|
||||
if (header.entry_size * header.column_count + FIXED_HEADER_SIZE >
|
||||
str->length)
|
||||
return ER_DYNCOL_FORMAT;
|
||||
|
||||
if (init_dynamic_array(names, sizeof(LEX_STRING),
|
||||
header.column_count, 0) ||
|
||||
init_dynamic_array(vals, sizeof(DYNAMIC_COLUMN_VALUE),
|
||||
header.column_count, 0) ||
|
||||
(header.format == DYNCOL_FMT_NUM &&
|
||||
!(*free_names= (char *)malloc(DYNCOL_NUM_CHAR * header.column_count))))
|
||||
{
|
||||
rc= ER_DYNCOL_RESOURCE;
|
||||
goto err;
|
||||
}
|
||||
nm= *free_names;
|
||||
|
||||
for (i= 0, header.entry= header.header;
|
||||
i < header.column_count;
|
||||
i++, header.entry+= header.entry_size)
|
||||
{
|
||||
DYNAMIC_COLUMN_VALUE val;
|
||||
LEX_STRING name;
|
||||
header.length=
|
||||
hdr_interval_length(&header, header.entry + header.entry_size);
|
||||
header.data= header.dtpool + header.offset;
|
||||
/*
|
||||
Check that the found data is withing the ranges. This can happen if
|
||||
we get data with wrong offsets.
|
||||
*/
|
||||
if (header.length == DYNCOL_OFFSET_ERROR ||
|
||||
header.length > INT_MAX || header.offset > header.data_size)
|
||||
{
|
||||
rc= ER_DYNCOL_FORMAT;
|
||||
goto err;
|
||||
}
|
||||
if ((rc= dynamic_column_get_value(&header, &val)) < 0)
|
||||
goto err;
|
||||
|
||||
if (header.format == DYNCOL_FMT_NUM)
|
||||
{
|
||||
uint num= uint2korr(header.entry);
|
||||
name.str= nm;
|
||||
name.length= snprintf(nm, DYNCOL_NUM_CHAR, "%u", num);
|
||||
nm+= name.length + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
name.length= header.entry[0];
|
||||
name.str= (char *)header.nmpool + uint2korr(header.entry + 1);
|
||||
}
|
||||
/* following is preallocated and so do not fail */
|
||||
(void) insert_dynamic(names, (uchar *)&name);
|
||||
(void) insert_dynamic(vals, (uchar *)&val);
|
||||
}
|
||||
return ER_DYNCOL_OK;
|
||||
|
||||
err:
|
||||
delete_dynamic(names);
|
||||
delete_dynamic(vals);
|
||||
if (*free_names)
|
||||
my_free(*free_names);
|
||||
*free_names= 0;
|
||||
return rc;
|
||||
}
|
||||
|
@ -9773,6 +9773,7 @@ int dynamic_column_error_message(enum_dyncol_func_result rc)
|
||||
switch (rc) {
|
||||
case ER_DYNCOL_YES:
|
||||
case ER_DYNCOL_OK:
|
||||
case ER_DYNCOL_TRUNCATED:
|
||||
break; // it is not an error
|
||||
case ER_DYNCOL_FORMAT:
|
||||
my_error(ER_DYN_COL_WRONG_FORMAT, MYF(0));
|
||||
|
@ -272,6 +272,7 @@ bool rename_temporary_table(THD* thd, TABLE *table, const char *new_db,
|
||||
const char *table_name);
|
||||
bool is_equal(const LEX_STRING *a, const LEX_STRING *b);
|
||||
|
||||
class Open_tables_backup;
|
||||
/* Functions to work with system tables. */
|
||||
bool open_system_tables_for_read(THD *thd, TABLE_LIST *table_list,
|
||||
Open_tables_backup *backup);
|
||||
|
@ -12,7 +12,7 @@ SET(cassandra_sources
|
||||
gen-cpp/Cassandra.h)
|
||||
|
||||
#INCLUDE_DIRECTORIES(BEFORE ${Boost_INCLUDE_DIRS})
|
||||
INCLUDE_DIRECTORIES(AFTER /home/psergey/cassandra/thrift/include/thrift/)
|
||||
INCLUDE_DIRECTORIES(AFTER /usr/local/include/thrift)
|
||||
#
|
||||
STRING(REPLACE "-fno-exceptions" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
STRING(REPLACE "-fno-implicit-templates" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
|
||||
|
@ -17,6 +17,12 @@
|
||||
|
||||
#include "cassandra_se.h"
|
||||
|
||||
struct st_mysql_lex_string
|
||||
{
|
||||
char *str;
|
||||
size_t length;
|
||||
};
|
||||
|
||||
using namespace std;
|
||||
using namespace apache::thrift;
|
||||
using namespace apache::thrift::transport;
|
||||
@ -74,6 +80,7 @@ class Cassandra_se_impl: public Cassandra_se_interface
|
||||
std::string rowkey; /* key of the record we're returning now */
|
||||
|
||||
SlicePredicate slice_pred;
|
||||
SliceRange slice_pred_sr;
|
||||
bool get_slices_returned_less;
|
||||
bool get_slice_found_rows;
|
||||
public:
|
||||
@ -91,6 +98,8 @@ public:
|
||||
void first_ddl_column();
|
||||
bool next_ddl_column(char **name, int *name_len, char **value, int *value_len);
|
||||
void get_rowkey_type(char **name, char **type);
|
||||
size_t get_ddl_size();
|
||||
const char* get_default_validator();
|
||||
|
||||
/* Settings */
|
||||
void set_consistency_levels(ulong read_cons_level, ulong write_cons_level);
|
||||
@ -98,15 +107,19 @@ public:
|
||||
/* Writes */
|
||||
void clear_insert_buffer();
|
||||
void start_row_insert(const char *key, int key_len);
|
||||
void add_insert_column(const char *name, const char *value, int value_len);
|
||||
void add_insert_column(const char *name, int name_len,
|
||||
const char *value, int value_len);
|
||||
void add_insert_delete_column(const char *name, int name_len);
|
||||
void add_row_deletion(const char *key, int key_len,
|
||||
Column_name_enumerator *col_names);
|
||||
|
||||
Column_name_enumerator *col_names,
|
||||
LEX_STRING *names, uint nnames);
|
||||
|
||||
bool do_insert();
|
||||
|
||||
/* Reads, point lookups */
|
||||
bool get_slice(char *key, size_t key_len, bool *found);
|
||||
bool get_next_read_column(char **name, char **value, int *value_len);
|
||||
bool get_next_read_column(char **name, int *name_len,
|
||||
char **value, int *value_len );
|
||||
void get_read_rowkey(char **value, int *value_len);
|
||||
|
||||
/* Reads, multi-row scans */
|
||||
@ -122,6 +135,7 @@ public:
|
||||
|
||||
/* Setup that's necessary before a multi-row read. (todo: use it before point lookups, too) */
|
||||
void clear_read_columns();
|
||||
void clear_read_all_columns();
|
||||
void add_read_column(const char *name);
|
||||
|
||||
/* Reads, MRR scans */
|
||||
@ -277,6 +291,16 @@ void Cassandra_se_impl::get_rowkey_type(char **name, char **type)
|
||||
*name= NULL;
|
||||
}
|
||||
|
||||
size_t Cassandra_se_impl::get_ddl_size()
|
||||
{
|
||||
return cf_def.column_metadata.size();
|
||||
}
|
||||
|
||||
const char* Cassandra_se_impl::get_default_validator()
|
||||
{
|
||||
return cf_def.default_validation_class.c_str();
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// Data writes
|
||||
@ -315,8 +339,9 @@ void Cassandra_se_impl::start_row_insert(const char *key, int key_len)
|
||||
}
|
||||
|
||||
|
||||
void Cassandra_se_impl::add_row_deletion(const char *key, int key_len,
|
||||
Column_name_enumerator *col_names)
|
||||
void Cassandra_se_impl::add_row_deletion(const char *key, int key_len,
|
||||
Column_name_enumerator *col_names,
|
||||
LEX_STRING *names, uint nnames)
|
||||
{
|
||||
std::string key_to_delete;
|
||||
key_to_delete.assign(key, key_len);
|
||||
@ -344,6 +369,9 @@ void Cassandra_se_impl::add_row_deletion(const char *key, int key_len,
|
||||
const char *col_name;
|
||||
while ((col_name= col_names->get_next_name()))
|
||||
slice_pred.column_names.push_back(std::string(col_name));
|
||||
for (uint i= 0; i < nnames; i++)
|
||||
slice_pred.column_names.push_back(std::string(names[i].str,
|
||||
names[i].length));
|
||||
|
||||
mut.deletion.predicate= slice_pred;
|
||||
|
||||
@ -351,7 +379,9 @@ void Cassandra_se_impl::add_row_deletion(const char *key, int key_len,
|
||||
}
|
||||
|
||||
|
||||
void Cassandra_se_impl::add_insert_column(const char *name, const char *value,
|
||||
void Cassandra_se_impl::add_insert_column(const char *name,
|
||||
int name_len,
|
||||
const char *value,
|
||||
int value_len)
|
||||
{
|
||||
Mutation mut;
|
||||
@ -359,7 +389,10 @@ void Cassandra_se_impl::add_insert_column(const char *name, const char *value,
|
||||
mut.column_or_supercolumn.__isset.column= true;
|
||||
|
||||
Column& col=mut.column_or_supercolumn.column;
|
||||
col.name.assign(name);
|
||||
if (name_len)
|
||||
col.name.assign(name, name_len);
|
||||
else
|
||||
col.name.assign(name);
|
||||
col.value.assign(value, value_len);
|
||||
col.timestamp= insert_timestamp;
|
||||
col.__isset.value= true;
|
||||
@ -367,6 +400,23 @@ void Cassandra_se_impl::add_insert_column(const char *name, const char *value,
|
||||
insert_list->push_back(mut);
|
||||
}
|
||||
|
||||
void Cassandra_se_impl::add_insert_delete_column(const char *name,
|
||||
int name_len)
|
||||
{
|
||||
Mutation mut;
|
||||
mut.__isset.deletion= true;
|
||||
mut.deletion.__isset.timestamp= true;
|
||||
mut.deletion.timestamp= insert_timestamp;
|
||||
mut.deletion.__isset.predicate= true;
|
||||
|
||||
SlicePredicate slice_pred;
|
||||
slice_pred.__isset.column_names= true;
|
||||
slice_pred.column_names.push_back(std::string(name, name_len));
|
||||
mut.deletion.predicate= slice_pred;
|
||||
|
||||
insert_list->push_back(mut);
|
||||
}
|
||||
|
||||
|
||||
bool Cassandra_se_impl::retryable_do_insert()
|
||||
{
|
||||
@ -444,8 +494,8 @@ bool Cassandra_se_impl::retryable_get_slice()
|
||||
}
|
||||
|
||||
|
||||
bool Cassandra_se_impl::get_next_read_column(char **name, char **value,
|
||||
int *value_len)
|
||||
bool Cassandra_se_impl::get_next_read_column(char **name, int *name_len,
|
||||
char **value, int *value_len)
|
||||
{
|
||||
bool use_counter=false;
|
||||
while (1)
|
||||
@ -468,12 +518,14 @@ bool Cassandra_se_impl::get_next_read_column(char **name, char **value,
|
||||
ColumnOrSuperColumn& cs= *column_data_it;
|
||||
if (use_counter)
|
||||
{
|
||||
*name_len= cs.counter_column.name.size();
|
||||
*name= (char*)cs.counter_column.name.c_str();
|
||||
*value= (char*)&cs.counter_column.value;
|
||||
*value_len= sizeof(cs.counter_column.value);
|
||||
}
|
||||
else
|
||||
{
|
||||
*name_len= cs.column.name.size();
|
||||
*name= (char*)cs.column.name.c_str();
|
||||
*value= (char*)cs.column.value.c_str();
|
||||
*value_len= cs.column.value.length();
|
||||
@ -601,6 +653,13 @@ void Cassandra_se_impl::clear_read_columns()
|
||||
slice_pred.column_names.clear();
|
||||
}
|
||||
|
||||
void Cassandra_se_impl::clear_read_all_columns()
|
||||
{
|
||||
slice_pred_sr.start = "";
|
||||
slice_pred_sr.finish = "";
|
||||
slice_pred.__set_slice_range(slice_pred_sr);
|
||||
}
|
||||
|
||||
|
||||
void Cassandra_se_impl::add_read_column(const char *name_arg)
|
||||
{
|
||||
|
@ -6,6 +6,8 @@
|
||||
both together causes compile errors due to conflicts).
|
||||
*/
|
||||
|
||||
struct st_mysql_lex_string;
|
||||
typedef struct st_mysql_lex_string LEX_STRING;
|
||||
|
||||
/* We need to define this here so that ha_cassandra.cc also has access to it */
|
||||
typedef enum
|
||||
@ -50,19 +52,25 @@ public:
|
||||
virtual bool next_ddl_column(char **name, int *name_len, char **value,
|
||||
int *value_len)=0;
|
||||
virtual void get_rowkey_type(char **name, char **type)=0;
|
||||
virtual size_t get_ddl_size()=0;
|
||||
virtual const char* get_default_validator()=0;
|
||||
|
||||
/* Writes */
|
||||
virtual void clear_insert_buffer()=0;
|
||||
virtual void add_row_deletion(const char *key, int key_len,
|
||||
Column_name_enumerator *col_names)=0;
|
||||
Column_name_enumerator *col_names,
|
||||
LEX_STRING *names, uint nnames)=0;
|
||||
virtual void start_row_insert(const char *key, int key_len)=0;
|
||||
virtual void add_insert_column(const char *name, const char *value,
|
||||
virtual void add_insert_delete_column(const char *name, int name_len)= 0;
|
||||
virtual void add_insert_column(const char *name, int name_len,
|
||||
const char *value,
|
||||
int value_len)=0;
|
||||
virtual bool do_insert()=0;
|
||||
|
||||
/* Reads */
|
||||
virtual bool get_slice(char *key, size_t key_len, bool *found)=0 ;
|
||||
virtual bool get_next_read_column(char **name, char **value, int *value_len)=0;
|
||||
virtual bool get_next_read_column(char **name, int *name_len,
|
||||
char **value, int *value_len)=0;
|
||||
virtual void get_read_rowkey(char **value, int *value_len)=0;
|
||||
|
||||
/* Reads, multi-row scans */
|
||||
@ -70,7 +78,7 @@ public:
|
||||
virtual bool get_range_slices(bool last_key_as_start_key)=0;
|
||||
virtual void finish_reading_range_slices()=0;
|
||||
virtual bool get_next_range_slice_row(bool *eof)=0;
|
||||
|
||||
|
||||
/* Reads, MRR scans */
|
||||
virtual void new_lookup_keys()=0;
|
||||
virtual int add_lookup_key(const char *key, size_t key_len)=0;
|
||||
@ -79,8 +87,9 @@ public:
|
||||
|
||||
/* read_set setup */
|
||||
virtual void clear_read_columns()=0;
|
||||
virtual void clear_read_all_columns()=0;
|
||||
virtual void add_read_column(const char *name)=0;
|
||||
|
||||
|
||||
virtual bool truncate()=0;
|
||||
virtual bool remove_row()=0;
|
||||
|
||||
|
@ -11,7 +11,7 @@ namespace org { namespace apache { namespace cassandra {
|
||||
const cassandraConstants g_cassandra_constants;
|
||||
|
||||
cassandraConstants::cassandraConstants() {
|
||||
cassandra_const_VERSION = "19.32.0";
|
||||
cassandra_const_VERSION = (char *)"19.32.0";
|
||||
}
|
||||
|
||||
}}} // namespace
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -40,6 +40,33 @@ class ColumnDataConverter;
|
||||
|
||||
struct ha_table_option_struct;
|
||||
|
||||
|
||||
struct st_dynamic_column_value;
|
||||
|
||||
typedef bool (* CAS2DYN_CONVERTER)(const char *cass_data,
|
||||
int cass_data_len,
|
||||
struct st_dynamic_column_value *value);
|
||||
typedef bool (* DYN2CAS_CONVERTER)(struct st_dynamic_column_value *value,
|
||||
char **cass_data,
|
||||
int *cass_data_len,
|
||||
void *buf, void **freemem);
|
||||
struct cassandra_type_def
|
||||
{
|
||||
const char *name;
|
||||
CAS2DYN_CONVERTER cassandra_to_dynamic;
|
||||
DYN2CAS_CONVERTER dynamic_to_cassandra;
|
||||
};
|
||||
|
||||
typedef struct cassandra_type_def CASSANDRA_TYPE_DEF;
|
||||
|
||||
enum cassandtra_type_enum {CT_BIGINT, CT_INT, CT_COUNTER, CT_FLOAT, CT_DOUBLE,
|
||||
CT_BLOB, CT_ASCII, CT_TEXT, CT_TIMESTAMP, CT_UUID, CT_BOOLEAN, CT_VARINT,
|
||||
CT_DECIMAL};
|
||||
|
||||
typedef enum cassandtra_type_enum CASSANDRA_TYPE;
|
||||
|
||||
|
||||
|
||||
/** @brief
|
||||
Class definition for the storage engine
|
||||
*/
|
||||
@ -48,23 +75,35 @@ class ha_cassandra: public handler
|
||||
friend class Column_name_enumerator_impl;
|
||||
THR_LOCK_DATA lock; ///< MySQL lock
|
||||
CASSANDRA_SHARE *share; ///< Shared lock info
|
||||
|
||||
|
||||
Cassandra_se_interface *se;
|
||||
|
||||
/* description of static part of the table definition */
|
||||
ColumnDataConverter **field_converters;
|
||||
uint n_field_converters;
|
||||
|
||||
CASSANDRA_TYPE_DEF *default_type_def;
|
||||
/* description of dynamic columns part */
|
||||
CASSANDRA_TYPE_DEF *special_type_field_converters;
|
||||
LEX_STRING *special_type_field_names;
|
||||
uint n_special_type_fields;
|
||||
DYNAMIC_ARRAY dynamic_values, dynamic_names;
|
||||
DYNAMIC_STRING dynamic_rec;
|
||||
|
||||
ColumnDataConverter *rowkey_converter;
|
||||
|
||||
bool setup_field_converters(Field **field, uint n_fields);
|
||||
void free_field_converters();
|
||||
|
||||
|
||||
int read_cassandra_columns(bool unpack_pk);
|
||||
int check_table_options(struct ha_table_option_struct* options);
|
||||
|
||||
bool doing_insert_batch;
|
||||
ha_rows insert_rows_batched;
|
||||
|
||||
|
||||
uint dyncol_field;
|
||||
bool dyncol_set;
|
||||
|
||||
/* Used to produce 'wrong column %s at row %lu' warnings */
|
||||
ha_rows insert_lineno;
|
||||
void print_conversion_error(const char *field_name,
|
||||
@ -191,6 +230,14 @@ public:
|
||||
private:
|
||||
bool source_exhausted;
|
||||
bool mrr_start_read();
|
||||
int check_field_options(Field **fields);
|
||||
int read_dyncol(DYNAMIC_ARRAY *vals, DYNAMIC_ARRAY *names,
|
||||
String *valcol, char **freenames);
|
||||
int write_dynamic_row(DYNAMIC_ARRAY *names, DYNAMIC_ARRAY *vals);
|
||||
void static free_dynamic_row(DYNAMIC_ARRAY *vals, DYNAMIC_ARRAY *names,
|
||||
char *free_names);
|
||||
CASSANDRA_TYPE_DEF * get_cassandra_field_def(char *cass_name,
|
||||
int cass_name_length);
|
||||
public:
|
||||
|
||||
/*
|
||||
|
Loading…
x
Reference in New Issue
Block a user