2
Copyright (C) 2010 Stewart Smith
4
This program is free software; you can redistribute it and/or
5
modify it under the terms of the GNU General Public License
6
as published by the Free Software Foundation; either version 2
7
of the License, or (at your option) any later version.
9
This program is distributed in the hope that it will be useful,
10
but WITHOUT ANY WARRANTY; without even the implied warranty of
11
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
GNU General Public License for more details.
14
You should have received a copy of the GNU General Public License
15
along with this program; if not, write to the Free Software
16
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
/* innobase_get_int_col_max_value() comes from ha_innodb.cc which is under
20
the following license and Copyright */
22
/*****************************************************************************
24
Copyright (c) 2000, 2009, MySQL AB & Innobase Oy. All Rights Reserved.
25
Copyright (c) 2008, 2009 Google Inc.
27
Portions of this file contain modifications contributed and copyrighted by
28
Google, Inc. Those modifications are gratefully acknowledged and are described
29
briefly in the InnoDB documentation. The contributions by Google are
30
incorporated with their permission, and subject to the conditions contained in
31
the file COPYING.Google.
33
This program is free software; you can redistribute it and/or modify it under
34
the terms of the GNU General Public License as published by the Free Software
35
Foundation; version 2 of the License.
37
This program is distributed in the hope that it will be useful, but WITHOUT
38
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
39
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
41
You should have received a copy of the GNU General Public License along with
42
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
43
St, Fifth Floor, Boston, MA 02110-1301 USA
45
*****************************************************************************/
46
/***********************************************************************
48
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
49
Copyright (c) 2009, Percona Inc.
51
Portions of this file contain modifications contributed and copyrighted
52
by Percona Inc.. Those modifications are
53
gratefully acknowledged and are described briefly in the InnoDB
54
documentation. The contributions by Percona Inc. are incorporated with
55
their permission, and subject to the conditions contained in the file
58
This program is free software; you can redistribute it and/or modify it
59
under the terms of the GNU General Public License as published by the
60
Free Software Foundation; version 2 of the License.
62
This program is distributed in the hope that it will be useful, but
63
WITHOUT ANY WARRANTY; without even the implied warranty of
64
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
65
Public License for more details.
67
You should have received a copy of the GNU General Public License along
68
with this program; if not, write to the Free Software Foundation, Inc.,
69
51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
71
***********************************************************************/
75
#include <drizzled/table.h>
76
#include <drizzled/error.h>
77
#include "drizzled/internal/my_pthread.h"
78
#include <drizzled/plugin/transactional_storage_engine.h>
79
#include <drizzled/plugin/error_message.h>
85
#include <boost/algorithm/string.hpp>
86
#include <boost/unordered_set.hpp>
87
#include <boost/foreach.hpp>
90
#include <drizzled/message/table.pb.h>
91
#include "drizzled/internal/m_string.h"
93
#include "drizzled/global_charset_info.h"
95
#include "haildb_datadict_dump_func.h"
96
#include "config_table_function.h"
97
#include "status_table_function.h"
101
#include "haildb_engine.h"
103
#include <drizzled/field.h>
104
#include "drizzled/field/timestamp.h" // needed for UPDATE NOW()
105
#include "drizzled/field/blob.h"
106
#include "drizzled/field/enum.h"
107
#include <drizzled/session.h>
108
#include <boost/program_options.hpp>
109
#include <drizzled/module/option_map.h>
111
#include <drizzled/charset.h>
113
namespace po= boost::program_options;
114
#include <boost/algorithm/string.hpp>
117
using namespace google;
118
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);
121
static void fill_ib_search_tpl_from_drizzle_key(ib_tpl_t search_tuple,
122
const drizzled::KeyInfo *key_info,
123
const unsigned char *key_ptr,
125
static void store_key_value_from_haildb(KeyInfo *key_info, unsigned char* ref, int ref_len, const unsigned char *record);
127
#define HAILDB_EXT ".EID"
129
const char HAILDB_TABLE_DEFINITIONS_TABLE[]= "data_dictionary/haildb_table_definitions";
130
const string statement_savepoint_name("STATEMENT");
132
static boost::unordered_set<std::string> haildb_system_table_names;
135
static const char *HailDBCursor_exts[] = {
139
class HailDBEngine : public drizzled::plugin::TransactionalStorageEngine
142
HailDBEngine(const string &name_arg)
143
: drizzled::plugin::TransactionalStorageEngine(name_arg,
145
HTON_CAN_INDEX_BLOBS |
147
HTON_PARTIAL_COLUMN_READ |
148
HTON_HAS_DOES_TRANSACTIONS)
150
table_definition_ext= HAILDB_EXT;
155
virtual Cursor *create(Table &table)
157
return new HailDBCursor(*this, table);
160
const char **bas_ext() const {
161
return HailDBCursor_exts;
164
bool validateCreateTableOption(const std::string &key,
165
const std::string &state);
167
int doCreateTable(Session&,
169
const drizzled::TableIdentifier &identifier,
170
drizzled::message::Table& proto);
172
int doDropTable(Session&, const TableIdentifier &identifier);
174
int doRenameTable(drizzled::Session&,
175
const drizzled::TableIdentifier&,
176
const drizzled::TableIdentifier&);
178
int doGetTableDefinition(Session& session,
179
const TableIdentifier &identifier,
180
drizzled::message::Table &table_proto);
182
bool doDoesTableExist(Session&, const TableIdentifier &identifier);
185
void getTableNamesInSchemaFromHailDB(const drizzled::SchemaIdentifier &schema,
186
drizzled::plugin::TableNameList *set_of_names,
187
drizzled::TableIdentifier::vector *identifiers);
190
void doGetTableIdentifiers(drizzled::CachedDirectory &,
191
const drizzled::SchemaIdentifier &schema,
192
drizzled::TableIdentifier::vector &identifiers);
194
/* The following defines can be increased if necessary */
195
uint32_t max_supported_keys() const { return 1000; }
196
uint32_t max_supported_key_length() const { return 3500; }
197
uint32_t max_supported_key_part_length() const { return 767; }
199
uint32_t index_flags(enum ha_key_alg) const
201
return (HA_READ_NEXT |
207
virtual int doStartTransaction(Session *session,
208
start_transaction_option_t options);
209
virtual void doStartStatement(Session *session);
210
virtual void doEndStatement(Session *session);
212
virtual int doSetSavepoint(Session* session,
213
drizzled::NamedSavepoint &savepoint);
214
virtual int doRollbackToSavepoint(Session* session,
215
drizzled::NamedSavepoint &savepoint);
216
virtual int doReleaseSavepoint(Session* session,
217
drizzled::NamedSavepoint &savepoint);
218
virtual int doCommit(Session* session, bool all);
219
virtual int doRollback(Session* session, bool all);
221
typedef std::map<std::string, HailDBTableShare*> HailDBMap;
222
HailDBMap haildb_open_tables;
223
HailDBTableShare *findOpenTable(const std::string table_name);
224
void addOpenTable(const std::string &table_name, HailDBTableShare *);
225
void deleteOpenTable(const std::string &table_name);
227
uint64_t getInitialAutoIncrementValue(HailDBCursor *cursor);
228
uint64_t getHiddenPrimaryKeyInitialAutoIncrementValue(HailDBCursor *cursor);
232
static drizzled::plugin::StorageEngine *haildb_engine= NULL;
235
static ib_trx_t* get_trx(Session* session)
237
return (ib_trx_t*) session->getEngineData(haildb_engine);
240
/* This is a superset of the map from innobase plugin.
241
Unlike innobase plugin we don't act on errors here, we just
243
static int ib_err_t_to_drizzle_error(ib_err_t err)
255
return ER_QUERY_INTERRUPTED; // FIXME: is this correct?
257
case DB_OUT_OF_MEMORY:
258
return HA_ERR_OUT_OF_MEM;
260
case DB_DUPLICATE_KEY:
261
return HA_ERR_FOUND_DUPP_KEY;
263
case DB_FOREIGN_DUPLICATE_KEY:
264
return HA_ERR_FOREIGN_DUPLICATE_KEY;
266
case DB_MISSING_HISTORY:
267
return HA_ERR_TABLE_DEF_CHANGED;
269
case DB_RECORD_NOT_FOUND:
270
return HA_ERR_NO_ACTIVE_RECORD;
273
return HA_ERR_LOCK_DEADLOCK;
275
case DB_LOCK_WAIT_TIMEOUT:
276
return HA_ERR_LOCK_WAIT_TIMEOUT;
278
case DB_NO_REFERENCED_ROW:
279
return HA_ERR_NO_REFERENCED_ROW;
281
case DB_ROW_IS_REFERENCED:
282
return HA_ERR_ROW_IS_REFERENCED;
284
case DB_CANNOT_ADD_CONSTRAINT:
285
return HA_ERR_CANNOT_ADD_FOREIGN;
287
case DB_CANNOT_DROP_CONSTRAINT:
288
return HA_ERR_ROW_IS_REFERENCED; /* misleading. should have new err code */
290
case DB_COL_APPEARS_TWICE_IN_INDEX:
292
return HA_ERR_CRASHED;
294
case DB_MUST_GET_MORE_FILE_SPACE:
295
case DB_OUT_OF_FILE_SPACE:
296
return HA_ERR_RECORD_FILE_FULL;
298
case DB_TABLE_IS_BEING_USED:
299
return HA_ERR_WRONG_COMMAND;
301
case DB_TABLE_NOT_FOUND:
302
return HA_ERR_NO_SUCH_TABLE;
304
case DB_TOO_BIG_RECORD:
305
return HA_ERR_TO_BIG_ROW;
307
case DB_NO_SAVEPOINT:
308
return HA_ERR_NO_SAVEPOINT;
310
case DB_LOCK_TABLE_FULL:
311
return HA_ERR_LOCK_TABLE_FULL;
313
case DB_PRIMARY_KEY_IS_NULL:
314
return ER_PRIMARY_CANT_HAVE_NULL;
316
case DB_TOO_MANY_CONCURRENT_TRXS:
317
return HA_ERR_RECORD_FILE_FULL; /* need better error code */
319
case DB_END_OF_INDEX:
320
return HA_ERR_END_OF_FILE;
323
return HA_ERR_UNSUPPORTED;
327
static ib_trx_level_t tx_isolation_to_ib_trx_level(enum_tx_isolation level)
331
case ISO_REPEATABLE_READ:
332
return IB_TRX_REPEATABLE_READ;
333
case ISO_READ_COMMITTED:
334
return IB_TRX_READ_COMMITTED;
335
case ISO_SERIALIZABLE:
336
return IB_TRX_SERIALIZABLE;
337
case ISO_READ_UNCOMMITTED:
338
return IB_TRX_READ_UNCOMMITTED;
342
return IB_TRX_REPEATABLE_READ;
345
int HailDBEngine::doStartTransaction(Session *session,
346
start_transaction_option_t options)
348
ib_trx_t *transaction;
349
ib_trx_level_t isolation_level;
353
transaction= get_trx(session);
354
isolation_level= tx_isolation_to_ib_trx_level((enum_tx_isolation)session_tx_isolation(session));
355
*transaction= ib_trx_begin(isolation_level);
357
return *transaction == NULL;
360
void HailDBEngine::doStartStatement(Session *session)
362
if(*get_trx(session) == NULL)
363
doStartTransaction(session, START_TRANS_NO_OPTIONS);
365
ib_savepoint_take(*get_trx(session), statement_savepoint_name.c_str(),
366
statement_savepoint_name.length());
369
void HailDBEngine::doEndStatement(Session *)
373
int HailDBEngine::doSetSavepoint(Session* session,
374
drizzled::NamedSavepoint &savepoint)
376
ib_trx_t *transaction= get_trx(session);
377
ib_savepoint_take(*transaction, savepoint.getName().c_str(),
378
savepoint.getName().length());
382
int HailDBEngine::doRollbackToSavepoint(Session* session,
383
drizzled::NamedSavepoint &savepoint)
385
ib_trx_t *transaction= get_trx(session);
388
err= ib_savepoint_rollback(*transaction, savepoint.getName().c_str(),
389
savepoint.getName().length());
391
return ib_err_t_to_drizzle_error(err);
394
int HailDBEngine::doReleaseSavepoint(Session* session,
395
drizzled::NamedSavepoint &savepoint)
397
ib_trx_t *transaction= get_trx(session);
400
err= ib_savepoint_release(*transaction, savepoint.getName().c_str(),
401
savepoint.getName().length());
402
if (err != DB_SUCCESS)
403
return ib_err_t_to_drizzle_error(err);
408
int HailDBEngine::doCommit(Session* session, bool all)
411
ib_trx_t *transaction= get_trx(session);
413
if (all || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
415
err= ib_trx_commit(*transaction);
417
if (err != DB_SUCCESS)
418
return ib_err_t_to_drizzle_error(err);
426
int HailDBEngine::doRollback(Session* session, bool all)
429
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 (err != DB_SUCCESS)
436
return ib_err_t_to_drizzle_error(err);
442
err= ib_savepoint_rollback(*transaction, statement_savepoint_name.c_str(),
443
statement_savepoint_name.length());
444
if (err != DB_SUCCESS)
445
return ib_err_t_to_drizzle_error(err);
451
HailDBTableShare *HailDBEngine::findOpenTable(const string table_name)
453
HailDBMap::iterator find_iter=
454
haildb_open_tables.find(table_name);
456
if (find_iter != haildb_open_tables.end())
457
return (*find_iter).second;
462
void HailDBEngine::addOpenTable(const string &table_name, HailDBTableShare *share)
464
haildb_open_tables[table_name]= share;
467
void HailDBEngine::deleteOpenTable(const string &table_name)
469
haildb_open_tables.erase(table_name);
472
static pthread_mutex_t haildb_mutex= PTHREAD_MUTEX_INITIALIZER;
474
uint64_t HailDBCursor::getHiddenPrimaryKeyInitialAutoIncrementValue()
478
ib_trx_t transaction= *get_trx(getTable()->in_use);
479
ib_cursor_attach_trx(cursor, transaction);
480
tuple= ib_clust_read_tuple_create(cursor);
481
err= ib_cursor_last(cursor);
482
assert(err == DB_SUCCESS || err == DB_END_OF_INDEX); // Probably a FIXME
483
err= ib_cursor_read_row(cursor, tuple);
484
if (err == DB_RECORD_NOT_FOUND)
488
assert (err == DB_SUCCESS);
489
err= ib_tuple_read_u64(tuple, getTable()->getShare()->fields, &nr);
492
ib_tuple_delete(tuple);
494
err= ib_cursor_reset(cursor);
495
assert(err == DB_SUCCESS);
499
uint64_t HailDBCursor::getInitialAutoIncrementValue()
504
(void) extra(HA_EXTRA_KEYREAD);
505
getTable()->mark_columns_used_by_index_no_reset(getTable()->getShare()->next_number_index);
506
doStartIndexScan(getTable()->getShare()->next_number_index, 1);
507
if (getTable()->getShare()->next_number_keypart == 0)
508
{ // Autoincrement at key-start
509
error=index_last(getTable()->getUpdateRecord());
513
unsigned char key[MAX_KEY_LENGTH];
514
key_copy(key, getTable()->getInsertRecord(),
515
getTable()->key_info + getTable()->getShare()->next_number_index,
516
getTable()->getShare()->next_number_key_offset);
517
error= index_read_map(getTable()->getUpdateRecord(), key,
518
make_prev_keypart_map(getTable()->getShare()->next_number_keypart),
519
HA_READ_PREFIX_LAST);
525
nr= ((uint64_t) getTable()->found_next_number_field->
526
val_int_offset(getTable()->getShare()->rec_buff_length)+1);
528
(void) extra(HA_EXTRA_NO_KEYREAD);
530
if (getTable()->getShare()->getTableProto()->options().auto_increment_value() > nr)
531
nr= getTable()->getShare()->getTableProto()->options().auto_increment_value();
536
HailDBTableShare::HailDBTableShare(const char* name, bool hidden_primary_key)
537
: use_count(0), has_hidden_primary_key(hidden_primary_key)
539
table_name.assign(name);
542
uint64_t HailDBEngine::getInitialAutoIncrementValue(HailDBCursor *cursor)
544
doStartTransaction(current_session, START_TRANS_NO_OPTIONS);
545
uint64_t initial_auto_increment_value= cursor->getInitialAutoIncrementValue();
546
doCommit(current_session, true);
548
return initial_auto_increment_value;
551
uint64_t HailDBEngine::getHiddenPrimaryKeyInitialAutoIncrementValue(HailDBCursor *cursor)
553
doStartTransaction(current_session, START_TRANS_NO_OPTIONS);
554
uint64_t initial_auto_increment_value= cursor->getHiddenPrimaryKeyInitialAutoIncrementValue();
555
doCommit(current_session, true);
557
return initial_auto_increment_value;
560
HailDBTableShare *HailDBCursor::get_share(const char *table_name, bool has_hidden_primary_key, int *rc)
562
pthread_mutex_lock(&haildb_mutex);
564
HailDBEngine *a_engine= static_cast<HailDBEngine *>(getEngine());
565
share= a_engine->findOpenTable(table_name);
569
share= new HailDBTableShare(table_name, has_hidden_primary_key);
573
pthread_mutex_unlock(&haildb_mutex);
574
*rc= HA_ERR_OUT_OF_MEM;
578
if (getTable()->found_next_number_field)
580
share->auto_increment_value.fetch_and_store(
581
a_engine->getInitialAutoIncrementValue(this));
585
if (has_hidden_primary_key)
587
uint64_t hidden_pkey= 0;
588
hidden_pkey= a_engine->getHiddenPrimaryKeyInitialAutoIncrementValue(this);
589
share->hidden_pkey_auto_increment_value.fetch_and_store(hidden_pkey);
592
a_engine->addOpenTable(share->table_name, share);
593
thr_lock_init(&share->lock);
597
pthread_mutex_unlock(&haildb_mutex);
602
int HailDBCursor::free_share()
604
pthread_mutex_lock(&haildb_mutex);
605
if (!--share->use_count)
607
HailDBEngine *a_engine= static_cast<HailDBEngine *>(getEngine());
608
a_engine->deleteOpenTable(share->table_name);
611
pthread_mutex_unlock(&haildb_mutex);
617
THR_LOCK_DATA **HailDBCursor::store_lock(Session *session,
619
thr_lock_type lock_type)
621
/* Currently, we can get a transaction start by ::store_lock
622
instead of beginTransaction, startStatement.
624
See https://bugs.launchpad.net/drizzle/+bug/535528
626
all stemming from the transactional engine interface needing
627
a severe amount of immodium.
630
if(*get_trx(session) == NULL)
632
static_cast<HailDBEngine*>(getEngine())->
633
doStartTransaction(session, START_TRANS_NO_OPTIONS);
636
if (lock_type != TL_UNLOCK)
638
ib_savepoint_take(*get_trx(session), statement_savepoint_name.c_str(),
639
statement_savepoint_name.length());
642
/* the below is adapted from ha_innodb.cc */
644
const uint32_t sql_command = session_sql_command(session);
646
if (sql_command == SQLCOM_DROP_TABLE) {
648
/* MySQL calls this function in DROP Table though this table
649
handle may belong to another session that is running a query.
650
Let us in that case skip any changes to the prebuilt struct. */
652
} else if (lock_type == TL_READ_WITH_SHARED_LOCKS
653
|| lock_type == TL_READ_NO_INSERT
654
|| (lock_type != TL_IGNORE
655
&& sql_command != SQLCOM_SELECT)) {
657
/* The OR cases above are in this order:
658
1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
659
are processing a stored procedure or function, or
660
2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
661
3) this is a SELECT ... IN SHARE MODE, or
662
4) we are doing a complex SQL statement like
663
INSERT INTO ... SELECT ... and the logical logging (MySQL
664
binlog) requires the use of a locking read, or
665
MySQL is doing LOCK TABLES ... READ.
666
5) we let InnoDB do locking reads for all SQL statements that
667
are not simple SELECTs; note that select_lock_type in this
668
case may get strengthened in ::external_lock() to LOCK_X.
669
Note that we MUST use a locking read in all data modifying
670
SQL statements, because otherwise the execution would not be
671
serializable, and also the results from the update could be
672
unexpected if an obsolete consistent read view would be
675
enum_tx_isolation isolation_level= session_tx_isolation(session);
677
if (isolation_level != ISO_SERIALIZABLE
678
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
679
&& (sql_command == SQLCOM_INSERT_SELECT
680
|| sql_command == SQLCOM_UPDATE
681
|| sql_command == SQLCOM_CREATE_TABLE)) {
683
/* If we either have innobase_locks_unsafe_for_binlog
684
option set or this session is using READ COMMITTED
685
isolation level and isolation level of the transaction
686
is not set to serializable and MySQL is doing
687
INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
688
CREATE ... SELECT... without FOR UPDATE or
689
IN SHARE MODE in select, then we use consistent
692
ib_lock_mode= IB_LOCK_NONE;
693
} else if (sql_command == SQLCOM_CHECKSUM) {
694
/* Use consistent read for checksum table */
696
ib_lock_mode= IB_LOCK_NONE;
698
ib_lock_mode= IB_LOCK_S;
701
} else if (lock_type != TL_IGNORE) {
703
/* We set possible LOCK_X value in external_lock, not yet
704
here even if this would be SELECT ... FOR UPDATE */
705
ib_lock_mode= IB_LOCK_NONE;
708
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
710
/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
711
TABLESPACE or TRUNCATE TABLE then allow multiple
712
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
713
< TL_WRITE_CONCURRENT_INSERT.
716
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
717
&& lock_type <= TL_WRITE)
718
&& !session_tablespace_op(session)
719
&& sql_command != SQLCOM_TRUNCATE
720
&& sql_command != SQLCOM_CREATE_TABLE) {
722
lock_type = TL_WRITE_ALLOW_WRITE;
725
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
726
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
727
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
728
to t2. Convert the lock to a normal read lock to allow
729
concurrent inserts to t2.
732
if (lock_type == TL_READ_NO_INSERT) {
737
lock.type = lock_type;
745
void HailDBCursor::get_auto_increment(uint64_t, //offset,
746
uint64_t, //increment,
748
uint64_t *first_value,
749
uint64_t *nb_reserved_values)
752
*first_value= share->auto_increment_value.fetch_and_increment();
753
if (*first_value == 0)
755
/* if it's zero, then we skip it... why? because of ass.
756
set auto-inc to -1 and the sequence is:
758
Zero is still "magic".
760
share->auto_increment_value.compare_and_swap(1, 0);
763
*nb_reserved_values= 1;
766
static const char* table_path_to_haildb_name(const char* name)
768
size_t l= strlen(name);
769
static string datadict_path("data_dictionary/");
770
static string sys_prefix("data_dictionary/haildb_");
771
static string sys_table_prefix("HAILDB_");
773
if (strncmp(name, sys_prefix.c_str(), sys_prefix.length()) == 0)
775
string find_name(name+datadict_path.length());
776
std::transform(find_name.begin(), find_name.end(), find_name.begin(), ::toupper);
777
boost::unordered_set<string>::iterator iter= haildb_system_table_names.find(find_name);
778
if (iter != haildb_system_table_names.end())
779
return (*iter).c_str()+sys_table_prefix.length();
783
while(slashes>0 && l > 0)
795
static void TableIdentifier_to_haildb_name(const TableIdentifier &identifier, std::string *str)
797
str->assign(table_path_to_haildb_name(identifier.getPath().c_str()));
800
HailDBCursor::HailDBCursor(drizzled::plugin::StorageEngine &engine_arg,
802
:Cursor(engine_arg, table_arg),
803
ib_lock_mode(IB_LOCK_NONE),
804
write_can_replace(false),
808
static unsigned int get_first_unique_index(drizzled::Table &table)
810
for (uint32_t k= 0; k < table.getShare()->keys; k++)
812
if (table.key_info[k].flags & HA_NOSAME)
821
int HailDBCursor::open(const char *name, int, uint32_t)
823
const char* haildb_table_name= table_path_to_haildb_name(name);
824
ib_err_t err= ib_table_get_id(haildb_table_name, &table_id);
825
bool has_hidden_primary_key= false;
828
if (err != DB_SUCCESS)
829
return ib_err_t_to_drizzle_error(err);
831
err= ib_cursor_open_table_using_id(table_id, NULL, &cursor);
832
cursor_is_sec_index= false;
834
if (err != DB_SUCCESS)
835
return ib_err_t_to_drizzle_error(err);
837
err= ib_index_get_id(haildb_table_name, "HIDDEN_PRIMARY", &idx_id);
839
if (err == DB_SUCCESS)
840
has_hidden_primary_key= true;
843
share= get_share(name, has_hidden_primary_key, &rc);
844
lock.init(&share->lock);
847
if (getTable()->getShare()->getPrimaryKey() != MAX_KEY)
848
ref_length= getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_length;
849
else if (share->has_hidden_primary_key)
850
ref_length= sizeof(uint64_t);
853
unsigned int keynr= get_first_unique_index(*getTable());
854
ref_length= getTable()->key_info[keynr].key_length;
857
in_table_scan= false;
862
int HailDBCursor::close(void)
864
ib_err_t err= ib_cursor_close(cursor);
865
if (err != DB_SUCCESS)
866
return ib_err_t_to_drizzle_error(err);
876
int HailDBCursor::external_lock(Session* session, int lock_type)
878
ib_cursor_stmt_begin(cursor);
882
if (lock_type == F_WRLCK)
884
/* SELECT ... FOR UPDATE or UPDATE TABLE */
885
ib_lock_mode= IB_LOCK_X;
888
ib_lock_mode= IB_LOCK_NONE;
893
static int create_table_add_field(ib_tbl_sch_t schema,
894
const message::Table::Field &field,
897
ib_col_attr_t column_attr= IB_COL_NONE;
899
if (field.has_constraints() && ! field.constraints().is_nullable())
900
column_attr= IB_COL_NOT_NULL;
902
switch (field.type())
904
case message::Table::Field::VARCHAR:
905
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_VARCHAR,
907
field.string_options().length());
909
case message::Table::Field::INTEGER:
910
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
913
case message::Table::Field::BIGINT:
914
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
917
case message::Table::Field::DOUBLE:
918
case message::Table::Field::DATETIME:
919
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_DOUBLE,
920
column_attr, 0, sizeof(double));
922
case message::Table::Field::ENUM:
923
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
926
case message::Table::Field::DATE:
927
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
930
case message::Table::Field::TIMESTAMP:
931
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
934
case message::Table::Field::BLOB:
935
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_BLOB,
938
case message::Table::Field::DECIMAL:
939
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_DECIMAL,
943
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "Column Type");
944
return(HA_ERR_UNSUPPORTED);
950
static ib_err_t store_table_message(ib_trx_t transaction, const char* table_name, drizzled::message::Table& table_message)
953
ib_tpl_t message_tuple;
955
string serialized_message;
957
err= ib_cursor_open_table(HAILDB_TABLE_DEFINITIONS_TABLE, transaction, &cursor);
958
if (err != DB_SUCCESS)
961
message_tuple= ib_clust_read_tuple_create(cursor);
963
err= ib_col_set_value(message_tuple, 0, table_name, strlen(table_name));
964
if (err != DB_SUCCESS)
968
table_message.SerializeToString(&serialized_message);
975
err= ib_col_set_value(message_tuple, 1, serialized_message.c_str(),
976
serialized_message.length());
977
if (err != DB_SUCCESS)
980
err= ib_cursor_insert_row(cursor, message_tuple);
983
ib_tuple_delete(message_tuple);
985
ib_err_t cleanup_err= ib_cursor_close(cursor);
986
if (err == DB_SUCCESS)
992
bool HailDBEngine::validateCreateTableOption(const std::string &key,
993
const std::string &state)
995
if (boost::iequals(key, "ROW_FORMAT"))
997
if (boost::iequals(state, "COMPRESSED"))
1000
if (boost::iequals(state, "COMPACT"))
1003
if (boost::iequals(state, "DYNAMIC"))
1006
if (boost::iequals(state, "REDUNDANT"))
1013
static ib_tbl_fmt_t parse_ib_table_format(const std::string &value)
1015
if (boost::iequals(value, "REDUNDANT"))
1016
return IB_TBL_REDUNDANT;
1017
else if (boost::iequals(value, "COMPACT"))
1018
return IB_TBL_COMPACT;
1019
else if (boost::iequals(value, "DYNAMIC"))
1020
return IB_TBL_DYNAMIC;
1021
else if (boost::iequals(value, "COMPRESSED"))
1022
return IB_TBL_COMPRESSED;
1024
assert(false); /* You need to add possible table formats here */
1025
return IB_TBL_COMPACT;
1028
int HailDBEngine::doCreateTable(Session &session,
1030
const drizzled::TableIdentifier &identifier,
1031
drizzled::message::Table& table_message)
1033
ib_tbl_sch_t haildb_table_schema= NULL;
1034
// ib_idx_sch_t haildb_pkey= NULL;
1035
ib_trx_t haildb_schema_transaction;
1036
ib_id_t haildb_table_id;
1037
ib_err_t haildb_err= DB_SUCCESS;
1038
string haildb_table_name;
1039
bool has_explicit_pkey= false;
1043
if (table_message.type() == message::Table::TEMPORARY)
1045
ib_bool_t create_db_err= ib_database_create(GLOBAL_TEMPORARY_EXT);
1046
if (create_db_err != IB_TRUE)
1050
TableIdentifier_to_haildb_name(identifier, &haildb_table_name);
1052
ib_tbl_fmt_t haildb_table_format= IB_TBL_COMPACT;
1054
const size_t num_engine_options= table_message.engine().options_size();
1055
for (size_t x= 0; x < num_engine_options; x++)
1057
const message::Engine::Option &engine_option= table_message.engine().options(x);
1058
if (boost::iequals(engine_option.name(), "ROW_FORMAT"))
1060
haildb_table_format= parse_ib_table_format(engine_option.state());
1064
haildb_err= ib_table_schema_create(haildb_table_name.c_str(),
1065
&haildb_table_schema,
1066
haildb_table_format, 0);
1068
if (haildb_err != DB_SUCCESS)
1070
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1071
ER_CANT_CREATE_TABLE,
1072
_("Cannot create table %s. HailDB Error %d (%s)\n"),
1073
haildb_table_name.c_str(), haildb_err, ib_strerror(haildb_err));
1074
return ib_err_t_to_drizzle_error(haildb_err);
1077
for (int colnr= 0; colnr < table_message.field_size() ; colnr++)
1079
const message::Table::Field field = table_message.field(colnr);
1081
int field_err= create_table_add_field(haildb_table_schema, field,
1084
if (haildb_err != DB_SUCCESS || field_err != 0)
1085
ib_table_schema_delete(haildb_table_schema); /* cleanup */
1087
if (haildb_err != DB_SUCCESS)
1089
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1090
ER_CANT_CREATE_TABLE,
1091
_("Cannot create field %s on table %s."
1092
" HailDB Error %d (%s)\n"),
1093
field.name().c_str(), haildb_table_name.c_str(),
1094
haildb_err, ib_strerror(haildb_err));
1095
return ib_err_t_to_drizzle_error(haildb_err);
1101
bool has_primary= false;
1102
for (int indexnr= 0; indexnr < table_message.indexes_size() ; indexnr++)
1104
message::Table::Index *index = table_message.mutable_indexes(indexnr);
1106
ib_idx_sch_t haildb_index;
1108
haildb_err= ib_table_schema_add_index(haildb_table_schema, index->name().c_str(),
1110
if (haildb_err != DB_SUCCESS)
1113
if (index->is_primary())
1116
haildb_err= ib_index_schema_set_clustered(haildb_index);
1117
has_explicit_pkey= true;
1118
if (haildb_err != DB_SUCCESS)
1122
if (index->is_unique())
1124
haildb_err= ib_index_schema_set_unique(haildb_index);
1125
if (haildb_err != DB_SUCCESS)
1129
if (index->type() == message::Table::Index::UNKNOWN_INDEX)
1130
index->set_type(message::Table::Index::BTREE);
1132
for (int partnr= 0; partnr < index->index_part_size(); partnr++)
1134
const message::Table::Index::IndexPart part= index->index_part(partnr);
1135
const message::Table::Field::FieldType part_type= table_message.field(part.fieldnr()).type();
1136
uint64_t compare_length= 0;
1138
if (part_type == message::Table::Field::BLOB
1139
|| part_type == message::Table::Field::VARCHAR)
1140
compare_length= part.compare_length();
1142
haildb_err= ib_index_schema_add_col(haildb_index,
1143
table_message.field(part.fieldnr()).name().c_str(),
1145
if (haildb_err != DB_SUCCESS)
1149
if (! has_primary && index->is_unique())
1151
haildb_err= ib_index_schema_set_clustered(haildb_index);
1152
has_explicit_pkey= true;
1153
if (haildb_err != DB_SUCCESS)
1159
if (! has_explicit_pkey)
1161
ib_idx_sch_t haildb_index;
1163
haildb_err= ib_table_schema_add_col(haildb_table_schema, "hidden_primary_key_col",
1164
IB_INT, IB_COL_NOT_NULL, 0, 8);
1166
haildb_err= ib_table_schema_add_index(haildb_table_schema, "HIDDEN_PRIMARY",
1168
if (haildb_err != DB_SUCCESS)
1171
haildb_err= ib_index_schema_set_clustered(haildb_index);
1172
if (haildb_err != DB_SUCCESS)
1175
haildb_err= ib_index_schema_add_col(haildb_index, "hidden_primary_key_col", 0);
1176
if (haildb_err != DB_SUCCESS)
1180
haildb_schema_transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
1181
haildb_err= ib_schema_lock_exclusive(haildb_schema_transaction);
1182
if (haildb_err != DB_SUCCESS)
1184
ib_err_t rollback_err= ib_trx_rollback(haildb_schema_transaction);
1185
ib_table_schema_delete(haildb_table_schema);
1187
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1188
ER_CANT_CREATE_TABLE,
1189
_("Cannot Lock HailDB Data Dictionary. HailDB Error %d (%s)\n"),
1190
haildb_err, ib_strerror(haildb_err));
1192
assert (rollback_err == DB_SUCCESS);
1194
return HA_ERR_GENERIC;
1197
haildb_err= ib_table_create(haildb_schema_transaction, haildb_table_schema,
1200
if (haildb_err != DB_SUCCESS)
1202
ib_err_t rollback_err= ib_trx_rollback(haildb_schema_transaction);
1203
ib_table_schema_delete(haildb_table_schema);
1205
if (haildb_err == DB_TABLE_IS_BEING_USED)
1208
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1209
ER_CANT_CREATE_TABLE,
1210
_("Cannot create table %s. HailDB Error %d (%s)\n"),
1211
haildb_table_name.c_str(),
1212
haildb_err, ib_strerror(haildb_err));
1214
assert (rollback_err == DB_SUCCESS);
1215
return HA_ERR_GENERIC;
1218
if (table_message.type() == message::Table::TEMPORARY)
1220
session.getMessageCache().storeTableMessage(identifier, table_message);
1221
haildb_err= DB_SUCCESS;
1224
haildb_err= store_table_message(haildb_schema_transaction,
1225
haildb_table_name.c_str(),
1228
if (haildb_err == DB_SUCCESS)
1229
haildb_err= ib_trx_commit(haildb_schema_transaction);
1231
haildb_err= ib_trx_rollback(haildb_schema_transaction);
1234
ib_table_schema_delete(haildb_table_schema);
1236
if (haildb_err != DB_SUCCESS)
1238
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1239
ER_CANT_CREATE_TABLE,
1240
_("Cannot create table %s. HailDB Error %d (%s)\n"),
1241
haildb_table_name.c_str(),
1242
haildb_err, ib_strerror(haildb_err));
1243
return ib_err_t_to_drizzle_error(haildb_err);
1249
static int delete_table_message_from_haildb(ib_trx_t transaction, const char* table_name)
1252
ib_tpl_t search_tuple;
1256
err= ib_cursor_open_table(HAILDB_TABLE_DEFINITIONS_TABLE, transaction, &cursor);
1257
if (err != DB_SUCCESS)
1260
search_tuple= ib_clust_search_tuple_create(cursor);
1262
err= ib_col_set_value(search_tuple, 0, table_name, strlen(table_name));
1263
if (err != DB_SUCCESS)
1266
// ib_cursor_set_match_mode(cursor, IB_EXACT_MATCH);
1268
err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
1269
if (err == DB_RECORD_NOT_FOUND || res != 0)
1272
err= ib_cursor_delete_row(cursor);
1273
assert (err == DB_SUCCESS);
1276
ib_err_t rollback_err= ib_cursor_close(cursor);
1277
if (err == DB_SUCCESS)
1280
ib_tuple_delete(search_tuple);
1285
int HailDBEngine::doDropTable(Session &session,
1286
const TableIdentifier &identifier)
1288
ib_trx_t haildb_schema_transaction;
1289
ib_err_t haildb_err;
1290
string haildb_table_name;
1292
TableIdentifier_to_haildb_name(identifier, &haildb_table_name);
1294
haildb_schema_transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
1295
haildb_err= ib_schema_lock_exclusive(haildb_schema_transaction);
1296
if (haildb_err != DB_SUCCESS)
1298
ib_err_t rollback_err= ib_trx_rollback(haildb_schema_transaction);
1300
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1301
ER_CANT_DELETE_FILE,
1302
_("Cannot Lock HailDB Data Dictionary. HailDB Error %d (%s)\n"),
1303
haildb_err, ib_strerror(haildb_err));
1305
assert (rollback_err == DB_SUCCESS);
1307
return HA_ERR_GENERIC;
1310
if (identifier.getType() == message::Table::TEMPORARY)
1312
session.getMessageCache().removeTableMessage(identifier);
1313
delete_table_message_from_haildb(haildb_schema_transaction,
1314
haildb_table_name.c_str());
1318
if (delete_table_message_from_haildb(haildb_schema_transaction, haildb_table_name.c_str()) != DB_SUCCESS)
1320
ib_schema_unlock(haildb_schema_transaction);
1321
ib_err_t rollback_err= ib_trx_rollback(haildb_schema_transaction);
1322
assert(rollback_err == DB_SUCCESS);
1323
return HA_ERR_GENERIC;
1327
haildb_err= ib_table_drop(haildb_schema_transaction, haildb_table_name.c_str());
1329
if (haildb_err == DB_TABLE_NOT_FOUND)
1331
haildb_err= ib_trx_rollback(haildb_schema_transaction);
1332
assert(haildb_err == DB_SUCCESS);
1335
else if (haildb_err != DB_SUCCESS)
1337
ib_err_t rollback_err= ib_trx_rollback(haildb_schema_transaction);
1339
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1340
ER_CANT_DELETE_FILE,
1341
_("Cannot DROP table %s. HailDB Error %d (%s)\n"),
1342
haildb_table_name.c_str(),
1343
haildb_err, ib_strerror(haildb_err));
1345
assert(rollback_err == DB_SUCCESS);
1347
return HA_ERR_GENERIC;
1350
haildb_err= ib_trx_commit(haildb_schema_transaction);
1351
if (haildb_err != DB_SUCCESS)
1353
ib_err_t rollback_err= ib_trx_rollback(haildb_schema_transaction);
1355
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1356
ER_CANT_DELETE_FILE,
1357
_("Cannot DROP table %s. HailDB Error %d (%s)\n"),
1358
haildb_table_name.c_str(),
1359
haildb_err, ib_strerror(haildb_err));
1361
assert(rollback_err == DB_SUCCESS);
1362
return HA_ERR_GENERIC;
1368
static ib_err_t rename_table_message(ib_trx_t transaction, const TableIdentifier &from_identifier, const TableIdentifier &to_identifier)
1371
ib_tpl_t search_tuple;
1372
ib_tpl_t read_tuple;
1373
ib_tpl_t update_tuple;
1376
ib_err_t rollback_err;
1377
const char *message;
1378
ib_ulint_t message_len;
1379
drizzled::message::Table table_message;
1380
string from_haildb_table_name;
1381
string to_haildb_table_name;
1384
string serialized_message;
1385
ib_col_meta_t col_meta;
1387
TableIdentifier_to_haildb_name(from_identifier, &from_haildb_table_name);
1388
TableIdentifier_to_haildb_name(to_identifier, &to_haildb_table_name);
1390
from= from_haildb_table_name.c_str();
1391
to= to_haildb_table_name.c_str();
1393
err= ib_cursor_open_table(HAILDB_TABLE_DEFINITIONS_TABLE, transaction, &cursor);
1394
if (err != DB_SUCCESS)
1396
rollback_err= ib_trx_rollback(transaction);
1397
assert(rollback_err == DB_SUCCESS);
1401
search_tuple= ib_clust_search_tuple_create(cursor);
1402
read_tuple= ib_clust_read_tuple_create(cursor);
1404
err= ib_col_set_value(search_tuple, 0, from, strlen(from));
1405
if (err != DB_SUCCESS)
1408
// ib_cursor_set_match_mode(cursor, IB_EXACT_MATCH);
1410
err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
1411
if (err == DB_RECORD_NOT_FOUND || res != 0)
1414
err= ib_cursor_read_row(cursor, read_tuple);
1415
if (err == DB_RECORD_NOT_FOUND || res != 0)
1418
message= (const char*)ib_col_get_value(read_tuple, 1);
1419
message_len= ib_col_get_meta(read_tuple, 1, &col_meta);
1421
if (table_message.ParseFromArray(message, message_len) == false)
1424
table_message.set_name(to_identifier.getTableName());
1425
table_message.set_schema(to_identifier.getSchemaName());
1427
update_tuple= ib_clust_read_tuple_create(cursor);
1429
err= ib_tuple_copy(update_tuple, read_tuple);
1430
assert(err == DB_SUCCESS);
1432
err= ib_col_set_value(update_tuple, 0, to, strlen(to));
1435
table_message.SerializeToString(&serialized_message);
1442
err= ib_col_set_value(update_tuple, 1, serialized_message.c_str(),
1443
serialized_message.length());
1445
err= ib_cursor_update_row(cursor, read_tuple, update_tuple);
1448
ib_tuple_delete(update_tuple);
1449
ib_tuple_delete(read_tuple);
1450
ib_tuple_delete(search_tuple);
1452
err= ib_cursor_close(cursor);
1458
int HailDBEngine::doRenameTable(drizzled::Session &session,
1459
const drizzled::TableIdentifier &from,
1460
const drizzled::TableIdentifier &to)
1462
ib_trx_t haildb_schema_transaction;
1464
string from_haildb_table_name;
1465
string to_haildb_table_name;
1467
if (to.getType() == message::Table::TEMPORARY
1468
&& from.getType() == message::Table::TEMPORARY)
1470
session.getMessageCache().renameTableMessage(from, to);
1474
TableIdentifier_to_haildb_name(from, &from_haildb_table_name);
1475
TableIdentifier_to_haildb_name(to, &to_haildb_table_name);
1477
haildb_schema_transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
1478
err= ib_schema_lock_exclusive(haildb_schema_transaction);
1479
if (err != DB_SUCCESS)
1481
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1482
ER_CANT_DELETE_FILE,
1483
_("Cannot Lock HailDB Data Dictionary. HailDB Error %d (%s)\n"),
1484
err, ib_strerror(err));
1489
err= ib_table_rename(haildb_schema_transaction,
1490
from_haildb_table_name.c_str(),
1491
to_haildb_table_name.c_str());
1492
if (err != DB_SUCCESS)
1495
err= rename_table_message(haildb_schema_transaction, from, to);
1497
if (err != DB_SUCCESS)
1500
err= ib_trx_commit(haildb_schema_transaction);
1501
if (err != DB_SUCCESS)
1506
ib_err_t rollback_err= ib_schema_unlock(haildb_schema_transaction);
1507
assert(rollback_err == DB_SUCCESS);
1508
rollback_err= ib_trx_rollback(haildb_schema_transaction);
1509
assert(rollback_err == DB_SUCCESS);
1510
return ib_err_t_to_drizzle_error(err);
1513
void HailDBEngine::getTableNamesInSchemaFromHailDB(
1514
const drizzled::SchemaIdentifier &schema,
1515
drizzled::plugin::TableNameList *set_of_names,
1516
drizzled::TableIdentifier::vector *identifiers)
1518
ib_trx_t transaction;
1521
Why not use getPath()?
1523
string search_string(schema.getSchemaName());
1525
boost::algorithm::to_lower(search_string);
1527
search_string.append("/");
1529
transaction = ib_trx_begin(IB_TRX_REPEATABLE_READ);
1530
ib_err_t haildb_err= ib_schema_lock_exclusive(transaction);
1531
assert(haildb_err == DB_SUCCESS); /* FIXME: doGetTableNames needs to be able to return error */
1533
if (search_string.compare("data_dictionary/") == 0)
1537
BOOST_FOREACH(std::string table_name, haildb_system_table_names)
1539
set_of_names->insert(table_name);
1544
BOOST_FOREACH(std::string table_name, haildb_system_table_names)
1546
identifiers->push_back(TableIdentifier(schema.getSchemaName(),
1552
haildb_err= ib_cursor_open_table("SYS_TABLES", transaction, &cursor);
1553
assert(haildb_err == DB_SUCCESS); /* FIXME */
1555
ib_tpl_t read_tuple;
1556
ib_tpl_t search_tuple;
1558
read_tuple= ib_clust_read_tuple_create(cursor);
1559
search_tuple= ib_clust_search_tuple_create(cursor);
1561
haildb_err= ib_col_set_value(search_tuple, 0, search_string.c_str(),
1562
search_string.length());
1563
assert (haildb_err == DB_SUCCESS); // FIXME
1566
haildb_err = ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
1567
// fixme: check error above
1569
while (haildb_err == DB_SUCCESS)
1571
haildb_err= ib_cursor_read_row(cursor, read_tuple);
1573
const char *table_name;
1575
ib_col_meta_t column_metadata;
1577
table_name= (const char*)ib_col_get_value(read_tuple, 0);
1578
table_name_len= ib_col_get_meta(read_tuple, 0, &column_metadata);
1580
if (search_string.compare(0, search_string.length(),
1581
table_name, search_string.length()) == 0)
1583
const char *just_table_name= strchr(table_name, '/');
1584
assert(just_table_name);
1585
just_table_name++; /* skip over '/' */
1587
set_of_names->insert(just_table_name);
1589
identifiers->push_back(TableIdentifier(schema.getSchemaName(), just_table_name));
1593
haildb_err= ib_cursor_next(cursor);
1594
read_tuple= ib_tuple_clear(read_tuple);
1597
ib_tuple_delete(read_tuple);
1598
ib_tuple_delete(search_tuple);
1600
haildb_err= ib_cursor_close(cursor);
1601
assert(haildb_err == DB_SUCCESS); // FIXME
1603
haildb_err= ib_trx_commit(transaction);
1604
assert(haildb_err == DB_SUCCESS); // FIXME
1607
void HailDBEngine::doGetTableIdentifiers(drizzled::CachedDirectory &,
1608
const drizzled::SchemaIdentifier &schema,
1609
drizzled::TableIdentifier::vector &identifiers)
1611
getTableNamesInSchemaFromHailDB(schema, NULL, &identifiers);
1614
static int read_table_message_from_haildb(const char* table_name, drizzled::message::Table *table_message)
1616
ib_trx_t transaction;
1617
ib_tpl_t search_tuple;
1618
ib_tpl_t read_tuple;
1620
const char *message;
1621
ib_ulint_t message_len;
1622
ib_col_meta_t col_meta;
1625
ib_err_t rollback_err;
1627
transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
1628
err= ib_schema_lock_exclusive(transaction);
1629
if (err != DB_SUCCESS)
1631
rollback_err= ib_trx_rollback(transaction);
1632
assert(rollback_err == DB_SUCCESS);
1636
err= ib_cursor_open_table(HAILDB_TABLE_DEFINITIONS_TABLE, transaction, &cursor);
1637
if (err != DB_SUCCESS)
1639
rollback_err= ib_trx_rollback(transaction);
1640
assert(rollback_err == DB_SUCCESS);
1644
search_tuple= ib_clust_search_tuple_create(cursor);
1645
read_tuple= ib_clust_read_tuple_create(cursor);
1647
err= ib_col_set_value(search_tuple, 0, table_name, strlen(table_name));
1648
if (err != DB_SUCCESS)
1651
// ib_cursor_set_match_mode(cursor, IB_EXACT_MATCH);
1653
err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
1654
if (err == DB_RECORD_NOT_FOUND || res != 0)
1657
err= ib_cursor_read_row(cursor, read_tuple);
1658
if (err == DB_RECORD_NOT_FOUND || res != 0)
1661
message= (const char*)ib_col_get_value(read_tuple, 1);
1662
message_len= ib_col_get_meta(read_tuple, 1, &col_meta);
1664
if (table_message->ParseFromArray(message, message_len) == false)
1667
ib_tuple_delete(search_tuple);
1668
ib_tuple_delete(read_tuple);
1669
err= ib_cursor_close(cursor);
1670
if (err != DB_SUCCESS)
1671
goto rollback_close_err;
1672
err= ib_trx_commit(transaction);
1673
if (err != DB_SUCCESS)
1674
goto rollback_close_err;
1679
ib_tuple_delete(search_tuple);
1680
ib_tuple_delete(read_tuple);
1681
rollback_err= ib_cursor_close(cursor);
1682
assert(rollback_err == DB_SUCCESS);
1684
ib_schema_unlock(transaction);
1685
rollback_err= ib_trx_rollback(transaction);
1686
assert(rollback_err == DB_SUCCESS);
1688
if (strcmp(table_name, HAILDB_TABLE_DEFINITIONS_TABLE) == 0)
1690
message::Engine *engine= table_message->mutable_engine();
1691
engine->set_name("InnoDB");
1692
table_message->set_name("haildb_table_definitions");
1693
table_message->set_schema("data_dictionary");
1694
table_message->set_type(message::Table::STANDARD);
1695
table_message->set_creation_timestamp(0);
1696
table_message->set_update_timestamp(0);
1698
message::Table::TableOptions *options= table_message->mutable_options();
1699
options->set_collation_id(my_charset_bin.number);
1700
options->set_collation(my_charset_bin.name);
1702
message::Table::Field *field= table_message->add_field();
1703
field->set_name("table_name");
1704
field->set_type(message::Table::Field::VARCHAR);
1705
message::Table::Field::StringFieldOptions *stropt= field->mutable_string_options();
1706
stropt->set_length(IB_MAX_TABLE_NAME_LEN);
1707
stropt->set_collation_id(my_charset_bin.number);
1708
stropt->set_collation(my_charset_bin.name);
1710
field= table_message->add_field();
1711
field->set_name("message");
1712
field->set_type(message::Table::Field::BLOB);
1713
stropt= field->mutable_string_options();
1714
stropt->set_collation_id(my_charset_bin.number);
1715
stropt->set_collation(my_charset_bin.name);
1717
message::Table::Index *index= table_message->add_indexes();
1718
index->set_name("PRIMARY");
1719
index->set_is_primary(true);
1720
index->set_is_unique(true);
1721
index->set_type(message::Table::Index::BTREE);
1722
index->set_key_length(IB_MAX_TABLE_NAME_LEN);
1723
message::Table::Index::IndexPart *part= index->add_index_part();
1724
part->set_fieldnr(0);
1725
part->set_compare_length(IB_MAX_TABLE_NAME_LEN);
1733
int HailDBEngine::doGetTableDefinition(Session &session,
1734
const TableIdentifier &identifier,
1735
drizzled::message::Table &table)
1737
ib_crsr_t haildb_cursor= NULL;
1738
string haildb_table_name;
1740
/* Check temporary tables!? */
1741
if (session.getMessageCache().getTableMessage(identifier, table))
1744
TableIdentifier_to_haildb_name(identifier, &haildb_table_name);
1746
if (ib_cursor_open_table(haildb_table_name.c_str(), NULL, &haildb_cursor) != DB_SUCCESS)
1749
ib_err_t err= ib_cursor_close(haildb_cursor);
1751
assert (err == DB_SUCCESS);
1753
if (read_table_message_from_haildb(haildb_table_name.c_str(), &table) != 0)
1755
if (get_haildb_system_table_message(haildb_table_name.c_str(), &table) == 0)
1762
bool HailDBEngine::doDoesTableExist(Session &,
1763
const TableIdentifier& identifier)
1765
ib_crsr_t haildb_cursor;
1766
string haildb_table_name;
1768
TableIdentifier_to_haildb_name(identifier, &haildb_table_name);
1770
boost::unordered_set<string>::iterator iter= haildb_system_table_names.find(identifier.getTableName());
1771
if (iter != haildb_system_table_names.end())
1774
if (ib_cursor_open_table(haildb_table_name.c_str(), NULL, &haildb_cursor) != DB_SUCCESS)
1777
ib_err_t err= ib_cursor_close(haildb_cursor);
1778
assert(err == DB_SUCCESS);
1783
const char *HailDBCursor::index_type(uint32_t)
1788
static ib_err_t write_row_to_haildb_tuple(const unsigned char* buf,
1789
Field **fields, ib_tpl_t tuple)
1792
ib_err_t err= DB_ERROR;
1793
ptrdiff_t row_offset= buf - (*fields)->getTable()->getInsertRecord();
1795
for (Field **field= fields; *field; field++, colnr++)
1797
(**field).move_field_offset(row_offset);
1799
if (! (**field).isWriteSet() && (**field).is_null())
1801
(**field).move_field_offset(-row_offset);
1805
if ((**field).is_null())
1807
err= ib_col_set_value(tuple, colnr, NULL, IB_SQL_NULL);
1808
assert(err == DB_SUCCESS);
1809
(**field).move_field_offset(-row_offset);
1813
if ((**field).type() == DRIZZLE_TYPE_VARCHAR)
1815
/* To get around the length bytes (1 or 2) at (**field).ptr
1816
we can use Field_varstring::val_str to a String
1817
to get a pointer to the real string without copying it.
1820
(**field).setReadSet();
1821
(**field).val_str_internal(&str);
1822
err= ib_col_set_value(tuple, colnr, str.ptr(), str.length());
1824
else if ((**field).type() == DRIZZLE_TYPE_ENUM)
1826
err= ib_tuple_write_u32(tuple, colnr, *((ib_u32_t*)(*field)->ptr));
1828
else if ((**field).type() == DRIZZLE_TYPE_DATE)
1830
(**field).setReadSet();
1831
err= ib_tuple_write_u32(tuple, colnr, (*field)->val_int());
1833
else if ((**field).type() == DRIZZLE_TYPE_BLOB)
1835
Field_blob *blob= reinterpret_cast<Field_blob*>(*field);
1836
unsigned char* blob_ptr;
1837
uint32_t blob_length= blob->get_length();
1838
blob->get_ptr(&blob_ptr);
1839
err= ib_col_set_value(tuple, colnr, blob_ptr, blob_length);
1843
err= ib_col_set_value(tuple, colnr, (*field)->ptr, (*field)->data_length());
1846
assert (err == DB_SUCCESS);
1848
(**field).move_field_offset(-row_offset);
1854
static uint64_t innobase_get_int_col_max_value(const Field* field)
1856
uint64_t max_value = 0;
1858
switch(field->key_type()) {
1860
case HA_KEYTYPE_BINARY:
1861
max_value = 0xFFULL;
1864
case HA_KEYTYPE_ULONG_INT:
1865
max_value = 0xFFFFFFFFULL;
1867
case HA_KEYTYPE_LONG_INT:
1868
max_value = 0x7FFFFFFFULL;
1871
case HA_KEYTYPE_ULONGLONG:
1872
max_value = 0xFFFFFFFFFFFFFFFFULL;
1874
case HA_KEYTYPE_LONGLONG:
1875
max_value = 0x7FFFFFFFFFFFFFFFULL;
1877
case HA_KEYTYPE_DOUBLE:
1878
/* We use the maximum as per IEEE754-2008 standard, 2^53 */
1879
max_value = 0x20000000000000ULL;
1888
int HailDBCursor::doInsertRecord(unsigned char *record)
1893
ib_trx_t transaction= *get_trx(getTable()->in_use);
1895
tuple= ib_clust_read_tuple_create(cursor);
1897
if (cursor_is_sec_index)
1899
err= ib_cursor_close(cursor);
1900
assert(err == DB_SUCCESS);
1902
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
1904
if (err != DB_SUCCESS)
1905
return ib_err_t_to_drizzle_error(err);
1907
cursor_is_sec_index= false;
1911
ib_cursor_attach_trx(cursor, transaction);
1914
err= ib_cursor_first(cursor);
1915
if (current_session->lex->sql_command == SQLCOM_CREATE_TABLE
1916
&& err == DB_MISSING_HISTORY)
1918
/* See https://bugs.launchpad.net/drizzle/+bug/556978
1920
* In CREATE SELECT, transaction is started in ::store_lock
1921
* at the start of the statement, before the table is created.
1922
* This means the table doesn't exist in our snapshot,
1923
* and we get a DB_MISSING_HISTORY error on ib_cursor_first().
1924
* The way to get around this is to here, restart the transaction
1930
HailDBEngine *storage_engine= static_cast<HailDBEngine*>(getEngine());
1931
err= ib_cursor_reset(cursor);
1932
storage_engine->doCommit(current_session, true);
1933
storage_engine->doStartTransaction(current_session, START_TRANS_NO_OPTIONS);
1934
transaction= *get_trx(getTable()->in_use);
1935
assert(err == DB_SUCCESS);
1936
ib_cursor_attach_trx(cursor, transaction);
1937
err= ib_cursor_first(cursor);
1940
assert(err == DB_SUCCESS || err == DB_END_OF_INDEX);
1943
if (getTable()->next_number_field)
1945
update_auto_increment();
1947
uint64_t temp_auto= getTable()->next_number_field->val_int();
1949
if (temp_auto <= innobase_get_int_col_max_value(getTable()->next_number_field))
1953
uint64_t fetched_auto= share->auto_increment_value;
1955
if (temp_auto >= fetched_auto)
1957
uint64_t store_value= temp_auto+1;
1958
if (store_value == 0)
1961
if (share->auto_increment_value.compare_and_swap(store_value, fetched_auto) == fetched_auto)
1971
write_row_to_haildb_tuple(record, getTable()->getFields(), tuple);
1973
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());
1978
err= ib_cursor_insert_row(cursor, tuple);
1980
if (err == DB_DUPLICATE_KEY)
1982
if (write_can_replace)
1984
store_key_value_from_haildb(getTable()->key_info + getTable()->getShare()->getPrimaryKey(),
1985
ref, ref_length, record);
1987
ib_tpl_t search_tuple= ib_clust_search_tuple_create(cursor);
1989
fill_ib_search_tpl_from_drizzle_key(search_tuple,
1990
getTable()->key_info + 0,
1994
err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
1995
assert(err == DB_SUCCESS);
1996
ib_tuple_delete(search_tuple);
1998
tuple= ib_tuple_clear(tuple);
1999
err= ib_cursor_delete_row(cursor);
2001
err= ib_cursor_first(cursor);
2002
assert(err == DB_SUCCESS || err == DB_END_OF_INDEX);
2004
write_row_to_haildb_tuple(record, getTable()->getFields(), tuple);
2006
err= ib_cursor_insert_row(cursor, tuple);
2007
assert(err==DB_SUCCESS); // probably be nice and process errors
2010
ret= HA_ERR_FOUND_DUPP_KEY;
2012
else if (err != DB_SUCCESS)
2013
ret= ib_err_t_to_drizzle_error(err);
2015
tuple= ib_tuple_clear(tuple);
2016
ib_tuple_delete(tuple);
2018
err= ib_cursor_reset(cursor);
2023
int HailDBCursor::doUpdateRecord(const unsigned char *old_data,
2024
unsigned char *new_data)
2026
ib_tpl_t update_tuple;
2028
bool created_tuple= false;
2030
update_tuple= ib_clust_read_tuple_create(cursor);
2034
ib_trx_t transaction= *get_trx(getTable()->in_use);
2036
if (cursor_is_sec_index)
2038
err= ib_cursor_close(cursor);
2039
assert(err == DB_SUCCESS);
2041
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2043
if (err != DB_SUCCESS)
2044
return ib_err_t_to_drizzle_error(err);
2045
cursor_is_sec_index= false;
2049
ib_cursor_attach_trx(cursor, transaction);
2052
store_key_value_from_haildb(getTable()->key_info + getTable()->getShare()->getPrimaryKey(),
2053
ref, ref_length, old_data);
2055
ib_tpl_t search_tuple= ib_clust_search_tuple_create(cursor);
2057
fill_ib_search_tpl_from_drizzle_key(search_tuple,
2058
getTable()->key_info + 0,
2061
err= ib_cursor_set_lock_mode(cursor, IB_LOCK_X);
2062
assert(err == DB_SUCCESS);
2065
err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
2066
assert(err == DB_SUCCESS);
2068
tuple= ib_clust_read_tuple_create(cursor);
2070
err= ib_cursor_read_row(cursor, tuple);
2071
assert(err == DB_SUCCESS);// FIXME
2073
created_tuple= true;
2076
err= ib_tuple_copy(update_tuple, tuple);
2077
assert(err == DB_SUCCESS);
2079
write_row_to_haildb_tuple(new_data, getTable()->getFields(), update_tuple);
2081
err= ib_cursor_update_row(cursor, tuple, update_tuple);
2083
ib_tuple_delete(update_tuple);
2087
ib_err_t ib_err= ib_cursor_reset(cursor); //fixme check error
2088
assert(ib_err == DB_SUCCESS);
2089
tuple= ib_tuple_clear(tuple);
2090
ib_tuple_delete(tuple);
2094
advance_cursor= true;
2096
return ib_err_t_to_drizzle_error(err);
2099
int HailDBCursor::doDeleteRecord(const unsigned char *)
2103
assert(ib_cursor_is_positioned(cursor) == IB_TRUE);
2104
err= ib_cursor_delete_row(cursor);
2106
advance_cursor= true;
2108
return ib_err_t_to_drizzle_error(err);
2111
int HailDBCursor::delete_all_rows(void)
2113
/* I *think* ib_truncate is non-transactional....
2114
so only support TRUNCATE and not DELETE FROM t;
2115
(this is what ha_innodb does)
2117
if (session_sql_command(getTable()->in_use) != SQLCOM_TRUNCATE)
2118
return HA_ERR_WRONG_COMMAND;
2123
ib_trx_t transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
2125
if (cursor_is_sec_index)
2127
err= ib_cursor_close(cursor);
2128
assert(err == DB_SUCCESS);
2130
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2132
if (err != DB_SUCCESS)
2133
return ib_err_t_to_drizzle_error(err);
2134
cursor_is_sec_index= false;
2138
ib_cursor_attach_trx(cursor, transaction);
2141
err= ib_schema_lock_exclusive(transaction);
2142
if (err != DB_SUCCESS)
2144
ib_err_t rollback_err= ib_trx_rollback(transaction);
2146
push_warning_printf(getTable()->in_use, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
2147
ER_CANT_DELETE_FILE,
2148
_("Cannot Lock HailDB Data Dictionary. HailDB Error %d (%s)\n"),
2149
err, ib_strerror(err));
2151
assert (rollback_err == DB_SUCCESS);
2153
return HA_ERR_GENERIC;
2156
share->auto_increment_value.fetch_and_store(1);
2158
err= ib_cursor_truncate(&cursor, &id);
2159
if (err != DB_SUCCESS)
2162
ib_schema_unlock(transaction);
2163
/* ib_cursor_truncate commits on success */
2165
err= ib_cursor_open_table_using_id(id, NULL, &cursor);
2166
if (err != DB_SUCCESS)
2172
ib_schema_unlock(transaction);
2173
ib_err_t rollback_err= ib_trx_rollback(transaction);
2174
assert(rollback_err == DB_SUCCESS);
2175
return ib_err_t_to_drizzle_error(err);
2178
int HailDBCursor::doStartTableScan(bool)
2180
ib_err_t err= DB_SUCCESS;
2181
ib_trx_t transaction;
2185
in_table_scan= true;
2187
transaction= *get_trx(getTable()->in_use);
2189
assert(transaction != NULL);
2191
if (cursor_is_sec_index)
2193
err= ib_cursor_close(cursor);
2194
assert(err == DB_SUCCESS);
2196
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2197
cursor_is_sec_index= false;
2201
ib_cursor_attach_trx(cursor, transaction);
2204
if (err != DB_SUCCESS)
2205
return ib_err_t_to_drizzle_error(err);
2207
err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
2208
assert(err == DB_SUCCESS); // FIXME
2210
tuple= ib_clust_read_tuple_create(cursor);
2212
err= ib_cursor_first(cursor);
2213
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;
2220
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)
2229
ptrdiff_t row_offset= buf - table->getInsertRecord();
2231
err= ib_cursor_read_row(cursor, tuple);
2233
if (err == DB_RECORD_NOT_FOUND)
2234
return HA_ERR_END_OF_FILE;
2235
if (err != DB_SUCCESS)
2236
return ib_err_t_to_drizzle_error(err);
2240
/* We need the primary key for ::position() to work */
2241
if (table->getShare()->getPrimaryKey() != MAX_KEY)
2242
table->mark_columns_used_by_index_no_reset(table->getShare()->getPrimaryKey());
2244
for (Field **field= table->getFields() ; *field ; field++, colnr++)
2246
if (! (**field).isReadSet())
2247
(**field).setReadSet(); /* Fucking broken API screws us royally. */
2249
(**field).move_field_offset(row_offset);
2251
(**field).setWriteSet();
2253
uint32_t length= ib_col_get_len(tuple, colnr);
2254
if (length == IB_SQL_NULL)
2256
(**field).set_null();
2257
(**field).move_field_offset(-row_offset);
2261
(**field).set_notnull();
2263
if ((**field).type() == DRIZZLE_TYPE_VARCHAR)
2265
(*field)->store((const char*)ib_col_get_value(tuple, colnr),
2269
else if ((**field).type() == DRIZZLE_TYPE_DATE)
2272
err= ib_tuple_read_u32(tuple, colnr, &date_read);
2273
(*field)->store(date_read);
2275
else if ((**field).type() == DRIZZLE_TYPE_BLOB)
2277
if (blobroot == NULL)
2278
(reinterpret_cast<Field_blob*>(*field))->set_ptr(length,
2279
(unsigned char*)ib_col_get_value(tuple,
2283
if (*blobroot == NULL)
2285
*blobroot= new drizzled::memory::Root();
2286
(**blobroot).init_alloc_root();
2289
unsigned char *blob_ptr= (unsigned char*)(**blobroot).alloc_root(length);
2290
memcpy(blob_ptr, ib_col_get_value(tuple, colnr), length);
2291
(reinterpret_cast<Field_blob*>(*field))->set_ptr(length, blob_ptr);
2296
ib_col_copy_value(tuple, colnr, (*field)->ptr, (*field)->data_length());
2299
(**field).move_field_offset(-row_offset);
2301
if (err != DB_SUCCESS)
2302
return ib_err_t_to_drizzle_error(err);
2305
if (has_hidden_primary_key)
2307
err= ib_tuple_read_u64(tuple, colnr, hidden_pkey);
2310
return ib_err_t_to_drizzle_error(err);
2313
int HailDBCursor::rnd_next(unsigned char *buf)
2319
return previous_error;
2323
err= ib_cursor_next(cursor);
2324
if (err != DB_SUCCESS)
2325
return ib_err_t_to_drizzle_error(err);
2328
tuple= ib_tuple_clear(tuple);
2329
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2330
share->has_hidden_primary_key,
2331
&hidden_autoinc_pkey_position);
2333
advance_cursor= true;
2337
int HailDBCursor::doEndTableScan()
2341
ib_tuple_delete(tuple);
2343
err= ib_cursor_reset(cursor);
2344
assert(err == DB_SUCCESS);
2345
in_table_scan= false;
2347
return ib_err_t_to_drizzle_error(err);
2350
int HailDBCursor::rnd_pos(unsigned char *buf, unsigned char *pos)
2355
ib_tpl_t search_tuple= ib_clust_search_tuple_create(cursor);
2357
if (share->has_hidden_primary_key)
2359
err= ib_col_set_value(search_tuple, 0,
2360
((uint64_t*)(pos)), sizeof(uint64_t));
2361
if (err != DB_SUCCESS)
2362
return ib_err_t_to_drizzle_error(err);
2367
if (getTable()->getShare()->getPrimaryKey() != MAX_KEY)
2368
keynr= getTable()->getShare()->getPrimaryKey();
2370
keynr= get_first_unique_index(*getTable());
2372
fill_ib_search_tpl_from_drizzle_key(search_tuple,
2373
getTable()->key_info + keynr,
2377
err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
2378
if (err != DB_SUCCESS)
2379
return ib_err_t_to_drizzle_error(err);
2385
ib_tuple_delete(search_tuple);
2387
tuple= ib_tuple_clear(tuple);
2390
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2391
share->has_hidden_primary_key,
2392
&hidden_autoinc_pkey_position);
2394
advance_cursor= true;
2399
static void store_key_value_from_haildb(KeyInfo *key_info, unsigned char* ref, int ref_len, const unsigned char *record)
2401
KeyPartInfo* key_part= key_info->key_part;
2402
KeyPartInfo* end= key_info->key_part + key_info->key_parts;
2403
unsigned char* ref_start= ref;
2405
memset(ref, 0, ref_len);
2407
for (; key_part != end; key_part++)
2411
if(key_part->null_bit)
2413
*ref= is_null= record[key_part->null_offset] & key_part->null_bit;
2417
Field *field= key_part->field;
2419
if (field->type() == DRIZZLE_TYPE_VARCHAR)
2423
ref+= key_part->length + 2; /* 2 bytes for length */
2428
field->val_str_internal(&str);
2430
*ref++= (char)(str.length() & 0x000000ff);
2431
*ref++= (char)((str.length()>>8) & 0x000000ff);
2433
memcpy(ref, str.ptr(), str.length());
2434
ref+= key_part->length;
2441
ref+= key_part->length;
2445
memcpy(ref, record+key_part->offset, key_part->length);
2446
ref+= key_part->length;
2451
assert(ref == ref_start + ref_len);
2454
void HailDBCursor::position(const unsigned char *record)
2456
if (share->has_hidden_primary_key)
2457
*((uint64_t*) ref)= hidden_autoinc_pkey_position;
2461
if (getTable()->getShare()->getPrimaryKey() != MAX_KEY)
2462
keynr= getTable()->getShare()->getPrimaryKey();
2464
keynr= get_first_unique_index(*getTable());
2466
store_key_value_from_haildb(getTable()->key_info + keynr,
2467
ref, ref_length, record);
2473
double HailDBCursor::scan_time()
2475
ib_table_stats_t table_stats;
2478
err= ib_get_table_statistics(cursor, &table_stats, sizeof(table_stats));
2480
/* Approximate I/O seeks for full table scan */
2481
return (double) (table_stats.stat_clustered_index_size / 16384);
2484
int HailDBCursor::info(uint32_t flag)
2486
ib_table_stats_t table_stats;
2489
if (flag & HA_STATUS_VARIABLE)
2491
err= ib_get_table_statistics(cursor, &table_stats, sizeof(table_stats));
2493
stats.records= table_stats.stat_n_rows;
2495
if (table_stats.stat_n_rows < 2)
2499
stats.data_file_length= table_stats.stat_clustered_index_size;
2500
stats.index_file_length= table_stats.stat_sum_of_other_index_sizes;
2502
stats.mean_rec_length= stats.data_file_length / stats.records;
2505
if (flag & HA_STATUS_AUTO)
2506
stats.auto_increment_value= 1;
2508
if (flag & HA_STATUS_ERRKEY) {
2509
const char *err_table_name;
2510
const char *err_index_name;
2512
ib_trx_t transaction= *get_trx(getTable()->in_use);
2514
err= ib_get_duplicate_key(transaction, &err_table_name, &err_index_name);
2518
for (unsigned int i = 0; i < getTable()->getShare()->keys; i++)
2520
if (strcmp(err_index_name, getTable()->key_info[i].name) == 0)
2532
int HailDBCursor::doStartIndexScan(uint32_t keynr, bool)
2535
ib_trx_t transaction= *get_trx(getTable()->in_use);
2537
active_index= keynr;
2539
if (active_index == 0 && ! share->has_hidden_primary_key)
2541
if (cursor_is_sec_index)
2543
err= ib_cursor_close(cursor);
2544
assert(err == DB_SUCCESS);
2546
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2548
if (err != DB_SUCCESS)
2549
return ib_err_t_to_drizzle_error(err);
2554
ib_cursor_attach_trx(cursor, transaction);
2557
cursor_is_sec_index= false;
2558
tuple= ib_clust_read_tuple_create(cursor);
2563
err= ib_index_get_id(table_path_to_haildb_name(getShare()->getPath()),
2564
getShare()->getKeyInfo(keynr).name,
2566
if (err != DB_SUCCESS)
2567
return ib_err_t_to_drizzle_error(err);
2569
err= ib_cursor_close(cursor);
2570
assert(err == DB_SUCCESS);
2572
err= ib_cursor_open_index_using_id(index_id, transaction, &cursor);
2574
if (err != DB_SUCCESS)
2575
return ib_err_t_to_drizzle_error(err);
2577
cursor_is_sec_index= true;
2579
tuple= ib_clust_read_tuple_create(cursor);
2580
ib_cursor_set_cluster_access(cursor);
2583
err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
2584
assert(err == DB_SUCCESS);
2586
advance_cursor= false;
2590
static ib_srch_mode_t ha_rkey_function_to_ib_srch_mode(drizzled::ha_rkey_function find_flag)
2594
case HA_READ_KEY_EXACT:
2596
case HA_READ_KEY_OR_NEXT:
2598
case HA_READ_KEY_OR_PREV:
2600
case HA_READ_AFTER_KEY:
2602
case HA_READ_BEFORE_KEY:
2604
case HA_READ_PREFIX:
2606
case HA_READ_PREFIX_LAST:
2608
case HA_READ_PREFIX_LAST_OR_PREV:
2610
case HA_READ_MBR_CONTAIN:
2611
case HA_READ_MBR_INTERSECT:
2612
case HA_READ_MBR_WITHIN:
2613
case HA_READ_MBR_DISJOINT:
2614
case HA_READ_MBR_EQUAL:
2615
assert(false); /* these just exist in the enum, not used. */
2619
/* Must return or compiler complains about reaching end of function */
2620
return (ib_srch_mode_t)0;
2623
static void fill_ib_search_tpl_from_drizzle_key(ib_tpl_t search_tuple,
2624
const drizzled::KeyInfo *key_info,
2625
const unsigned char *key_ptr,
2628
KeyPartInfo *key_part= key_info->key_part;
2629
KeyPartInfo *end= key_part + key_info->key_parts;
2630
const unsigned char *buff= key_ptr;
2635
for(; key_part != end && buff < key_ptr + key_len; key_part++)
2637
Field *field= key_part->field;
2638
bool is_null= false;
2640
if (key_part->null_bit)
2645
err= ib_col_set_value(search_tuple, fieldnr, NULL, IB_SQL_NULL);
2646
assert(err == DB_SUCCESS);
2651
if (field->type() == DRIZZLE_TYPE_VARCHAR)
2655
buff+= key_part->length + 2; /* 2 bytes length */
2659
int length= *buff + (*(buff + 1) << 8);
2661
err= ib_col_set_value(search_tuple, fieldnr, buff, length);
2662
assert(err == DB_SUCCESS);
2664
buff+= key_part->length;
2666
else if (field->type() == DRIZZLE_TYPE_DATE)
2668
uint32_t date_int= static_cast<uint32_t>(field->val_int());
2669
err= ib_col_set_value(search_tuple, fieldnr, &date_int, 4);
2670
buff+= key_part->length;
2677
buff+= key_part->length;
2681
err= ib_col_set_value(search_tuple, fieldnr,
2682
buff, key_part->length);
2683
assert(err == DB_SUCCESS);
2685
buff+= key_part->length;
2691
assert(buff == key_ptr + key_len);
2694
int HailDBCursor::haildb_index_read(unsigned char *buf,
2695
const unsigned char *key_ptr,
2697
drizzled::ha_rkey_function find_flag,
2698
bool allocate_blobs)
2700
ib_tpl_t search_tuple;
2704
ib_srch_mode_t search_mode;
2706
search_mode= ha_rkey_function_to_ib_srch_mode(find_flag);
2708
if (active_index == 0 && ! share->has_hidden_primary_key)
2709
search_tuple= ib_clust_search_tuple_create(cursor);
2711
search_tuple= ib_sec_search_tuple_create(cursor);
2713
fill_ib_search_tpl_from_drizzle_key(search_tuple,
2714
getTable()->key_info + active_index,
2717
err= ib_cursor_moveto(cursor, search_tuple, search_mode, &res);
2718
ib_tuple_delete(search_tuple);
2720
if ((err == DB_RECORD_NOT_FOUND || err == DB_END_OF_INDEX))
2722
getTable()->status= STATUS_NOT_FOUND;
2723
return HA_ERR_KEY_NOT_FOUND;
2726
if (err != DB_SUCCESS)
2728
return ib_err_t_to_drizzle_error(err);
2731
tuple= ib_tuple_clear(tuple);
2732
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2733
share->has_hidden_primary_key,
2734
&hidden_autoinc_pkey_position,
2735
(allocate_blobs)? &blobroot : NULL);
2737
getTable()->status= 0;
2739
getTable()->status= STATUS_NOT_FOUND;
2741
advance_cursor= true;
2746
int HailDBCursor::index_read(unsigned char *buf,
2747
const unsigned char *key_ptr,
2749
drizzled::ha_rkey_function find_flag)
2751
return haildb_index_read(buf, key_ptr, key_len, find_flag, false);
2754
/* This is straight from cursor.cc, but it's private there :( */
2755
uint32_t HailDBCursor::calculate_key_len(uint32_t key_position,
2756
key_part_map keypart_map_arg)
2758
/* works only with key prefixes */
2759
assert(((keypart_map_arg + 1) & keypart_map_arg) == 0);
2761
KeyPartInfo *key_part_found= getTable()->getShare()->getKeyInfo(key_position).key_part;
2762
KeyPartInfo *end_key_part_found= key_part_found + getTable()->getShare()->getKeyInfo(key_position).key_parts;
2765
while (key_part_found < end_key_part_found && keypart_map_arg)
2767
length+= key_part_found->store_length;
2768
keypart_map_arg >>= 1;
2775
int HailDBCursor::haildb_index_read_map(unsigned char * buf,
2776
const unsigned char *key,
2777
key_part_map keypart_map,
2778
enum ha_rkey_function find_flag,
2779
bool allocate_blobs)
2781
uint32_t key_len= calculate_key_len(active_index, keypart_map);
2782
return haildb_index_read(buf, key, key_len, find_flag, allocate_blobs);
2785
int HailDBCursor::index_read_idx_map(unsigned char * buf,
2787
const unsigned char * key,
2788
key_part_map keypart_map,
2789
enum ha_rkey_function find_flag)
2792
error= doStartIndexScan(index, 0);
2795
error= haildb_index_read_map(buf, key, keypart_map, find_flag, true);
2796
error1= doEndIndexScan();
2798
return error ? error : error1;
2801
int HailDBCursor::reset()
2804
blobroot->free_root(MYF(0));
2809
int HailDBCursor::index_next(unsigned char *buf)
2811
int ret= HA_ERR_END_OF_FILE;
2815
ib_err_t err= ib_cursor_next(cursor);
2816
if (err == DB_END_OF_INDEX)
2817
return HA_ERR_END_OF_FILE;
2820
tuple= ib_tuple_clear(tuple);
2821
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2822
share->has_hidden_primary_key,
2823
&hidden_autoinc_pkey_position);
2825
advance_cursor= true;
2829
int HailDBCursor::doEndIndexScan()
2831
active_index= MAX_KEY;
2833
return doEndTableScan();
2836
int HailDBCursor::index_prev(unsigned char *buf)
2838
int ret= HA_ERR_END_OF_FILE;
2843
err= ib_cursor_prev(cursor);
2844
if (err != DB_SUCCESS)
2846
if (err == DB_END_OF_INDEX)
2847
return HA_ERR_END_OF_FILE;
2849
return ib_err_t_to_drizzle_error(err);
2853
tuple= ib_tuple_clear(tuple);
2854
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2855
share->has_hidden_primary_key,
2856
&hidden_autoinc_pkey_position);
2858
advance_cursor= true;
2864
int HailDBCursor::index_first(unsigned char *buf)
2866
int ret= HA_ERR_END_OF_FILE;
2869
err= ib_cursor_first(cursor);
2870
if (err != DB_SUCCESS)
2871
return ib_err_t_to_drizzle_error(err);
2873
tuple= ib_tuple_clear(tuple);
2874
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2875
share->has_hidden_primary_key,
2876
&hidden_autoinc_pkey_position);
2878
advance_cursor= true;
2884
int HailDBCursor::index_last(unsigned char *buf)
2886
int ret= HA_ERR_END_OF_FILE;
2889
err= ib_cursor_last(cursor);
2890
if (err != DB_SUCCESS)
2891
return ib_err_t_to_drizzle_error(err);
2893
tuple= ib_tuple_clear(tuple);
2894
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2895
share->has_hidden_primary_key,
2896
&hidden_autoinc_pkey_position);
2897
advance_cursor= true;
2902
int HailDBCursor::extra(enum ha_extra_function operation)
2906
case HA_EXTRA_FLUSH:
2908
blobroot->free_root(MYF(0));
2910
case HA_EXTRA_WRITE_CAN_REPLACE:
2911
write_can_replace= true;
2913
case HA_EXTRA_WRITE_CANNOT_REPLACE:
2914
write_can_replace= false;
2923
static int create_table_message_table()
2925
ib_tbl_sch_t schema;
2926
ib_idx_sch_t index_schema;
2927
ib_trx_t transaction;
2929
ib_err_t err, rollback_err;
2930
ib_bool_t create_db_err;
2932
create_db_err= ib_database_create("data_dictionary");
2933
if (create_db_err != IB_TRUE)
2936
err= ib_table_schema_create(HAILDB_TABLE_DEFINITIONS_TABLE, &schema,
2938
if (err != DB_SUCCESS)
2941
err= ib_table_schema_add_col(schema, "table_name", IB_VARCHAR, IB_COL_NONE, 0,
2942
IB_MAX_TABLE_NAME_LEN);
2943
if (err != DB_SUCCESS)
2946
err= ib_table_schema_add_col(schema, "message", IB_BLOB, IB_COL_NONE, 0, 0);
2947
if (err != DB_SUCCESS)
2950
err= ib_table_schema_add_index(schema, "PRIMARY_KEY", &index_schema);
2951
if (err != DB_SUCCESS)
2954
err= ib_index_schema_add_col(index_schema, "table_name", 0);
2955
if (err != DB_SUCCESS)
2957
err= ib_index_schema_set_clustered(index_schema);
2958
if (err != DB_SUCCESS)
2961
transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
2962
err= ib_schema_lock_exclusive(transaction);
2963
if (err != DB_SUCCESS)
2966
err= ib_table_create(transaction, schema, &table_id);
2967
if (err != DB_SUCCESS)
2970
err= ib_trx_commit(transaction);
2971
if (err != DB_SUCCESS)
2974
ib_table_schema_delete(schema);
2978
ib_schema_unlock(transaction);
2979
rollback_err= ib_trx_rollback(transaction);
2980
assert(rollback_err == DB_SUCCESS);
2982
ib_table_schema_delete(schema);
2986
static bool innobase_use_doublewrite= true;
2987
static bool srv_file_per_table= false;
2988
static bool innobase_adaptive_hash_index;
2989
static bool srv_adaptive_flushing;
2990
static bool innobase_print_verbose_log;
2991
static bool innobase_rollback_on_timeout;
2992
static bool innobase_create_status_file;
2993
static bool srv_use_sys_malloc;
2994
static string innobase_file_format_name;
2995
typedef constrained_check<unsigned int, 1000, 1> autoextend_constraint;
2996
static autoextend_constraint srv_auto_extend_increment;
2997
typedef constrained_check<size_t, SIZE_MAX, 5242880, 1048576> buffer_pool_constraint;
2998
static buffer_pool_constraint innobase_buffer_pool_size;
2999
typedef constrained_check<size_t, SIZE_MAX, 512, 1024> additional_mem_pool_constraint;
3000
static additional_mem_pool_constraint innobase_additional_mem_pool_size;
3001
static bool innobase_use_checksums= true;
3002
typedef constrained_check<unsigned int, UINT_MAX, 100> io_capacity_constraint;
3003
typedef constrained_check<uint32_t, 2, 0> trinary_constraint;
3004
static trinary_constraint innobase_fast_shutdown;
3005
static trinary_constraint srv_flush_log_at_trx_commit;
3006
typedef constrained_check<uint32_t, 6, 0> force_recovery_constraint;
3007
static force_recovery_constraint innobase_force_recovery;
3008
typedef constrained_check<int64_t, INT64_MAX, 1024*1024, 1024*1024> log_file_constraint;
3009
static log_file_constraint haildb_log_file_size;
3011
static io_capacity_constraint srv_io_capacity;
3012
typedef constrained_check<unsigned int, 100, 2> log_files_in_group_constraint;
3013
static log_files_in_group_constraint haildb_log_files_in_group;
3014
typedef constrained_check<unsigned int, 1024*1024*1024, 1> lock_wait_constraint;
3015
static lock_wait_constraint innobase_lock_wait_timeout;
3016
typedef constrained_check<long, LONG_MAX, 256*1024, 1024> log_buffer_size_constraint;
3017
static log_buffer_size_constraint innobase_log_buffer_size;
3018
typedef constrained_check<unsigned int, 97, 5> lru_old_blocks_constraint;
3019
static lru_old_blocks_constraint innobase_lru_old_blocks_pct;
3020
typedef constrained_check<unsigned int, 99, 0> max_dirty_pages_constraint;
3021
static max_dirty_pages_constraint haildb_max_dirty_pages_pct;
3022
static uint64_constraint haildb_max_purge_lag;
3023
static uint64_constraint haildb_sync_spin_loops;
3024
typedef constrained_check<uint32_t, UINT32_MAX, 10> open_files_constraint;
3025
static open_files_constraint haildb_open_files;
3026
typedef constrained_check<unsigned int, 64, 1> io_threads_constraint;
3027
static io_threads_constraint haildb_read_io_threads;
3028
static io_threads_constraint haildb_write_io_threads;
3031
static uint32_t innobase_lru_block_access_recency;
3035
static int haildb_file_format_name_validate(Session*, set_var *var)
3038
const char *format= var->value->str_value.ptr();
3042
ib_err_t err= ib_cfg_set_text("file_format", format);
3044
if (err == DB_SUCCESS)
3046
innobase_file_format_name= format;
3053
static void haildb_lru_old_blocks_pct_update(Session*, sql_var_t)
3055
int ret= ib_cfg_set_int("lru_old_blocks_pct", static_cast<uint32_t>(innobase_lru_old_blocks_pct));
3059
static void haildb_lru_block_access_recency_update(Session*, sql_var_t)
3061
int ret= ib_cfg_set_int("lru_block_access_recency", static_cast<uint32_t>(innobase_lru_block_access_recency));
3065
static void haildb_status_file_update(Session*, sql_var_t)
3069
if (innobase_create_status_file)
3070
err= ib_cfg_set_bool_on("status_file");
3072
err= ib_cfg_set_bool_off("status_file");
3076
extern "C" int haildb_errmsg_callback(ib_msg_stream_t, const char *fmt, ...);
3079
extern bool volatile shutdown_in_progress;
3082
extern "C" int haildb_errmsg_callback(ib_msg_stream_t, const char *fmt, ...)
3086
va_start(args, fmt);
3087
if (! shutdown_in_progress)
3088
r= plugin::ErrorMessage::vprintf(NULL, ERRMSG_LVL_WARN, fmt, args);
3090
vfprintf(stderr, fmt, args);
3096
static int haildb_init(drizzled::module::Context &context)
3098
haildb_system_table_names.insert(std::string("HAILDB_SYS_TABLES"));
3099
haildb_system_table_names.insert(std::string("HAILDB_SYS_COLUMNS"));
3100
haildb_system_table_names.insert(std::string("HAILDB_SYS_INDEXES"));
3101
haildb_system_table_names.insert(std::string("HAILDB_SYS_FIELDS"));
3102
haildb_system_table_names.insert(std::string("HAILDB_SYS_FOREIGN"));
3103
haildb_system_table_names.insert(std::string("HAILDB_SYS_FOREIGN_COLS"));
3105
const module::option_map &vm= context.getOptions();
3107
/* Inverted Booleans */
3109
innobase_adaptive_hash_index= (vm.count("disable-adaptive-hash-index")) ? false : true;
3110
srv_adaptive_flushing= (vm.count("disable-adaptive-flushing")) ? false : true;
3111
innobase_use_checksums= (vm.count("disable-checksums")) ? false : true;
3112
innobase_use_doublewrite= (vm.count("disable-doublewrite")) ? false : true;
3113
innobase_print_verbose_log= (vm.count("disable-print-verbose-log")) ? false : true;
3114
srv_use_sys_malloc= (vm.count("use-internal-malloc")) ? false : true;
3120
if (err != DB_SUCCESS)
3123
ib_logger_set(haildb_errmsg_callback, NULL);
3125
if (not vm["data-home-dir"].as<string>().empty())
3127
err= ib_cfg_set_text("data_home_dir", vm["data-home-dir"].as<string>().c_str());
3128
if (err != DB_SUCCESS)
3132
if (vm.count("log-group-home-dir"))
3134
err= ib_cfg_set_text("log_group_home_dir", vm["log-group-home-dir"].as<string>().c_str());
3135
if (err != DB_SUCCESS)
3139
if (innobase_print_verbose_log)
3140
err= ib_cfg_set_bool_on("print_verbose_log");
3142
err= ib_cfg_set_bool_off("print_verbose_log");
3144
if (err != DB_SUCCESS)
3147
if (innobase_rollback_on_timeout)
3148
err= ib_cfg_set_bool_on("rollback_on_timeout");
3150
err= ib_cfg_set_bool_off("rollback_on_timeout");
3152
if (err != DB_SUCCESS)
3155
if (innobase_use_doublewrite)
3156
err= ib_cfg_set_bool_on("doublewrite");
3158
err= ib_cfg_set_bool_off("doublewrite");
3160
if (err != DB_SUCCESS)
3163
if (innobase_adaptive_hash_index)
3164
err= ib_cfg_set_bool_on("adaptive_hash_index");
3166
err= ib_cfg_set_bool_off("adaptive_hash_index");
3168
if (err != DB_SUCCESS)
3171
if (srv_adaptive_flushing)
3172
err= ib_cfg_set_bool_on("adaptive_flushing");
3174
err= ib_cfg_set_bool_off("adaptive_flushing");
3176
if (err != DB_SUCCESS)
3179
err= ib_cfg_set_int("additional_mem_pool_size", innobase_additional_mem_pool_size.get());
3180
if (err != DB_SUCCESS)
3183
err= ib_cfg_set_int("autoextend_increment", srv_auto_extend_increment.get());
3184
if (err != DB_SUCCESS)
3187
err= ib_cfg_set_int("buffer_pool_size", innobase_buffer_pool_size.get());
3188
if (err != DB_SUCCESS)
3191
err= ib_cfg_set_int("io_capacity", srv_io_capacity.get());
3192
if (err != DB_SUCCESS)
3195
if (srv_file_per_table)
3196
err= ib_cfg_set_bool_on("file_per_table");
3198
err= ib_cfg_set_bool_off("file_per_table");
3200
if (err != DB_SUCCESS)
3203
err= ib_cfg_set_int("flush_log_at_trx_commit",
3204
srv_flush_log_at_trx_commit.get());
3205
if (err != DB_SUCCESS)
3208
if (vm.count("flush-method") != 0)
3210
err= ib_cfg_set_text("flush_method",
3211
vm["flush-method"].as<string>().c_str());
3212
if (err != DB_SUCCESS)
3216
err= ib_cfg_set_int("force_recovery",
3217
innobase_force_recovery.get());
3218
if (err != DB_SUCCESS)
3221
err= ib_cfg_set_text("data_file_path", vm["data-file-path"].as<string>().c_str());
3222
if (err != DB_SUCCESS)
3225
err= ib_cfg_set_int("log_file_size", haildb_log_file_size.get());
3226
if (err != DB_SUCCESS)
3229
err= ib_cfg_set_int("log_buffer_size", innobase_log_buffer_size.get());
3230
if (err != DB_SUCCESS)
3233
err= ib_cfg_set_int("log_files_in_group", haildb_log_files_in_group.get());
3234
if (err != DB_SUCCESS)
3237
err= ib_cfg_set_int("checksums", innobase_use_checksums);
3238
if (err != DB_SUCCESS)
3241
err= ib_cfg_set_int("lock_wait_timeout", innobase_lock_wait_timeout.get());
3242
if (err != DB_SUCCESS)
3245
err= ib_cfg_set_int("max_dirty_pages_pct", haildb_max_dirty_pages_pct.get());
3246
if (err != DB_SUCCESS)
3249
err= ib_cfg_set_int("max_purge_lag", haildb_max_purge_lag.get());
3250
if (err != DB_SUCCESS)
3253
err= ib_cfg_set_int("open_files", haildb_open_files.get());
3254
if (err != DB_SUCCESS)
3257
err= ib_cfg_set_int("read_io_threads", haildb_read_io_threads.get());
3258
if (err != DB_SUCCESS)
3261
err= ib_cfg_set_int("write_io_threads", haildb_write_io_threads.get());
3262
if (err != DB_SUCCESS)
3265
err= ib_cfg_set_int("sync_spin_loops", haildb_sync_spin_loops.get());
3266
if (err != DB_SUCCESS)
3269
if (srv_use_sys_malloc)
3270
err= ib_cfg_set_bool_on("use_sys_malloc");
3272
err= ib_cfg_set_bool_off("use_sys_malloc");
3274
if (err != DB_SUCCESS)
3277
err= ib_startup(innobase_file_format_name.c_str());
3278
if (err != DB_SUCCESS)
3281
create_table_message_table();
3283
haildb_engine= new HailDBEngine("InnoDB");
3284
context.add(haildb_engine);
3285
context.registerVariable(new sys_var_bool_ptr_readonly("adaptive_hash_index",
3286
&innobase_adaptive_hash_index));
3287
context.registerVariable(new sys_var_bool_ptr_readonly("adaptive_flushing",
3288
&srv_adaptive_flushing));
3289
context.registerVariable(new sys_var_constrained_value_readonly<size_t>("additional_mem_pool_size",innobase_additional_mem_pool_size));
3290
context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("autoextend_increment", srv_auto_extend_increment));
3291
context.registerVariable(new sys_var_constrained_value_readonly<size_t>("buffer_pool_size", innobase_buffer_pool_size));
3292
context.registerVariable(new sys_var_bool_ptr_readonly("checksums",
3293
&innobase_use_checksums));
3294
context.registerVariable(new sys_var_bool_ptr_readonly("doublewrite",
3295
&innobase_use_doublewrite));
3296
context.registerVariable(new sys_var_const_string_val("data_file_path",
3297
vm["data-file-path"].as<string>()));
3298
context.registerVariable(new sys_var_const_string_val("data_home_dir",
3299
vm["data-home-dir"].as<string>()));
3300
context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("io_capacity", srv_io_capacity));
3301
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("fast_shutdown", innobase_fast_shutdown));
3302
context.registerVariable(new sys_var_bool_ptr_readonly("file_per_table",
3303
&srv_file_per_table));
3304
context.registerVariable(new sys_var_bool_ptr_readonly("rollback_on_timeout",
3305
&innobase_rollback_on_timeout));
3306
context.registerVariable(new sys_var_bool_ptr_readonly("print_verbose_log",
3307
&innobase_print_verbose_log));
3308
context.registerVariable(new sys_var_bool_ptr("status_file",
3309
&innobase_create_status_file,
3310
haildb_status_file_update));
3311
context.registerVariable(new sys_var_bool_ptr_readonly("use_sys_malloc",
3312
&srv_use_sys_malloc));
3313
context.registerVariable(new sys_var_std_string("file_format",
3314
innobase_file_format_name,
3315
haildb_file_format_name_validate));
3316
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("flush_log_at_trx_commit", srv_flush_log_at_trx_commit));
3317
context.registerVariable(new sys_var_const_string_val("flush_method",
3318
vm.count("flush-method") ? vm["flush-method"].as<string>() : ""));
3319
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("force_recovery", innobase_force_recovery));
3320
context.registerVariable(new sys_var_const_string_val("log_group_home_dir",
3321
vm.count("log-group-home-dir") ? vm["log-group-home-dir"].as<string>() : ""));
3322
context.registerVariable(new sys_var_constrained_value<int64_t>("log_file_size", haildb_log_file_size));
3323
context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("log_files_in_group", haildb_log_files_in_group));
3324
context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("lock_wait_timeout", innobase_lock_wait_timeout));
3325
context.registerVariable(new sys_var_constrained_value_readonly<long>("log_buffer_size", innobase_log_buffer_size));
3326
context.registerVariable(new sys_var_constrained_value<unsigned int>("lru_old_blocks_pct", innobase_lru_old_blocks_pct, haildb_lru_old_blocks_pct_update));
3327
context.registerVariable(new sys_var_uint32_t_ptr("lru_block_access_recency",
3328
&innobase_lru_block_access_recency,
3329
haildb_lru_block_access_recency_update));
3330
context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("max_dirty_pages_pct", haildb_max_dirty_pages_pct));
3331
context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("max_purge_lag", haildb_max_purge_lag));
3332
context.registerVariable(new sys_var_constrained_value_readonly<uint64_t>("sync_spin_loops", haildb_sync_spin_loops));
3333
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("open_files", haildb_open_files));
3334
context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("read_io_threads", haildb_read_io_threads));
3335
context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("write_io_threads", haildb_write_io_threads));
3337
haildb_datadict_dump_func_initialize(context);
3338
config_table_function_initialize(context);
3339
status_table_function_initialize(context);
3343
fprintf(stderr, _("Error starting HailDB %d (%s)\n"),
3344
err, ib_strerror(err));
3349
HailDBEngine::~HailDBEngine()
3352
ib_shutdown_t shutdown_flag= IB_SHUTDOWN_NORMAL;
3354
if (innobase_fast_shutdown.get() == 1)
3355
shutdown_flag= IB_SHUTDOWN_NO_IBUFMERGE_PURGE;
3356
else if (innobase_fast_shutdown.get() == 2)
3357
shutdown_flag= IB_SHUTDOWN_NO_BUFPOOL_FLUSH;
3359
err= ib_shutdown(shutdown_flag);
3361
if (err != DB_SUCCESS)
3363
fprintf(stderr,"Error %d shutting down HailDB!\n", err);
3369
static void init_options(drizzled::module::option_context &context)
3371
context("disable-adaptive-hash-index",
3372
N_("Disable HailDB adaptive hash index (enabled by default)."));
3373
context("disable-adaptive-flushing",
3374
N_("Do not attempt to flush dirty pages to avoid IO bursts at checkpoints."));
3375
context("additional-mem-pool-size",
3376
po::value<additional_mem_pool_constraint>(&innobase_additional_mem_pool_size)->default_value(8*1024*1024L),
3377
N_("Size of a memory pool HailDB uses to store data dictionary information and other internal data structures."));
3378
context("autoextend-increment",
3379
po::value<autoextend_constraint>(&srv_auto_extend_increment)->default_value(8),
3380
N_("Data file autoextend increment in megabytes"));
3381
context("buffer-pool-size",
3382
po::value<buffer_pool_constraint>(&innobase_buffer_pool_size)->default_value(128*1024*1024L),
3383
N_("The size of the memory buffer HailDB uses to cache data and indexes of its tables."));
3384
context("data-home-dir",
3385
po::value<string>()->default_value(""),
3386
N_("The common part for HailDB table spaces."));
3387
context("disable-checksums",
3388
N_("Disable HailDB checksums validation (enabled by default)."));
3389
context("disable-doublewrite",
3390
N_("Disable HailDB doublewrite buffer (enabled by default)."));
3391
context("io-capacity",
3392
po::value<io_capacity_constraint>(&srv_io_capacity)->default_value(200),
3393
N_("Number of IOPs the server can do. Tunes the background IO rate"));
3394
context("fast-shutdown",
3395
po::value<trinary_constraint>(&innobase_fast_shutdown)->default_value(1),
3396
N_("Speeds up the shutdown process of the HailDB storage engine. Possible values are 0, 1 (faster) or 2 (fastest - crash-like)."));
3397
context("file-per-table",
3398
po::value<bool>(&srv_file_per_table)->default_value(false)->zero_tokens(),
3399
N_("Stores each HailDB table to an .ibd file in the database dir."));
3400
context("file-format",
3401
po::value<string>(&innobase_file_format_name)->default_value("Barracuda"),
3402
N_("File format to use for new tables in .ibd files."));
3403
context("flush-log-at-trx-commit",
3404
po::value<trinary_constraint>(&srv_flush_log_at_trx_commit)->default_value(1),
3405
N_("Set to 0 (write and flush once per second),1 (write and flush at each commit) or 2 (write at commit, flush once per second)."));
3406
context("flush-method",
3407
po::value<string>(),
3408
N_("With which method to flush data."));
3409
context("force-recovery",
3410
po::value<force_recovery_constraint>(&innobase_force_recovery)->default_value(0),
3411
N_("Helps to save your data in case the disk image of the database becomes corrupt."));
3412
context("data-file-path",
3413
po::value<string>()->default_value("ibdata1:10M:autoextend"),
3414
N_("Path to individual files and their sizes."));
3415
context("log-group-home-dir",
3416
po::value<string>(),
3417
N_("Path to HailDB log files."));
3418
context("log-file-size",
3419
po::value<log_file_constraint>(&haildb_log_file_size)->default_value(20*1024*1024L),
3420
N_("Size of each log file in a log group."));
3421
context("haildb-log-files-in-group",
3422
po::value<log_files_in_group_constraint>(&haildb_log_files_in_group)->default_value(2),
3423
N_("Number of log files in the log group. HailDB writes to the files in a circular fashion. Value 3 is recommended here."));
3424
context("lock-wait-timeout",
3425
po::value<lock_wait_constraint>(&innobase_lock_wait_timeout)->default_value(5),
3426
N_("Timeout in seconds an HailDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout."));
3427
context("log-buffer-size",
3428
po::value<log_buffer_size_constraint>(&innobase_log_buffer_size)->default_value(8*1024*1024L),
3429
N_("The size of the buffer which HailDB uses to write log to the log files on disk."));
3430
context("lru-old-blocks-pct",
3431
po::value<lru_old_blocks_constraint>(&innobase_lru_old_blocks_pct)->default_value(37),
3432
N_("Sets the point in the LRU list from where all pages are classified as old (Advanced users)"));
3433
context("lru-block-access-recency",
3434
po::value<uint32_t>(&innobase_lru_block_access_recency)->default_value(0),
3435
N_("Milliseconds between accesses to a block at which it is made young. 0=disabled (Advanced users)"));
3436
context("max-dirty-pages-pct",
3437
po::value<max_dirty_pages_constraint>(&haildb_max_dirty_pages_pct)->default_value(75),
3438
N_("Percentage of dirty pages allowed in bufferpool."));
3439
context("max-purge-lag",
3440
po::value<uint64_constraint>(&haildb_max_purge_lag)->default_value(0),
3441
N_("Desired maximum length of the purge queue (0 = no limit)"));
3442
context("rollback-on-timeout",
3443
po::value<bool>(&innobase_rollback_on_timeout)->default_value(false)->zero_tokens(),
3444
N_("Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)"));
3445
context("open-files",
3446
po::value<open_files_constraint>(&haildb_open_files)->default_value(300),
3447
N_("How many files at the maximum HailDB keeps open at the same time."));
3448
context("read-io-threads",
3449
po::value<io_threads_constraint>(&haildb_read_io_threads)->default_value(4),
3450
N_("Number of background read I/O threads in HailDB."));
3451
context("write-io-threads",
3452
po::value<io_threads_constraint>(&haildb_write_io_threads)->default_value(4),
3453
N_("Number of background write I/O threads in HailDB."));
3454
context("disable-print-verbose-log",
3455
N_("Disable if you want to reduce the number of messages written to the log (default: enabled)."));
3456
context("status-file",
3457
po::value<bool>(&innobase_create_status_file)->default_value(false)->zero_tokens(),
3458
N_("Enable SHOW HAILDB STATUS output in the log"));
3459
context("sync-spin-loops",
3460
po::value<uint64_constraint>(&haildb_sync_spin_loops)->default_value(30L),
3461
N_("Count of spin-loop rounds in HailDB mutexes (30 by default)"));
3462
context("use-internal-malloc",
3463
N_("Use HailDB's internal memory allocator instead of the OS memory allocator"));
3466
DRIZZLE_DECLARE_PLUGIN
3472
"Transactional Storage Engine using the HailDB Library",
3474
haildb_init, /* Plugin Init */
3475
NULL, /* system variables */
3476
init_options /* config options */
3478
DRIZZLE_DECLARE_PLUGIN_END;