| 1 |
#ifdef USE_PRAGMA_IMPLEMENTATION |
| 2 |
#pragma implementation // gcc: Class implementation |
| 3 |
#endif |
| 4 |
|
| 5 |
#include "mysql_priv.h" |
| 6 |
#undef PACKAGE |
| 7 |
#undef VERSION |
| 8 |
#undef HAVE_DTRACE |
| 9 |
#undef _DTRACE_VERSION |
| 10 |
|
| 11 |
#include "tritonn_config.h" |
| 12 |
|
| 13 |
/* We define DTRACE after mysql_priv.h in case it disabled dtrace in the main server */ |
| 14 |
#ifdef HAVE_DTRACE |
| 15 |
#define _DTRACE_VERSION 1 |
| 16 |
#else |
| 17 |
#endif |
| 18 |
|
| 19 |
#include "ha_tritonn.h" |
| 20 |
#include <mysql/plugin.h> |
| 21 |
|
| 22 |
/* create ha_tritonn instance */ |
| 23 |
static handler *tritonn_create_handler(handlerton *hton, |
| 24 |
TABLE_SHARE *table, |
| 25 |
MEM_ROOT *mem_root); |
| 26 |
|
| 27 |
static TRITONN_DB *tdb; |
| 28 |
static sen_db *get_sen_db(const char *db_name); |
| 29 |
|
| 30 |
/* delete database files */ |
| 31 |
static void tritonn_drop_database(handlerton *hton, char* path); |
| 32 |
|
| 33 |
/* flush logfile */ |
| 34 |
static bool tritonn_flush_logs(handlerton *hton); |
| 35 |
|
| 36 |
/* show engine status */ |
| 37 |
static bool tritonn_show_status(handlerton *hton, THD *thd, stat_print_fn *print, |
| 38 |
enum ha_stat_type stat); |
| 39 |
|
| 40 |
static void dump_create(const char *name, TABLE *table_arg, |
| 41 |
HA_CREATE_INFO *create_info); |
| 42 |
|
| 43 |
static void call_senna_ql(sen_ctx *ctx, const char *str, bool disp=true); |
| 44 |
|
| 45 |
static char *mysqltype2sennatype_string(enum_field_types types); |
| 46 |
|
| 47 |
/* handlerton capability flags. see handler.h for more information */ |
| 48 |
static int tritonn_hton_flags = HTON_ALTER_NOT_SUPPORTED | HTON_CAN_RECREATE | |
| 49 |
HTON_TEMPORARY_NOT_SUPPORTED | HTON_NO_PARTITION; |
| 50 |
|
| 51 |
/* Variables for tritonn share methods */ |
| 52 |
static HASH tritonn_open_tables; ///< Hash used to track the number of open tables; variable for tritonn share methods |
| 53 |
pthread_mutex_t tritonn_mutex; ///< This is the mutex used to init the hash; variable for tritonn share methods |
| 54 |
|
| 55 |
static uchar* get_key(TRITONN_SHARE *share, size_t *length, |
| 56 |
my_bool not_used __attribute__((unused))) |
| 57 |
{ |
| 58 |
*length=share->table_name_length; |
| 59 |
return (uchar*) share->table_name; |
| 60 |
} |
| 61 |
|
| 62 |
static int tritonn_init_hton(void *p) |
| 63 |
{ |
| 64 |
DBUG_ENTER("tritonn_init_hton"); |
| 65 |
DBTN; |
| 66 |
|
| 67 |
handlerton *hton; |
| 68 |
|
| 69 |
hton= (handlerton *)p; |
| 70 |
VOID(pthread_mutex_init(&tritonn_mutex, MY_MUTEX_INIT_FAST)); |
| 71 |
(void) hash_init(&tritonn_open_tables, system_charset_info, 32, 0, 0, |
| 72 |
(hash_get_key) get_key, 0, 0); |
| 73 |
|
| 74 |
hton->state = SHOW_OPTION_YES; |
| 75 |
hton->create = tritonn_create_handler; |
| 76 |
hton->drop_database = tritonn_drop_database; |
| 77 |
hton->flush_logs = tritonn_flush_logs; |
| 78 |
hton->show_status = tritonn_show_status; |
| 79 |
hton->flags = tritonn_hton_flags; |
| 80 |
|
| 81 |
sen_init(); |
| 82 |
DBUG_RETURN(0); |
| 83 |
} |
| 84 |
|
| 85 |
static int tritonn_deinit_hton(void *p) |
| 86 |
{ |
| 87 |
int error= 0; |
| 88 |
DBUG_ENTER("tritonn_deinit_hton"); |
| 89 |
DBTN; |
| 90 |
|
| 91 |
if (tritonn_open_tables.records) |
| 92 |
error= 1; |
| 93 |
hash_free(&tritonn_open_tables); |
| 94 |
while (tdb != NULL) { |
| 95 |
sen_db_close(tdb->db); |
| 96 |
tdb = tdb->next; |
| 97 |
} |
| 98 |
pthread_mutex_destroy(&tritonn_mutex); |
| 99 |
|
| 100 |
sen_fin(); |
| 101 |
DBUG_RETURN(0); |
| 102 |
} |
| 103 |
|
| 104 |
/** @brief |
| 105 |
Skeleton of simple lock controls. The "share" it creates is a structure we will |
| 106 |
pass to each tritonn handler. Do you have to have one of these? Well, you have |
| 107 |
pieces that are used for locking, and they are needed to function. |
| 108 |
*/ |
| 109 |
static TRITONN_SHARE *get_share(const char *table_name, TABLE *table) |
| 110 |
{ |
| 111 |
TRITONN_SHARE *share; |
| 112 |
uint length; |
| 113 |
char *tmp_name; |
| 114 |
|
| 115 |
DBTN; |
| 116 |
|
| 117 |
pthread_mutex_lock(&tritonn_mutex); |
| 118 |
length=(uint) strlen(table_name); |
| 119 |
|
| 120 |
if (!(share=(TRITONN_SHARE*) hash_search(&tritonn_open_tables, |
| 121 |
(uchar*) table_name, |
| 122 |
length))) |
| 123 |
{ |
| 124 |
if (!(share=(TRITONN_SHARE *) |
| 125 |
my_multi_malloc(MYF(MY_WME | MY_ZEROFILL), |
| 126 |
&share, sizeof(*share), |
| 127 |
&tmp_name, length+1, |
| 128 |
NullS))) |
| 129 |
{ |
| 130 |
pthread_mutex_unlock(&tritonn_mutex); |
| 131 |
return NULL; |
| 132 |
} |
| 133 |
|
| 134 |
share->use_count=0; |
| 135 |
share->table_name_length=length; |
| 136 |
share->table_name=tmp_name; |
| 137 |
strmov(share->table_name,table_name); |
| 138 |
if (my_hash_insert(&tritonn_open_tables, (uchar*) share)) |
| 139 |
goto error; |
| 140 |
thr_lock_init(&share->lock); |
| 141 |
pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST); |
| 142 |
} |
| 143 |
share->use_count++; |
| 144 |
pthread_mutex_unlock(&tritonn_mutex); |
| 145 |
|
| 146 |
return share; |
| 147 |
|
| 148 |
error: |
| 149 |
pthread_mutex_unlock(&tritonn_mutex); |
| 150 |
pthread_mutex_destroy(&share->mutex); |
| 151 |
my_free((uchar *) share, MYF(0)); |
| 152 |
|
| 153 |
return NULL; |
| 154 |
} |
| 155 |
|
| 156 |
/** @brief |
| 157 |
Free lock controls. We call this whenever we close a table. If the table had |
| 158 |
the last reference to the share, then we free memory associated with it. |
| 159 |
*/ |
| 160 |
static int free_share(TRITONN_SHARE *share) |
| 161 |
{ |
| 162 |
DBTN; |
| 163 |
pthread_mutex_lock(&tritonn_mutex); |
| 164 |
if (!--share->use_count) |
| 165 |
{ |
| 166 |
hash_delete(&tritonn_open_tables, (uchar*) share); |
| 167 |
thr_lock_delete(&share->lock); |
| 168 |
pthread_mutex_destroy(&share->mutex); |
| 169 |
my_free((uchar *) share, MYF(0)); |
| 170 |
} |
| 171 |
pthread_mutex_unlock(&tritonn_mutex); |
| 172 |
|
| 173 |
return 0; |
| 174 |
} |
| 175 |
|
| 176 |
/* create ha_tritonn instance */ |
| 177 |
static handler* tritonn_create_handler(handlerton *hton, |
| 178 |
TABLE_SHARE *table, |
| 179 |
MEM_ROOT *mem_root) |
| 180 |
{ |
| 181 |
DBTN; |
| 182 |
return new (mem_root) ha_tritonn(hton, table); |
| 183 |
} |
| 184 |
|
| 185 |
/* delete database files */ |
| 186 |
static void tritonn_drop_database(handlerton *hton, char* path) |
| 187 |
{ |
| 188 |
DBTN; |
| 189 |
} |
| 190 |
|
| 191 |
/* flush logfile */ |
| 192 |
static bool tritonn_flush_logs(handlerton *hton) |
| 193 |
{ |
| 194 |
DBTN; |
| 195 |
return true; |
| 196 |
} |
| 197 |
|
| 198 |
/* show engine status */ |
| 199 |
static bool tritonn_show_status(handlerton *hton, THD *thd, stat_print_fn *print, |
| 200 |
enum ha_stat_type stat) |
| 201 |
{ |
| 202 |
DBTN; |
| 203 |
return true; |
| 204 |
} |
| 205 |
|
| 206 |
ha_tritonn::ha_tritonn(handlerton *hton, TABLE_SHARE *table_arg) |
| 207 |
:handler(hton, table_arg) |
| 208 |
{ |
| 209 |
DBTN; |
| 210 |
} |
| 211 |
|
| 212 |
ha_tritonn::~ha_tritonn() |
| 213 |
{ |
| 214 |
DBTN; |
| 215 |
} |
| 216 |
|
| 217 |
const char *ha_tritonn::table_type() const |
| 218 |
{ |
| 219 |
DBTN; |
| 220 |
return "TRITONN"; |
| 221 |
} |
| 222 |
|
| 223 |
const char *ha_tritonn::index_type(uint inx) const |
| 224 |
{ |
| 225 |
DBTN; |
| 226 |
return "SENNA"; |
| 227 |
} |
| 228 |
|
| 229 |
/* TODO: examin this feature */ |
| 230 |
static const char *ha_tritonn_exts[] = { |
| 231 |
NullS |
| 232 |
}; |
| 233 |
|
| 234 |
const char **ha_tritonn::bas_ext() const |
| 235 |
{ |
| 236 |
DBTN; |
| 237 |
return ha_tritonn_exts; |
| 238 |
} |
| 239 |
|
| 240 |
// see $MYSQL_SRC/sql/handler.h "bits in table_flags" |
| 241 |
ulonglong ha_tritonn::table_flags() const { |
| 242 |
DBTN; |
| 243 |
return (HA_NO_TRANSACTIONS | HA_STATS_RECORDS_IS_EXACT | |
| 244 |
HA_NO_PREFIX_CHAR_KEYS | HA_CAN_FULLTEXT | HA_NO_AUTO_INCREMENT); |
| 245 |
} |
| 246 |
|
| 247 |
// see $MYSQL_SRC/sql/handler.h, "bits in index_flags" |
| 248 |
ulong ha_tritonn::index_flags(uint inx, uint part, bool all_parts) const { |
| 249 |
DBTN; |
| 250 |
return (HA_ONLY_WHOLE_INDEX); |
| 251 |
} |
| 252 |
|
| 253 |
int ha_tritonn::add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys) { |
| 254 |
DBTN; |
| 255 |
return HA_ERR_WRONG_COMMAND; |
| 256 |
} |
| 257 |
|
| 258 |
int ha_tritonn::prepare_drop_index(TABLE *table_arg, uint *key_num, uint num_of_keys) |
| 259 |
{ |
| 260 |
DBTN; |
| 261 |
return HA_ERR_WRONG_COMMAND; |
| 262 |
} |
| 263 |
|
| 264 |
int ha_tritonn::final_drop_index(TABLE *table_arg) |
| 265 |
{ |
| 266 |
DBTN; |
| 267 |
return HA_ERR_WRONG_COMMAND; |
| 268 |
} |
| 269 |
|
| 270 |
|
| 271 |
int ha_tritonn::open(const char *name, int mode, uint test_if_locked) |
| 272 |
{ |
| 273 |
DBUG_ENTER("ha_tritonn::open"); |
| 274 |
DBTN; |
| 275 |
|
| 276 |
if (!(share = get_share(name, table))) |
| 277 |
DBUG_RETURN(HA_ERR_OUT_OF_MEM); |
| 278 |
thr_lock_data_init(&share->lock,&lock,NULL); |
| 279 |
share->short_name = table_share->table_name.str; |
| 280 |
ctx = sen_ctx_open(get_sen_db(table_share->db.str),SEN_CTX_USEQL); |
| 281 |
call_senna_ql(ctx, "(define (select recs expr) (reverse (letrec " |
| 282 |
"((func (lambda (r x) (if x (let ((y (expr x))) " |
| 283 |
"(func (if y (cons y r) r) (recs ::+ x))) r)))) " |
| 284 |
"(func () (recs ::)))))",false); |
| 285 |
call_senna_ql(ctx, "(define (slot-exps class) (select <db> " |
| 286 |
"(lambda (x) (let ((s (x ::schema))) (and (pair? s) " |
| 287 |
"(eq? class (car s)) (list () (car (cdr (cdr s)))))))))",false); |
| 288 |
call_senna_ql(ctx, "(define (dump-table class) (if (< 0 class.:nrecords) " |
| 289 |
"(begin (disp `(: ,class (.:key ,@(slot-exps class)) 0 0) " |
| 290 |
":tsv))))",false); |
| 291 |
|
| 292 |
DBUG_RETURN(0); |
| 293 |
} |
| 294 |
|
| 295 |
int ha_tritonn::close(void) |
| 296 |
{ |
| 297 |
DBUG_ENTER("ha_tritonn::close"); |
| 298 |
DBTN; |
| 299 |
sen_ctx_close(ctx); |
| 300 |
DBUG_RETURN(free_share(share)); |
| 301 |
} |
| 302 |
|
| 303 |
int ha_tritonn::rnd_init(bool scan) |
| 304 |
{ |
| 305 |
DBUG_ENTER("ha_tritonn::rnd_init"); |
| 306 |
DBTN; |
| 307 |
char buf[1024]; |
| 308 |
my_snprintf(buf,1024,"(dump-table <%s>)", share->short_name); |
| 309 |
call_senna_ql(ctx,buf, false); |
| 310 |
DBUG_RETURN(0); |
| 311 |
} |
| 312 |
|
| 313 |
int ha_tritonn::rnd_next(uchar *buf) |
| 314 |
{ |
| 315 |
DBUG_ENTER("ha_tritonn::rnd_next"); |
| 316 |
DBTN; |
| 317 |
char *res; |
| 318 |
unsigned int res_len; |
| 319 |
int res_flags; |
| 320 |
char *row; |
| 321 |
sen_ctx_recv(ctx,&res,&res_len,&res_flags); |
| 322 |
if (res_flags & SEN_CTX_MORE) { |
| 323 |
char token[1024]; |
| 324 |
int offset=0; |
| 325 |
int i; |
| 326 |
for (Field **field=table->field; *field ; field++) { |
| 327 |
for (i=0; offset < res_len && *(res+offset) != '\t'; offset++,i++) { |
| 328 |
token[i] = *(res+offset); |
| 329 |
} |
| 330 |
offset++; |
| 331 |
switch((*field)->result_type()) { |
| 332 |
case STRING_RESULT: |
| 333 |
(*field)->store(token,i,system_charset_info); |
| 334 |
break; |
| 335 |
case REAL_RESULT: |
| 336 |
token[i] = '\0'; |
| 337 |
(*field)->store(atof(token)); |
| 338 |
break; |
| 339 |
case INT_RESULT: |
| 340 |
token[i] = '\0'; |
| 341 |
(*field)->store(atoi(token),false); |
| 342 |
break; |
| 343 |
case ROW_RESULT: |
| 344 |
(*field)->store("row_result",10,system_charset_info); |
| 345 |
break; |
| 346 |
case DECIMAL_RESULT: |
| 347 |
(*field)->store("decimal",7,system_charset_info); |
| 348 |
break; |
| 349 |
} |
| 350 |
} |
| 351 |
memset(buf, 0, table->s->null_bytes); |
| 352 |
DBUG_RETURN(0); |
| 353 |
} else { |
| 354 |
DBUG_RETURN(HA_ERR_END_OF_FILE); |
| 355 |
} |
| 356 |
} |
| 357 |
|
| 358 |
void ha_tritonn::position(const uchar *record) |
| 359 |
{ |
| 360 |
DBUG_ENTER("ha_tritonn::position"); |
| 361 |
DBTN; |
| 362 |
DBUG_VOID_RETURN; |
| 363 |
} |
| 364 |
|
| 365 |
int ha_tritonn::rnd_pos(uchar * buf, uchar *pos) |
| 366 |
{ |
| 367 |
DBUG_ENTER("ha_tritonn::rnd_pos"); |
| 368 |
DBTN; |
| 369 |
DBUG_RETURN(HA_ERR_WRONG_COMMAND); |
| 370 |
} |
| 371 |
|
| 372 |
int ha_tritonn::info(uint flag) |
| 373 |
{ |
| 374 |
DBUG_ENTER("ha_tritonn::info"); |
| 375 |
DBTN; |
| 376 |
char buf[1024]; |
| 377 |
char *res; |
| 378 |
unsigned int res_len; |
| 379 |
int res_flag; |
| 380 |
int i; |
| 381 |
my_snprintf(buf,1024,"(<%s> ::nrecords)", share->short_name); |
| 382 |
call_senna_ql(ctx,buf,false); |
| 383 |
sen_ctx_recv(ctx,&res,&res_len,&res_flag); |
| 384 |
char *res2 = (char*) sql_alloc(res_len+1); |
| 385 |
for (i=0; i<res_len; i++) { |
| 386 |
*(res2+i) = *(res+i); |
| 387 |
} |
| 388 |
*(res2+res_len) = '\0'; |
| 389 |
stats.records=atoi(res2); |
| 390 |
// printf("[SennaQL] returned nrecords = %d\n",stats.records); |
| 391 |
DBUG_RETURN(0); |
| 392 |
} |
| 393 |
|
| 394 |
THR_LOCK_DATA **ha_tritonn::store_lock(THD *thd, |
| 395 |
THR_LOCK_DATA **to, |
| 396 |
enum thr_lock_type lock_type) |
| 397 |
{ |
| 398 |
DBTN; |
| 399 |
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) |
| 400 |
lock.type=lock_type; |
| 401 |
*to++= &lock; |
| 402 |
return to; |
| 403 |
} |
| 404 |
|
| 405 |
int ha_tritonn::create(const char *name, TABLE *table_arg, |
| 406 |
HA_CREATE_INFO *create_info) |
| 407 |
{ |
| 408 |
DBUG_ENTER("ha_tritonn::create"); |
| 409 |
DBTN; |
| 410 |
char buf[FN_REFLEN]; |
| 411 |
//dump_create(name,table_arg,create_info); |
| 412 |
ctx = sen_ctx_open(get_sen_db(table_share->db.str),SEN_CTX_USEQL); |
| 413 |
my_snprintf(buf,1024,"(ptable '<%s>)",table_arg->s->table_name); |
| 414 |
call_senna_ql(ctx,buf); |
| 415 |
int i; |
| 416 |
/* col1 is assigned to pkey so i=1 here */ |
| 417 |
for (i=1; i < table_arg->s->fields; i++) { |
| 418 |
Field *field = table_arg->s->field[i]; |
| 419 |
my_snprintf(buf,1024,"(<%s> ::def :%s <%s>)", |
| 420 |
create_info->alias, |
| 421 |
field->field_name, |
| 422 |
mysqltype2sennatype_string(field->type())); |
| 423 |
call_senna_ql(ctx,buf); |
| 424 |
} |
| 425 |
sen_ctx_close(ctx); |
| 426 |
DBUG_RETURN(0); |
| 427 |
} |
| 428 |
|
| 429 |
uint ha_tritonn::max_supported_keys() const |
| 430 |
{ |
| 431 |
DBTN; |
| 432 |
return 1024; |
| 433 |
} |
| 434 |
|
| 435 |
uint ha_tritonn::max_supported_key_length() const |
| 436 |
{ |
| 437 |
DBTN; |
| 438 |
return 1024; |
| 439 |
} |
| 440 |
|
| 441 |
uint ha_tritonn::max_supported_key_part_length() const |
| 442 |
{ |
| 443 |
DBTN; |
| 444 |
return 1024; |
| 445 |
} |
| 446 |
|
| 447 |
|
| 448 |
struct st_mysql_storage_engine storage_engine_structure= |
| 449 |
{ MYSQL_HANDLERTON_INTERFACE_VERSION }; |
| 450 |
|
| 451 |
mysql_declare_plugin(tritonn) |
| 452 |
{ |
| 453 |
MYSQL_STORAGE_ENGINE_PLUGIN, |
| 454 |
&storage_engine_structure, |
| 455 |
"TRITONN", |
| 456 |
"Tritonn Project", |
| 457 |
"Tritonn storage engine", |
| 458 |
PLUGIN_LICENSE_BSD, |
| 459 |
tritonn_init_hton, /* Plugin Init */ |
| 460 |
tritonn_deinit_hton, /* Plugin Deinit */ |
| 461 |
0x0001 /* 0.1 */, |
| 462 |
NULL, /* status variables */ |
| 463 |
NULL, /* system variables */ |
| 464 |
NULL /* config options */ |
| 465 |
} |
| 466 |
mysql_declare_plugin_end; |
| 467 |
|
| 468 |
char *a_type[] = {"FIELD_ITEM","FUNC_ITEM", "SUM_FUNC_ITEM", "STRING_ITEM", |
| 469 |
"INT_ITEM", "REAL_ITEM", "NULL_ITEM", "VARBIN_ITEM", |
| 470 |
"COPY_STR_ITEM", "FIELD_AVG_ITEM", "DEFAULT_VALUE_ITEM", |
| 471 |
"PROC_ITEM","COND_ITEM", "REF_ITEM", "FIELD_STD_ITEM", |
| 472 |
"FIELD_VARIANCE_ITEM", "INSERT_VALUE_ITEM", |
| 473 |
"SUBSELECT_ITEM", "ROW_ITEM", "CACHE_ITEM", "TYPE_HOLDER", |
| 474 |
"PARAM_ITEM", "TRIGGER_FIELD_ITEM", "DECIMAL_ITEM", |
| 475 |
"XPATH_NODESET", "XPATH_NODESET_CMP", |
| 476 |
"VIEW_FIXER_ITEM"}; |
| 477 |
|
| 478 |
char *f_type[] ={"UNKNOWN_FUNC","EQ_FUNC","EQUAL_FUNC","NE_FUNC","LT_FUNC","LE_FUNC", |
| 479 |
"GE_FUNC","GT_FUNC","FT_FUNC", |
| 480 |
"LIKE_FUNC","ISNULL_FUNC","ISNOTNULL_FUNC", |
| 481 |
"COND_AND_FUNC", "COND_OR_FUNC", "COND_XOR_FUNC", |
| 482 |
"BETWEEN", "IN_FUNC", "MULT_EQUAL_FUNC", |
| 483 |
"INTERVAL_FUNC", "ISNOTNULLTEST_FUNC", |
| 484 |
"SP_EQUALS_FUNC", "SP_DISJOINT_FUNC","SP_INTERSECTS_FUNC", |
| 485 |
"SP_TOUCHES_FUNC","SP_CROSSES_FUNC","SP_WITHIN_FUNC", |
| 486 |
"SP_CONTAINS_FUNC","SP_OVERLAPS_FUNC", |
| 487 |
"SP_STARTPOINT","SP_ENDPOINT","SP_EXTERIORRING", |
| 488 |
"SP_POINTN","SP_GEOMETRYN","SP_INTERIORRINGN", |
| 489 |
"NOT_FUNC", "NOT_ALL_FUNC", |
| 490 |
"NOW_FUNC", "TRIG_COND_FUNC", |
| 491 |
"SUSERVAR_FUNC", "GUSERVAR_FUNC", "COLLATE_FUNC", |
| 492 |
"EXTRACT_FUNC", "CHAR_TYPECAST_FUNC", "FUNC_SP", "UDF_FUNC", |
| 493 |
"NEG_FUNC" }; |
| 494 |
|
| 495 |
extern int string2my_decimal(uint mask, const String *str, my_decimal *d); |
| 496 |
#include "item_func.h" |
| 497 |
#include "my_decimal.h" |
| 498 |
|
| 499 |
void dump_condition(Item *cond) |
| 500 |
{ |
| 501 |
char buff[256]; |
| 502 |
String str(buff,(uint32) sizeof(buff), system_charset_info); |
| 503 |
str.length(0); |
| 504 |
cond->print(&str, QT_ORDINARY); |
| 505 |
str.append("\0"); |
| 506 |
printf("COND* name=%s, type()=%s", cond->name, a_type[cond->type()]); |
| 507 |
if (cond->type() == Item::FUNC_ITEM) { |
| 508 |
Item_func *item = (Item_func*) cond; |
| 509 |
printf(", functype=%s", f_type[item->functype()]); |
| 510 |
} else if (cond->type() == Item::INT_ITEM) { |
| 511 |
Item_int *item = (Item_int*) cond; |
| 512 |
printf(", value=%d", item->value); |
| 513 |
} else if (cond->type() == Item::FIELD_ITEM) { |
| 514 |
} |
| 515 |
printf(", str=%s",str.ptr()); |
| 516 |
printf("\n"); |
| 517 |
if (cond->next != NULL) dump_condition(cond->next); |
| 518 |
return; |
| 519 |
} |
| 520 |
|
| 521 |
|
| 522 |
const COND* ha_tritonn::cond_push(const COND *cond) |
| 523 |
{ |
| 524 |
printf("===ha_tritonn::cond_push is called===\n"); |
| 525 |
Item *item = (Item*) cond; |
| 526 |
dump_condition(item); |
| 527 |
return cond; |
| 528 |
} |
| 529 |
|
| 530 |
static void dump_create(const char *name, TABLE *table_arg, |
| 531 |
HA_CREATE_INFO *create_info) |
| 532 |
{ |
| 533 |
int i; |
| 534 |
printf("===dump_create is called===\n"); |
| 535 |
printf("argments:: name=%s, table_arg=%p, create_info=%p\n",name,table_arg,create_info); |
| 536 |
printf("table_arg->s->table_name = %s\n",table_arg->s->table_name); |
| 537 |
printf("table_arg->s->db = %s\n", table_arg->s->db); |
| 538 |
printf("table_arg->s->path = %s\n", table_arg->s->path); |
| 539 |
printf("table_arg->s->fields = %d\n", table_arg->s->fields); |
| 540 |
printf("table_arg->s->keys = %d\n", table_arg->s->keys); |
| 541 |
printf("table_arg->s->primary_key = %d\n", table_arg->s->primary_key); |
| 542 |
printf("table_arg->s->row_type = %d\n", table_arg->s->row_type); |
| 543 |
printf("create_info->alias = %s\n", create_info->alias); |
| 544 |
printf("create_info->table_charset = %p\n", create_info->table_charset); |
| 545 |
printf("create_info->default_table_charset = %p\n", create_info->default_table_charset); |
| 546 |
printf("create_info->connect_string.str = %s\n",create_info->connect_string.str); |
| 547 |
printf("create_info->comment.str = %s\n", create_info->comment.str); |
| 548 |
|
| 549 |
for (i=0; i < table_arg->s->fieldnames.count; i++) { |
| 550 |
printf(" table_arg->s->fieldnames.type_names=%s\n", table_arg->s->fieldnames.type_names[i]); |
| 551 |
} |
| 552 |
for (i=0; i < table_arg->s->keynames.count; i++) { |
| 553 |
printf(" table_arg->s->keynames.type_names=%s\n", table_arg->s->keynames.type_names[i]); |
| 554 |
} |
| 555 |
|
| 556 |
for (i=0; i < table_arg->s->fields; i++) { |
| 557 |
Field *field = table_arg->s->field[i]; |
| 558 |
printf(" field=%p\n",field); |
| 559 |
printf(" field->field_name = %s\n", field->field_name); |
| 560 |
printf(" field->comment.str = %s\n", field->comment.str); |
| 561 |
printf(" field->field_length = %d\n", field->field_length); |
| 562 |
printf(" field->unireg_chekc = %d\n", field->unireg_check); |
| 563 |
printf(" field->flags = %d\n", field->flags); |
| 564 |
printf(" field->field_index = %d\n", field->field_index); |
| 565 |
printf(" field->type() = %d\n", field->type()); |
| 566 |
printf(" field->result_type() = %d\n", field->result_type()); |
| 567 |
} |
| 568 |
|
| 569 |
int keys = table_arg->s->keys; |
| 570 |
for (i=0; i < keys; i++) { |
| 571 |
KEY *key = table_arg->key_info+i; |
| 572 |
printf(" key=%p\n",key); |
| 573 |
printf(" key->name = %s\n", key->name); |
| 574 |
printf(" key->algorithm = %d\n", key->algorithm); |
| 575 |
printf(" key->key_parts = %d\n", key->key_parts); |
| 576 |
int j; |
| 577 |
for (j=0; j < key->key_parts; j++) { |
| 578 |
KEY_PART_INFO *part = key->key_part+j; |
| 579 |
printf(" part=%p\n",part); |
| 580 |
printf(" part->fieldnr=%d\n",part->fieldnr); |
| 581 |
printf(" part->field->field_name=%s\n",part->field->field_name); |
| 582 |
printf(" part->field->comment.str=%s\n",part->field->comment.str); |
| 583 |
} |
| 584 |
} |
| 585 |
} |
| 586 |
|
| 587 |
void call_senna_ql(sen_ctx *ctx, const char *str, bool disp) |
| 588 |
{ |
| 589 |
char *ql; |
| 590 |
char *res; |
| 591 |
unsigned int res_len; |
| 592 |
int res_flags; |
| 593 |
char *buf; |
| 594 |
unsigned int ql_len = strlen(str); |
| 595 |
ql = (char*) malloc(ql_len); |
| 596 |
strncpy(ql,str,ql_len); |
| 597 |
sen_ctx_send(ctx,ql,ql_len,0); |
| 598 |
if (disp == true) { |
| 599 |
do { |
| 600 |
sen_ctx_recv(ctx,&res,&res_len,&res_flags); |
| 601 |
buf = (char*) calloc(1,1024); |
| 602 |
printf("[SennaQL] %s => %s\n",str,strncat(buf,res,res_len)); |
| 603 |
free(buf); |
| 604 |
} while (res_flags & SEN_CTX_MORE); |
| 605 |
} |
| 606 |
free(ql); |
| 607 |
} |
| 608 |
|
| 609 |
static char *mysqltype2sennatype_string(enum_field_types types) |
| 610 |
{ |
| 611 |
switch(types) { |
| 612 |
case MYSQL_TYPE_TINY: |
| 613 |
case MYSQL_TYPE_SHORT: |
| 614 |
case MYSQL_TYPE_INT24: |
| 615 |
case MYSQL_TYPE_LONG: |
| 616 |
return "int"; |
| 617 |
case MYSQL_TYPE_FLOAT: |
| 618 |
case MYSQL_TYPE_DOUBLE: |
| 619 |
return "float"; |
| 620 |
case MYSQL_TYPE_STRING: |
| 621 |
case MYSQL_TYPE_VAR_STRING: |
| 622 |
case MYSQL_TYPE_VARCHAR: |
| 623 |
case MYSQL_TYPE_BLOB: |
| 624 |
return "text"; |
| 625 |
default: |
| 626 |
return "null"; |
| 627 |
} |
| 628 |
} |
| 629 |
|
| 630 |
const char* tritonn_escape_string(const char* str){ |
| 631 |
int i,len,cnt,offset; |
| 632 |
for (i=0,len=strlen(str),cnt=0; i<len; i++) { |
| 633 |
if (*(str+i) == '\\' || *(str+i) == '"') cnt++; |
| 634 |
} |
| 635 |
if (cnt == 0) return str; |
| 636 |
char *res = (char*) sql_alloc(len+cnt); |
| 637 |
for (i=0,offset=0; i<len; i++) { |
| 638 |
if (*(str+i) == '\\') { |
| 639 |
*(res+i+offset) = '\\'; |
| 640 |
offset++; |
| 641 |
*(res+i+offset) = '\\'; |
| 642 |
} else if (*(str+i) == '"') { |
| 643 |
*(res+i+offset) = '\\'; |
| 644 |
offset++; |
| 645 |
*(res+i+offset) = '"'; |
| 646 |
} else { |
| 647 |
*(res+i+offset) = *(str+i); |
| 648 |
} |
| 649 |
} |
| 650 |
return res; |
| 651 |
} |
| 652 |
|
| 653 |
int ha_tritonn::write_row(uchar* buf) |
| 654 |
{ |
| 655 |
DBTN; |
| 656 |
int i=0; |
| 657 |
char ql[1024]; |
| 658 |
char* pkey; |
| 659 |
for (Field **field=table->field; *field; field++) { |
| 660 |
String str; |
| 661 |
(*field)->val_str(&str); |
| 662 |
str.chop(); |
| 663 |
if (i==0) { |
| 664 |
pkey = (char*) sql_alloc(strlen(str.ptr())); |
| 665 |
strcpy(pkey,str.ptr()); |
| 666 |
my_snprintf(ql,1024,"(<%s> ::new \"%s\")",share->short_name, |
| 667 |
tritonn_escape_string(str.ptr())); |
| 668 |
} else { |
| 669 |
my_snprintf(ql,1024,"((<%s> : \"%s\") :%s \"%s\")", |
| 670 |
share->short_name, |
| 671 |
tritonn_escape_string(pkey), (*field)->field_name, |
| 672 |
tritonn_escape_string(str.ptr())); |
| 673 |
} |
| 674 |
call_senna_ql(ctx,ql); |
| 675 |
i++; |
| 676 |
} |
| 677 |
return 0; |
| 678 |
} |
| 679 |
|
| 680 |
TRITONN_DB *open_or_create_db(const char *db_name) |
| 681 |
{ |
| 682 |
char file_name[FN_REFLEN]; |
| 683 |
TRITONN_DB *d = (TRITONN_DB*) my_malloc(sizeof(TRITONN_DB), MYF(0)); |
| 684 |
d->db_name_length = strlen(db_name); |
| 685 |
d->db_name = (char*) my_malloc(d->db_name_length,MYF(0)); |
| 686 |
memcpy(d->db_name,db_name,d->db_name_length); |
| 687 |
my_snprintf(file_name,FN_REFLEN,"%s/tritonn.db",db_name); |
| 688 |
d->db = sen_db_open(file_name); |
| 689 |
if (d->db == NULL) { |
| 690 |
d->db = sen_db_create(file_name,0,sen_enc_utf8); |
| 691 |
} |
| 692 |
d->next = NULL; |
| 693 |
pthread_mutex_unlock(&tritonn_mutex); |
| 694 |
return d; |
| 695 |
} |
| 696 |
|
| 697 |
sen_db *get_sen_db(const char *db_name) |
| 698 |
{ |
| 699 |
pthread_mutex_lock(&tritonn_mutex); |
| 700 |
/* case1: no instance created yet */ |
| 701 |
if (tdb == NULL) { |
| 702 |
tdb = open_or_create_db(db_name); |
| 703 |
pthread_mutex_unlock(&tritonn_mutex); |
| 704 |
return tdb->db; |
| 705 |
} |
| 706 |
/* case2: instance hit */ |
| 707 |
TRITONN_DB *cur = tdb; |
| 708 |
while (true) { |
| 709 |
if (strcmp(cur->db_name,db_name) == 0) { |
| 710 |
pthread_mutex_unlock(&tritonn_mutex); |
| 711 |
return cur->db; |
| 712 |
} else if (cur->next != NULL) { |
| 713 |
cur = cur->next; |
| 714 |
} else { |
| 715 |
break; |
| 716 |
} |
| 717 |
} |
| 718 |
/* case3: instance not hit */ |
| 719 |
cur->next = open_or_create_db(db_name); |
| 720 |
pthread_mutex_unlock(&tritonn_mutex); |
| 721 |
return cur->next->db; |
| 722 |
} |
| 723 |
|