101
101
#include "haildb_engine.h"
103
103
#include <drizzled/field.h>
104
#include "drizzled/field/timestamp.h" // needed for UPDATE NOW()
105
104
#include "drizzled/field/blob.h"
106
105
#include "drizzled/field/enum.h"
107
106
#include <drizzled/session.h>
117
116
using namespace google;
118
117
using namespace drizzled;
120
int read_row_from_haildb(unsigned char* buf, ib_crsr_t cursor, ib_tpl_t tuple, Table* table, bool has_hidden_primary_key, uint64_t *hidden_pkey, drizzled::memory::Root **blobroot= NULL);
119
int read_row_from_haildb(Session *session, unsigned char* buf, ib_crsr_t cursor, ib_tpl_t tuple, Table* table, bool has_hidden_primary_key, uint64_t *hidden_pkey, drizzled::memory::Root **blobroot= NULL);
121
120
static void fill_ib_search_tpl_from_drizzle_key(ib_tpl_t search_tuple,
122
121
const drizzled::KeyInfo *key_info,
123
122
const unsigned char *key_ptr,
167
166
int doCreateTable(Session&,
168
167
Table& table_arg,
169
const drizzled::TableIdentifier &identifier,
168
const drizzled::identifier::Table &identifier,
170
169
drizzled::message::Table& proto);
172
int doDropTable(Session&, const TableIdentifier &identifier);
171
int doDropTable(Session&, const identifier::Table &identifier);
174
173
int doRenameTable(drizzled::Session&,
175
const drizzled::TableIdentifier&,
176
const drizzled::TableIdentifier&);
174
const drizzled::identifier::Table&,
175
const drizzled::identifier::Table&);
178
177
int doGetTableDefinition(Session& session,
179
const TableIdentifier &identifier,
178
const identifier::Table &identifier,
180
179
drizzled::message::Table &table_proto);
182
bool doDoesTableExist(Session&, const TableIdentifier &identifier);
181
bool doDoesTableExist(Session&, const identifier::Table &identifier);
185
void getTableNamesInSchemaFromHailDB(const drizzled::SchemaIdentifier &schema,
184
void getTableNamesInSchemaFromHailDB(const drizzled::identifier::Schema &schema,
186
185
drizzled::plugin::TableNameList *set_of_names,
187
drizzled::TableIdentifier::vector *identifiers);
186
drizzled::identifier::Table::vector *identifiers);
190
189
void doGetTableIdentifiers(drizzled::CachedDirectory &,
191
const drizzled::SchemaIdentifier &schema,
192
drizzled::TableIdentifier::vector &identifiers);
190
const drizzled::identifier::Schema &schema,
191
drizzled::identifier::Table::vector &identifiers);
194
193
/* The following defines can be increased if necessary */
195
194
uint32_t max_supported_keys() const { return 1000; }
240
239
/* This is a superset of the map from innobase plugin.
241
240
Unlike innobase plugin we don't act on errors here, we just
242
241
map error codes. */
243
static int ib_err_t_to_drizzle_error(ib_err_t err)
242
static int ib_err_t_to_drizzle_error(Session* session, ib_err_t err)
270
269
return HA_ERR_NO_ACTIVE_RECORD;
272
271
case DB_DEADLOCK:
272
/* HailDB will roll back a transaction itself due to DB_DEADLOCK.
273
This means we have to tell Drizzle about it */
274
mark_transaction_to_rollback(session, true);
273
275
return HA_ERR_LOCK_DEADLOCK;
275
277
case DB_LOCK_WAIT_TIMEOUT:
388
390
err= ib_savepoint_rollback(*transaction, savepoint.getName().c_str(),
389
391
savepoint.getName().length());
391
return ib_err_t_to_drizzle_error(err);
393
return ib_err_t_to_drizzle_error(session, err);
394
396
int HailDBEngine::doReleaseSavepoint(Session* session,
400
402
err= ib_savepoint_release(*transaction, savepoint.getName().c_str(),
401
403
savepoint.getName().length());
402
404
if (err != DB_SUCCESS)
403
return ib_err_t_to_drizzle_error(err);
405
return ib_err_t_to_drizzle_error(session, err);
411
413
ib_trx_t *transaction= get_trx(session);
413
if (all || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
415
417
err= ib_trx_commit(*transaction);
417
419
if (err != DB_SUCCESS)
418
return ib_err_t_to_drizzle_error(err);
420
return ib_err_t_to_drizzle_error(session, err);
420
422
*transaction= NULL;
429
431
ib_trx_t *transaction= get_trx(session);
431
if (all || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
433
err= ib_trx_rollback(*transaction);
435
if (ib_trx_state(*transaction) == IB_TRX_NOT_STARTED)
436
err= ib_trx_release(*transaction);
438
err= ib_trx_rollback(*transaction);
435
440
if (err != DB_SUCCESS)
436
return ib_err_t_to_drizzle_error(err);
441
return ib_err_t_to_drizzle_error(session, err);
438
443
*transaction= NULL;
447
if (ib_trx_state(*transaction) == IB_TRX_NOT_STARTED)
442
450
err= ib_savepoint_rollback(*transaction, statement_savepoint_name.c_str(),
443
451
statement_savepoint_name.length());
444
452
if (err != DB_SUCCESS)
445
return ib_err_t_to_drizzle_error(err);
453
return ib_err_t_to_drizzle_error(session, err);
488
496
assert (err == DB_SUCCESS);
489
err= ib_tuple_read_u64(tuple, getTable()->getShare()->fields, &nr);
497
err= ib_tuple_read_u64(tuple, getTable()->getShare()->sizeFields(), &nr);
492
500
ib_tuple_delete(tuple);
795
static void TableIdentifier_to_haildb_name(const TableIdentifier &identifier, std::string *str)
803
static void TableIdentifier_to_haildb_name(const identifier::Table &identifier, std::string *str)
797
805
str->assign(table_path_to_haildb_name(identifier.getPath().c_str()));
828
836
if (err != DB_SUCCESS)
829
return ib_err_t_to_drizzle_error(err);
837
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
831
839
err= ib_cursor_open_table_using_id(table_id, NULL, &cursor);
832
840
cursor_is_sec_index= false;
834
842
if (err != DB_SUCCESS)
835
return ib_err_t_to_drizzle_error(err);
843
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
837
845
err= ib_index_get_id(haildb_table_name, "HIDDEN_PRIMARY", &idx_id);
927
935
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
928
936
column_attr, 0, 4);
930
case message::Table::Field::TIMESTAMP:
938
case message::Table::Field::EPOCH:
931
939
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
932
940
column_attr, 0, 8);
1028
1036
int HailDBEngine::doCreateTable(Session &session,
1029
1037
Table& table_obj,
1030
const drizzled::TableIdentifier &identifier,
1038
const drizzled::identifier::Table &identifier,
1031
1039
drizzled::message::Table& table_message)
1033
1041
ib_tbl_sch_t haildb_table_schema= NULL;
1071
1079
ER_CANT_CREATE_TABLE,
1072
1080
_("Cannot create table %s. HailDB Error %d (%s)\n"),
1073
1081
haildb_table_name.c_str(), haildb_err, ib_strerror(haildb_err));
1074
return ib_err_t_to_drizzle_error(haildb_err);
1082
return ib_err_t_to_drizzle_error(&session, haildb_err);
1077
1085
for (int colnr= 0; colnr < table_message.field_size() ; colnr++)
1092
1100
" HailDB Error %d (%s)\n"),
1093
1101
field.name().c_str(), haildb_table_name.c_str(),
1094
1102
haildb_err, ib_strerror(haildb_err));
1095
return ib_err_t_to_drizzle_error(haildb_err);
1103
return ib_err_t_to_drizzle_error(&session, haildb_err);
1097
1105
if (field_err != 0)
1098
1106
return field_err;
1240
1248
_("Cannot create table %s. HailDB Error %d (%s)\n"),
1241
1249
haildb_table_name.c_str(),
1242
1250
haildb_err, ib_strerror(haildb_err));
1243
return ib_err_t_to_drizzle_error(haildb_err);
1251
return ib_err_t_to_drizzle_error(&session, haildb_err);
1285
1293
int HailDBEngine::doDropTable(Session &session,
1286
const TableIdentifier &identifier)
1294
const identifier::Table &identifier)
1288
1296
ib_trx_t haildb_schema_transaction;
1289
1297
ib_err_t haildb_err;
1368
static ib_err_t rename_table_message(ib_trx_t transaction, const TableIdentifier &from_identifier, const TableIdentifier &to_identifier)
1376
static ib_err_t rename_table_message(ib_trx_t transaction, const identifier::Table &from_identifier, const identifier::Table &to_identifier)
1370
1378
ib_crsr_t cursor;
1371
1379
ib_tpl_t search_tuple;
1458
1466
int HailDBEngine::doRenameTable(drizzled::Session &session,
1459
const drizzled::TableIdentifier &from,
1460
const drizzled::TableIdentifier &to)
1467
const drizzled::identifier::Table &from,
1468
const drizzled::identifier::Table &to)
1462
1470
ib_trx_t haildb_schema_transaction;
1507
1515
assert(rollback_err == DB_SUCCESS);
1508
1516
rollback_err= ib_trx_rollback(haildb_schema_transaction);
1509
1517
assert(rollback_err == DB_SUCCESS);
1510
return ib_err_t_to_drizzle_error(err);
1518
return ib_err_t_to_drizzle_error(&session, err);
1513
1521
void HailDBEngine::getTableNamesInSchemaFromHailDB(
1514
const drizzled::SchemaIdentifier &schema,
1522
const drizzled::identifier::Schema &schema,
1515
1523
drizzled::plugin::TableNameList *set_of_names,
1516
drizzled::TableIdentifier::vector *identifiers)
1524
drizzled::identifier::Table::vector *identifiers)
1518
1526
ib_trx_t transaction;
1519
1527
ib_crsr_t cursor;
1544
1552
BOOST_FOREACH(std::string table_name, haildb_system_table_names)
1546
identifiers->push_back(TableIdentifier(schema.getSchemaName(),
1554
identifiers->push_back(identifier::Table(schema.getSchemaName(),
1607
1615
void HailDBEngine::doGetTableIdentifiers(drizzled::CachedDirectory &,
1608
const drizzled::SchemaIdentifier &schema,
1609
drizzled::TableIdentifier::vector &identifiers)
1616
const drizzled::identifier::Schema &schema,
1617
drizzled::identifier::Table::vector &identifiers)
1611
1619
getTableNamesInSchemaFromHailDB(schema, NULL, &identifiers);
1733
1741
int HailDBEngine::doGetTableDefinition(Session &session,
1734
const TableIdentifier &identifier,
1742
const identifier::Table &identifier,
1735
1743
drizzled::message::Table &table)
1737
1745
ib_crsr_t haildb_cursor= NULL;
1762
1770
bool HailDBEngine::doDoesTableExist(Session &,
1763
const TableIdentifier& identifier)
1771
const identifier::Table& identifier)
1765
1773
ib_crsr_t haildb_cursor;
1766
1774
string haildb_table_name;
1902
1910
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
1904
1912
if (err != DB_SUCCESS)
1905
return ib_err_t_to_drizzle_error(err);
1913
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
1907
1915
cursor_is_sec_index= false;
1973
1981
if (share->has_hidden_primary_key)
1975
err= ib_tuple_write_u64(tuple, getTable()->getShare()->fields, share->hidden_pkey_auto_increment_value.fetch_and_increment());
1983
err= ib_tuple_write_u64(tuple, getTable()->getShare()->sizeFields(),
1984
share->hidden_pkey_auto_increment_value.fetch_and_increment());
1978
1987
err= ib_cursor_insert_row(cursor, tuple);
2010
2019
ret= HA_ERR_FOUND_DUPP_KEY;
2012
2021
else if (err != DB_SUCCESS)
2013
ret= ib_err_t_to_drizzle_error(err);
2022
ret= ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2015
2024
tuple= ib_tuple_clear(tuple);
2016
2025
ib_tuple_delete(tuple);
2041
2050
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2043
2052
if (err != DB_SUCCESS)
2044
return ib_err_t_to_drizzle_error(err);
2053
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2045
2054
cursor_is_sec_index= false;
2130
2139
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2132
2141
if (err != DB_SUCCESS)
2133
return ib_err_t_to_drizzle_error(err);
2142
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2134
2143
cursor_is_sec_index= false;
2172
2181
ib_schema_unlock(transaction);
2173
2182
ib_err_t rollback_err= ib_trx_rollback(transaction);
2174
2183
assert(rollback_err == DB_SUCCESS);
2175
return ib_err_t_to_drizzle_error(err);
2184
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2178
2187
int HailDBCursor::doStartTableScan(bool)
2204
2213
if (err != DB_SUCCESS)
2205
return ib_err_t_to_drizzle_error(err);
2214
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2207
2216
err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
2208
2217
assert(err == DB_SUCCESS); // FIXME
2212
2221
err= ib_cursor_first(cursor);
2213
2222
if (err != DB_SUCCESS && err != DB_END_OF_INDEX)
2215
previous_error= ib_err_t_to_drizzle_error(err);
2216
err= ib_cursor_reset(cursor);
2217
return previous_error;
2224
int reset_err= ib_cursor_reset(cursor);
2225
assert(reset_err == DB_SUCCESS);
2226
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2220
2229
advance_cursor= false;
2226
int read_row_from_haildb(unsigned char* buf, ib_crsr_t cursor, ib_tpl_t tuple, Table* table, bool has_hidden_primary_key, uint64_t *hidden_pkey, drizzled::memory::Root **blobroot)
2234
int read_row_from_haildb(Session *session, unsigned char* buf, ib_crsr_t cursor, ib_tpl_t tuple, Table* table, bool has_hidden_primary_key, uint64_t *hidden_pkey, drizzled::memory::Root **blobroot)
2229
2237
ptrdiff_t row_offset= buf - table->getInsertRecord();
2233
2241
if (err == DB_RECORD_NOT_FOUND)
2234
2242
return HA_ERR_END_OF_FILE;
2235
2243
if (err != DB_SUCCESS)
2236
return ib_err_t_to_drizzle_error(err);
2244
return ib_err_t_to_drizzle_error(session, err);
2299
2307
(**field).move_field_offset(-row_offset);
2301
2309
if (err != DB_SUCCESS)
2302
return ib_err_t_to_drizzle_error(err);
2310
return ib_err_t_to_drizzle_error(session, err);
2305
2313
if (has_hidden_primary_key)
2307
2315
err= ib_tuple_read_u64(tuple, colnr, hidden_pkey);
2310
return ib_err_t_to_drizzle_error(err);
2318
return ib_err_t_to_drizzle_error(session, err);
2313
2321
int HailDBCursor::rnd_next(unsigned char *buf)
2319
return previous_error;
2321
2326
if (advance_cursor)
2323
2328
err= ib_cursor_next(cursor);
2324
2329
if (err != DB_SUCCESS)
2325
return ib_err_t_to_drizzle_error(err);
2330
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2328
2333
tuple= ib_tuple_clear(tuple);
2329
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2334
ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2330
2336
share->has_hidden_primary_key,
2331
2337
&hidden_autoinc_pkey_position);
2343
2349
err= ib_cursor_reset(cursor);
2344
2350
assert(err == DB_SUCCESS);
2345
2351
in_table_scan= false;
2347
return ib_err_t_to_drizzle_error(err);
2352
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2350
2355
int HailDBCursor::rnd_pos(unsigned char *buf, unsigned char *pos)
2359
2364
err= ib_col_set_value(search_tuple, 0,
2360
2365
((uint64_t*)(pos)), sizeof(uint64_t));
2361
2366
if (err != DB_SUCCESS)
2362
return ib_err_t_to_drizzle_error(err);
2367
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2377
2382
err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
2378
2383
if (err != DB_SUCCESS)
2379
return ib_err_t_to_drizzle_error(err);
2384
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2381
2386
assert(res==0);
2387
2392
tuple= ib_tuple_clear(tuple);
2390
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2395
ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2391
2397
share->has_hidden_primary_key,
2392
2398
&hidden_autoinc_pkey_position);
2535
if (flag & HA_STATUS_CONST)
2537
for (unsigned int i = 0; i < getTable()->getShare()->sizeKeys(); i++)
2539
const char* index_name= getTable()->key_info[i].name;
2542
ha_rows rec_per_key;
2544
err= ib_get_index_stat_n_diff_key_vals(cursor, index_name,
2547
if (err != DB_SUCCESS)
2548
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2550
for (unsigned int j=0; j < getTable()->key_info[i].key_parts; j++)
2552
if (n_diff[j+1] == 0)
2553
rec_per_key= stats.records;
2555
rec_per_key= stats.records / n_diff[j+1];
2557
/* We import this heuristic from ha_innodb, which says
2558
that MySQL favours table scans too much over index searches,
2559
so we pretend our index selectivity is 2 times better. */
2561
rec_per_key= rec_per_key / 2;
2563
if (rec_per_key == 0)
2566
getTable()->key_info[i].rec_per_key[j]=
2567
rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
2568
(ulong) rec_per_key;
2546
2592
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2548
2594
if (err != DB_SUCCESS)
2549
return ib_err_t_to_drizzle_error(err);
2595
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2564
2610
getShare()->getKeyInfo(keynr).name,
2566
2612
if (err != DB_SUCCESS)
2567
return ib_err_t_to_drizzle_error(err);
2613
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2569
2615
err= ib_cursor_close(cursor);
2570
2616
assert(err == DB_SUCCESS);
2572
2618
err= ib_cursor_open_index_using_id(index_id, transaction, &cursor);
2574
2620
if (err != DB_SUCCESS)
2575
return ib_err_t_to_drizzle_error(err);
2621
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2577
2623
cursor_is_sec_index= true;
2726
2772
if (err != DB_SUCCESS)
2728
return ib_err_t_to_drizzle_error(err);
2774
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2731
2777
tuple= ib_tuple_clear(tuple);
2732
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2778
ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2733
2780
share->has_hidden_primary_key,
2734
2781
&hidden_autoinc_pkey_position,
2735
2782
(allocate_blobs)? &blobroot : NULL);
2856
int HailDBCursor::analyze(Session*)
2860
err= ib_update_table_statistics(cursor);
2862
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2809
2865
int HailDBCursor::index_next(unsigned char *buf)
2811
2867
int ret= HA_ERR_END_OF_FILE;
2820
2876
tuple= ib_tuple_clear(tuple);
2821
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2877
ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2822
2879
share->has_hidden_primary_key,
2823
2880
&hidden_autoinc_pkey_position);
2846
2903
if (err == DB_END_OF_INDEX)
2847
2904
return HA_ERR_END_OF_FILE;
2849
return ib_err_t_to_drizzle_error(err);
2906
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2853
2910
tuple= ib_tuple_clear(tuple);
2854
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2911
ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2855
2913
share->has_hidden_primary_key,
2856
2914
&hidden_autoinc_pkey_position);
2869
2927
err= ib_cursor_first(cursor);
2870
2928
if (err != DB_SUCCESS)
2871
return ib_err_t_to_drizzle_error(err);
2929
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2873
2931
tuple= ib_tuple_clear(tuple);
2874
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2932
ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2875
2934
share->has_hidden_primary_key,
2876
2935
&hidden_autoinc_pkey_position);
2889
2948
err= ib_cursor_last(cursor);
2890
2949
if (err != DB_SUCCESS)
2891
return ib_err_t_to_drizzle_error(err);
2950
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2893
2952
tuple= ib_tuple_clear(tuple);
2894
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2953
ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2895
2955
share->has_hidden_primary_key,
2896
2956
&hidden_autoinc_pkey_position);
2897
2957
advance_cursor= true;