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>
83
#include <boost/algorithm/string.hpp>
84
#include <boost/unordered_set.hpp>
85
#include <boost/foreach.hpp>
88
#include <drizzled/message/table.pb.h>
89
#include "drizzled/internal/m_string.h"
91
#include "drizzled/global_charset_info.h"
93
#include "haildb_datadict_dump_func.h"
94
#include "config_table_function.h"
95
#include "status_table_function.h"
99
#include "haildb_engine.h"
101
#include <drizzled/field.h>
102
#include "drizzled/field/timestamp.h" // needed for UPDATE NOW()
103
#include "drizzled/field/blob.h"
104
#include "drizzled/field/enum.h"
105
#include <drizzled/session.h>
106
#include <boost/program_options.hpp>
107
#include <drizzled/module/option_map.h>
109
#include <drizzled/charset.h>
111
namespace po= boost::program_options;
112
#include <boost/algorithm/string.hpp>
115
using namespace google;
116
using namespace drizzled;
118
int read_row_from_haildb(unsigned char* buf, ib_crsr_t cursor, ib_tpl_t tuple, Table* table, bool has_hidden_primary_key, uint64_t *hidden_pkey, drizzled::memory::Root **blobroot= NULL);
119
static void fill_ib_search_tpl_from_drizzle_key(ib_tpl_t search_tuple,
120
const drizzled::KeyInfo *key_info,
121
const unsigned char *key_ptr,
123
static void store_key_value_from_haildb(KeyInfo *key_info, unsigned char* ref, int ref_len, const unsigned char *record);
125
#define HAILDB_EXT ".EID"
127
const char HAILDB_TABLE_DEFINITIONS_TABLE[]= "data_dictionary/haildb_table_definitions";
128
const string statement_savepoint_name("STATEMENT");
130
static boost::unordered_set<std::string> haildb_system_table_names;
133
static const char *HailDBCursor_exts[] = {
137
class HailDBEngine : public drizzled::plugin::TransactionalStorageEngine
140
HailDBEngine(const string &name_arg)
141
: drizzled::plugin::TransactionalStorageEngine(name_arg,
143
HTON_CAN_INDEX_BLOBS |
145
HTON_PARTIAL_COLUMN_READ |
146
HTON_HAS_DOES_TRANSACTIONS)
148
table_definition_ext= HAILDB_EXT;
153
virtual Cursor *create(Table &table)
155
return new HailDBCursor(*this, table);
158
const char **bas_ext() const {
159
return HailDBCursor_exts;
162
bool validateCreateTableOption(const std::string &key,
163
const std::string &state);
165
int doCreateTable(Session&,
167
const drizzled::TableIdentifier &identifier,
168
drizzled::message::Table& proto);
170
int doDropTable(Session&, const TableIdentifier &identifier);
172
int doRenameTable(drizzled::Session&,
173
const drizzled::TableIdentifier&,
174
const drizzled::TableIdentifier&);
176
int doGetTableDefinition(Session& session,
177
const TableIdentifier &identifier,
178
drizzled::message::Table &table_proto);
180
bool doDoesTableExist(Session&, const TableIdentifier &identifier);
183
void getTableNamesInSchemaFromHailDB(const drizzled::SchemaIdentifier &schema,
184
drizzled::plugin::TableNameList *set_of_names,
185
drizzled::TableIdentifiers *identifiers);
188
void doGetTableIdentifiers(drizzled::CachedDirectory &,
189
const drizzled::SchemaIdentifier &schema,
190
drizzled::TableIdentifiers &identifiers);
192
/* The following defines can be increased if necessary */
193
uint32_t max_supported_keys() const { return 1000; }
194
uint32_t max_supported_key_length() const { return 3500; }
195
uint32_t max_supported_key_part_length() const { return 767; }
197
uint32_t index_flags(enum ha_key_alg) const
199
return (HA_READ_NEXT |
205
virtual int doStartTransaction(Session *session,
206
start_transaction_option_t options);
207
virtual void doStartStatement(Session *session);
208
virtual void doEndStatement(Session *session);
210
virtual int doSetSavepoint(Session* session,
211
drizzled::NamedSavepoint &savepoint);
212
virtual int doRollbackToSavepoint(Session* session,
213
drizzled::NamedSavepoint &savepoint);
214
virtual int doReleaseSavepoint(Session* session,
215
drizzled::NamedSavepoint &savepoint);
216
virtual int doCommit(Session* session, bool all);
217
virtual int doRollback(Session* session, bool all);
219
typedef std::map<std::string, HailDBTableShare*> HailDBMap;
220
HailDBMap haildb_open_tables;
221
HailDBTableShare *findOpenTable(const std::string table_name);
222
void addOpenTable(const std::string &table_name, HailDBTableShare *);
223
void deleteOpenTable(const std::string &table_name);
225
uint64_t getInitialAutoIncrementValue(HailDBCursor *cursor);
226
uint64_t getHiddenPrimaryKeyInitialAutoIncrementValue(HailDBCursor *cursor);
230
static drizzled::plugin::StorageEngine *haildb_engine= NULL;
233
static ib_trx_t* get_trx(Session* session)
235
return (ib_trx_t*) session->getEngineData(haildb_engine);
238
/* This is a superset of the map from innobase plugin.
239
Unlike innobase plugin we don't act on errors here, we just
241
static int ib_err_t_to_drizzle_error(ib_err_t err)
253
return ER_QUERY_INTERRUPTED; // FIXME: is this correct?
255
case DB_OUT_OF_MEMORY:
256
return HA_ERR_OUT_OF_MEM;
258
case DB_DUPLICATE_KEY:
259
return HA_ERR_FOUND_DUPP_KEY;
261
case DB_FOREIGN_DUPLICATE_KEY:
262
return HA_ERR_FOREIGN_DUPLICATE_KEY;
264
case DB_MISSING_HISTORY:
265
return HA_ERR_TABLE_DEF_CHANGED;
267
case DB_RECORD_NOT_FOUND:
268
return HA_ERR_NO_ACTIVE_RECORD;
271
return HA_ERR_LOCK_DEADLOCK;
273
case DB_LOCK_WAIT_TIMEOUT:
274
return HA_ERR_LOCK_WAIT_TIMEOUT;
276
case DB_NO_REFERENCED_ROW:
277
return HA_ERR_NO_REFERENCED_ROW;
279
case DB_ROW_IS_REFERENCED:
280
return HA_ERR_ROW_IS_REFERENCED;
282
case DB_CANNOT_ADD_CONSTRAINT:
283
return HA_ERR_CANNOT_ADD_FOREIGN;
285
case DB_CANNOT_DROP_CONSTRAINT:
286
return HA_ERR_ROW_IS_REFERENCED; /* misleading. should have new err code */
288
case DB_COL_APPEARS_TWICE_IN_INDEX:
290
return HA_ERR_CRASHED;
292
case DB_MUST_GET_MORE_FILE_SPACE:
293
case DB_OUT_OF_FILE_SPACE:
294
return HA_ERR_RECORD_FILE_FULL;
296
case DB_TABLE_IS_BEING_USED:
297
return HA_ERR_WRONG_COMMAND;
299
case DB_TABLE_NOT_FOUND:
300
return HA_ERR_NO_SUCH_TABLE;
302
case DB_TOO_BIG_RECORD:
303
return HA_ERR_TO_BIG_ROW;
305
case DB_NO_SAVEPOINT:
306
return HA_ERR_NO_SAVEPOINT;
308
case DB_LOCK_TABLE_FULL:
309
return HA_ERR_LOCK_TABLE_FULL;
311
case DB_PRIMARY_KEY_IS_NULL:
312
return ER_PRIMARY_CANT_HAVE_NULL;
314
case DB_TOO_MANY_CONCURRENT_TRXS:
315
return HA_ERR_RECORD_FILE_FULL; /* need better error code */
317
case DB_END_OF_INDEX:
318
return HA_ERR_END_OF_FILE;
321
return HA_ERR_UNSUPPORTED;
325
static ib_trx_level_t tx_isolation_to_ib_trx_level(enum_tx_isolation level)
329
case ISO_REPEATABLE_READ:
330
return IB_TRX_REPEATABLE_READ;
331
case ISO_READ_COMMITTED:
332
return IB_TRX_READ_COMMITTED;
333
case ISO_SERIALIZABLE:
334
return IB_TRX_SERIALIZABLE;
335
case ISO_READ_UNCOMMITTED:
336
return IB_TRX_READ_UNCOMMITTED;
340
return IB_TRX_REPEATABLE_READ;
343
int HailDBEngine::doStartTransaction(Session *session,
344
start_transaction_option_t options)
346
ib_trx_t *transaction;
347
ib_trx_level_t isolation_level;
351
transaction= get_trx(session);
352
isolation_level= tx_isolation_to_ib_trx_level((enum_tx_isolation)session_tx_isolation(session));
353
*transaction= ib_trx_begin(isolation_level);
358
void HailDBEngine::doStartStatement(Session *session)
360
if(*get_trx(session) == NULL)
361
doStartTransaction(session, START_TRANS_NO_OPTIONS);
363
ib_savepoint_take(*get_trx(session), statement_savepoint_name.c_str(),
364
statement_savepoint_name.length());
367
void HailDBEngine::doEndStatement(Session *)
371
int HailDBEngine::doSetSavepoint(Session* session,
372
drizzled::NamedSavepoint &savepoint)
374
ib_trx_t *transaction= get_trx(session);
375
ib_savepoint_take(*transaction, savepoint.getName().c_str(),
376
savepoint.getName().length());
380
int HailDBEngine::doRollbackToSavepoint(Session* session,
381
drizzled::NamedSavepoint &savepoint)
383
ib_trx_t *transaction= get_trx(session);
386
err= ib_savepoint_rollback(*transaction, savepoint.getName().c_str(),
387
savepoint.getName().length());
389
return ib_err_t_to_drizzle_error(err);
392
int HailDBEngine::doReleaseSavepoint(Session* session,
393
drizzled::NamedSavepoint &savepoint)
395
ib_trx_t *transaction= get_trx(session);
398
err= ib_savepoint_release(*transaction, savepoint.getName().c_str(),
399
savepoint.getName().length());
400
if (err != DB_SUCCESS)
401
return ib_err_t_to_drizzle_error(err);
406
int HailDBEngine::doCommit(Session* session, bool all)
409
ib_trx_t *transaction= get_trx(session);
411
if (all || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
413
err= ib_trx_commit(*transaction);
415
if (err != DB_SUCCESS)
416
return ib_err_t_to_drizzle_error(err);
424
int HailDBEngine::doRollback(Session* session, bool all)
427
ib_trx_t *transaction= get_trx(session);
429
if (all || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
431
err= ib_trx_rollback(*transaction);
433
if (err != DB_SUCCESS)
434
return ib_err_t_to_drizzle_error(err);
440
err= ib_savepoint_rollback(*transaction, statement_savepoint_name.c_str(),
441
statement_savepoint_name.length());
442
if (err != DB_SUCCESS)
443
return ib_err_t_to_drizzle_error(err);
449
HailDBTableShare *HailDBEngine::findOpenTable(const string table_name)
451
HailDBMap::iterator find_iter=
452
haildb_open_tables.find(table_name);
454
if (find_iter != haildb_open_tables.end())
455
return (*find_iter).second;
460
void HailDBEngine::addOpenTable(const string &table_name, HailDBTableShare *share)
462
haildb_open_tables[table_name]= share;
465
void HailDBEngine::deleteOpenTable(const string &table_name)
467
haildb_open_tables.erase(table_name);
470
static pthread_mutex_t haildb_mutex= PTHREAD_MUTEX_INITIALIZER;
472
uint64_t HailDBCursor::getHiddenPrimaryKeyInitialAutoIncrementValue()
476
ib_trx_t transaction= *get_trx(getTable()->in_use);
477
ib_cursor_attach_trx(cursor, transaction);
478
tuple= ib_clust_read_tuple_create(cursor);
479
err= ib_cursor_last(cursor);
480
assert(err == DB_SUCCESS || err == DB_END_OF_INDEX); // Probably a FIXME
481
err= ib_cursor_read_row(cursor, tuple);
482
if (err == DB_RECORD_NOT_FOUND)
486
assert (err == DB_SUCCESS);
487
err= ib_tuple_read_u64(tuple, getTable()->getShare()->fields, &nr);
490
ib_tuple_delete(tuple);
491
err= ib_cursor_reset(cursor);
492
assert(err == DB_SUCCESS);
496
uint64_t HailDBCursor::getInitialAutoIncrementValue()
501
(void) extra(HA_EXTRA_KEYREAD);
502
getTable()->mark_columns_used_by_index_no_reset(getTable()->getShare()->next_number_index);
503
doStartIndexScan(getTable()->getShare()->next_number_index, 1);
504
if (getTable()->getShare()->next_number_keypart == 0)
505
{ // Autoincrement at key-start
506
error=index_last(getTable()->getUpdateRecord());
510
unsigned char key[MAX_KEY_LENGTH];
511
key_copy(key, getTable()->getInsertRecord(),
512
getTable()->key_info + getTable()->getShare()->next_number_index,
513
getTable()->getShare()->next_number_key_offset);
514
error= index_read_map(getTable()->getUpdateRecord(), key,
515
make_prev_keypart_map(getTable()->getShare()->next_number_keypart),
516
HA_READ_PREFIX_LAST);
522
nr= ((uint64_t) getTable()->found_next_number_field->
523
val_int_offset(getTable()->getShare()->rec_buff_length)+1);
525
(void) extra(HA_EXTRA_NO_KEYREAD);
527
if (getTable()->getShare()->getTableProto()->options().auto_increment_value() > nr)
528
nr= getTable()->getShare()->getTableProto()->options().auto_increment_value();
533
HailDBTableShare::HailDBTableShare(const char* name, bool hidden_primary_key)
534
: use_count(0), has_hidden_primary_key(hidden_primary_key)
536
table_name.assign(name);
539
uint64_t HailDBEngine::getInitialAutoIncrementValue(HailDBCursor *cursor)
541
doStartTransaction(current_session, START_TRANS_NO_OPTIONS);
542
uint64_t initial_auto_increment_value= cursor->getInitialAutoIncrementValue();
543
doCommit(current_session, true);
545
return initial_auto_increment_value;
548
uint64_t HailDBEngine::getHiddenPrimaryKeyInitialAutoIncrementValue(HailDBCursor *cursor)
550
doStartTransaction(current_session, START_TRANS_NO_OPTIONS);
551
uint64_t initial_auto_increment_value= cursor->getHiddenPrimaryKeyInitialAutoIncrementValue();
552
doCommit(current_session, true);
554
return initial_auto_increment_value;
557
HailDBTableShare *HailDBCursor::get_share(const char *table_name, bool has_hidden_primary_key, int *rc)
559
pthread_mutex_lock(&haildb_mutex);
561
HailDBEngine *a_engine= static_cast<HailDBEngine *>(getEngine());
562
share= a_engine->findOpenTable(table_name);
566
share= new HailDBTableShare(table_name, has_hidden_primary_key);
570
pthread_mutex_unlock(&haildb_mutex);
571
*rc= HA_ERR_OUT_OF_MEM;
575
if (getTable()->found_next_number_field)
577
share->auto_increment_value.fetch_and_store(
578
a_engine->getInitialAutoIncrementValue(this));
582
if (has_hidden_primary_key)
584
uint64_t hidden_pkey= 0;
585
hidden_pkey= a_engine->getHiddenPrimaryKeyInitialAutoIncrementValue(this);
586
share->hidden_pkey_auto_increment_value.fetch_and_store(hidden_pkey);
589
a_engine->addOpenTable(share->table_name, share);
590
thr_lock_init(&share->lock);
594
pthread_mutex_unlock(&haildb_mutex);
599
int HailDBCursor::free_share()
601
pthread_mutex_lock(&haildb_mutex);
602
if (!--share->use_count)
604
HailDBEngine *a_engine= static_cast<HailDBEngine *>(getEngine());
605
a_engine->deleteOpenTable(share->table_name);
608
pthread_mutex_unlock(&haildb_mutex);
614
THR_LOCK_DATA **HailDBCursor::store_lock(Session *session,
616
thr_lock_type lock_type)
618
/* Currently, we can get a transaction start by ::store_lock
619
instead of beginTransaction, startStatement.
621
See https://bugs.launchpad.net/drizzle/+bug/535528
623
all stemming from the transactional engine interface needing
624
a severe amount of immodium.
627
if(*get_trx(session) == NULL)
629
static_cast<HailDBEngine*>(getEngine())->
630
doStartTransaction(session, START_TRANS_NO_OPTIONS);
633
if (lock_type != TL_UNLOCK)
635
ib_savepoint_take(*get_trx(session), statement_savepoint_name.c_str(),
636
statement_savepoint_name.length());
639
/* the below is adapted from ha_innodb.cc */
641
const uint32_t sql_command = session_sql_command(session);
643
if (sql_command == SQLCOM_DROP_TABLE) {
645
/* MySQL calls this function in DROP Table though this table
646
handle may belong to another session that is running a query.
647
Let us in that case skip any changes to the prebuilt struct. */
649
} else if (lock_type == TL_READ_WITH_SHARED_LOCKS
650
|| lock_type == TL_READ_NO_INSERT
651
|| (lock_type != TL_IGNORE
652
&& sql_command != SQLCOM_SELECT)) {
654
/* The OR cases above are in this order:
655
1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
656
are processing a stored procedure or function, or
657
2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
658
3) this is a SELECT ... IN SHARE MODE, or
659
4) we are doing a complex SQL statement like
660
INSERT INTO ... SELECT ... and the logical logging (MySQL
661
binlog) requires the use of a locking read, or
662
MySQL is doing LOCK TABLES ... READ.
663
5) we let InnoDB do locking reads for all SQL statements that
664
are not simple SELECTs; note that select_lock_type in this
665
case may get strengthened in ::external_lock() to LOCK_X.
666
Note that we MUST use a locking read in all data modifying
667
SQL statements, because otherwise the execution would not be
668
serializable, and also the results from the update could be
669
unexpected if an obsolete consistent read view would be
672
enum_tx_isolation isolation_level= session_tx_isolation(session);
674
if (isolation_level != ISO_SERIALIZABLE
675
&& (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
676
&& (sql_command == SQLCOM_INSERT_SELECT
677
|| sql_command == SQLCOM_UPDATE
678
|| sql_command == SQLCOM_CREATE_TABLE)) {
680
/* If we either have innobase_locks_unsafe_for_binlog
681
option set or this session is using READ COMMITTED
682
isolation level and isolation level of the transaction
683
is not set to serializable and MySQL is doing
684
INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
685
CREATE ... SELECT... without FOR UPDATE or
686
IN SHARE MODE in select, then we use consistent
689
ib_lock_mode= IB_LOCK_NONE;
690
} else if (sql_command == SQLCOM_CHECKSUM) {
691
/* Use consistent read for checksum table */
693
ib_lock_mode= IB_LOCK_NONE;
695
ib_lock_mode= IB_LOCK_S;
698
} else if (lock_type != TL_IGNORE) {
700
/* We set possible LOCK_X value in external_lock, not yet
701
here even if this would be SELECT ... FOR UPDATE */
702
ib_lock_mode= IB_LOCK_NONE;
705
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
707
/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
708
TABLESPACE or TRUNCATE TABLE then allow multiple
709
writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
710
< TL_WRITE_CONCURRENT_INSERT.
713
if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
714
&& lock_type <= TL_WRITE)
715
&& !session_tablespace_op(session)
716
&& sql_command != SQLCOM_TRUNCATE
717
&& sql_command != SQLCOM_CREATE_TABLE) {
719
lock_type = TL_WRITE_ALLOW_WRITE;
722
/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
723
MySQL would use the lock TL_READ_NO_INSERT on t2, and that
724
would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
725
to t2. Convert the lock to a normal read lock to allow
726
concurrent inserts to t2.
729
if (lock_type == TL_READ_NO_INSERT) {
734
lock.type = lock_type;
742
void HailDBCursor::get_auto_increment(uint64_t, //offset,
743
uint64_t, //increment,
745
uint64_t *first_value,
746
uint64_t *nb_reserved_values)
749
*first_value= share->auto_increment_value.fetch_and_increment();
750
if (*first_value == 0)
752
/* if it's zero, then we skip it... why? because of ass.
753
set auto-inc to -1 and the sequence is:
755
Zero is still "magic".
757
share->auto_increment_value.compare_and_swap(1, 0);
760
*nb_reserved_values= 1;
763
static const char* table_path_to_haildb_name(const char* name)
765
size_t l= strlen(name);
766
static string datadict_path("data_dictionary/");
767
static string sys_prefix("data_dictionary/haildb_");
768
static string sys_table_prefix("HAILDB_");
770
if (strncmp(name, sys_prefix.c_str(), sys_prefix.length()) == 0)
772
string find_name(name+datadict_path.length());
773
std::transform(find_name.begin(), find_name.end(), find_name.begin(), ::toupper);
774
boost::unordered_set<string>::iterator iter= haildb_system_table_names.find(find_name);
775
if (iter != haildb_system_table_names.end())
776
return (*iter).c_str()+sys_table_prefix.length();
780
while(slashes>0 && l > 0)
792
static void TableIdentifier_to_haildb_name(const TableIdentifier &identifier, std::string *str)
794
str->assign(table_path_to_haildb_name(identifier.getPath().c_str()));
797
HailDBCursor::HailDBCursor(drizzled::plugin::StorageEngine &engine_arg,
799
:Cursor(engine_arg, table_arg),
800
ib_lock_mode(IB_LOCK_NONE),
801
write_can_replace(false),
805
static unsigned int get_first_unique_index(drizzled::Table &table)
807
for (uint32_t k= 0; k < table.getShare()->keys; k++)
809
if (table.key_info[k].flags & HA_NOSAME)
818
int HailDBCursor::open(const char *name, int, uint32_t)
820
const char* haildb_table_name= table_path_to_haildb_name(name);
821
ib_err_t err= ib_cursor_open_table(haildb_table_name, NULL, &cursor);
822
bool has_hidden_primary_key= false;
825
if (err != DB_SUCCESS)
826
return ib_err_t_to_drizzle_error(err);
828
err= ib_index_get_id(haildb_table_name, "HIDDEN_PRIMARY", &idx_id);
830
if (err == DB_SUCCESS)
831
has_hidden_primary_key= true;
834
share= get_share(name, has_hidden_primary_key, &rc);
835
lock.init(&share->lock);
838
if (getTable()->getShare()->getPrimaryKey() != MAX_KEY)
839
ref_length= getTable()->key_info[getTable()->getShare()->getPrimaryKey()].key_length;
840
else if (share->has_hidden_primary_key)
841
ref_length= sizeof(uint64_t);
844
unsigned int keynr= get_first_unique_index(*getTable());
845
ref_length= getTable()->key_info[keynr].key_length;
848
in_table_scan= false;
853
int HailDBCursor::close(void)
855
ib_err_t err= ib_cursor_close(cursor);
856
if (err != DB_SUCCESS)
857
return ib_err_t_to_drizzle_error(err);
867
int HailDBCursor::external_lock(Session* session, int lock_type)
869
ib_cursor_stmt_begin(cursor);
873
if (lock_type == F_WRLCK)
875
/* SELECT ... FOR UPDATE or UPDATE TABLE */
876
ib_lock_mode= IB_LOCK_X;
879
ib_lock_mode= IB_LOCK_NONE;
884
static int create_table_add_field(ib_tbl_sch_t schema,
885
const message::Table::Field &field,
888
ib_col_attr_t column_attr= IB_COL_NONE;
890
if (field.has_constraints() && ! field.constraints().is_nullable())
891
column_attr= IB_COL_NOT_NULL;
893
switch (field.type())
895
case message::Table::Field::VARCHAR:
896
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_VARCHAR,
898
field.string_options().length());
900
case message::Table::Field::INTEGER:
901
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
904
case message::Table::Field::BIGINT:
905
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
908
case message::Table::Field::DOUBLE:
909
case message::Table::Field::DATETIME:
910
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_DOUBLE,
911
column_attr, 0, sizeof(double));
913
case message::Table::Field::ENUM:
914
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
917
case message::Table::Field::DATE:
918
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
921
case message::Table::Field::TIMESTAMP:
922
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
925
case message::Table::Field::BLOB:
926
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_BLOB,
929
case message::Table::Field::DECIMAL:
930
*err= ib_table_schema_add_col(schema, field.name().c_str(), IB_DECIMAL,
934
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "Column Type");
935
return(HA_ERR_UNSUPPORTED);
941
static ib_err_t store_table_message(ib_trx_t transaction, const char* table_name, drizzled::message::Table& table_message)
944
ib_tpl_t message_tuple;
946
string serialized_message;
948
err= ib_cursor_open_table(HAILDB_TABLE_DEFINITIONS_TABLE, transaction, &cursor);
949
if (err != DB_SUCCESS)
952
message_tuple= ib_clust_read_tuple_create(cursor);
954
err= ib_col_set_value(message_tuple, 0, table_name, strlen(table_name));
955
if (err != DB_SUCCESS)
959
table_message.SerializeToString(&serialized_message);
966
err= ib_col_set_value(message_tuple, 1, serialized_message.c_str(),
967
serialized_message.length());
968
if (err != DB_SUCCESS)
971
err= ib_cursor_insert_row(cursor, message_tuple);
974
ib_tuple_delete(message_tuple);
976
ib_err_t cleanup_err= ib_cursor_close(cursor);
977
if (err == DB_SUCCESS)
983
bool HailDBEngine::validateCreateTableOption(const std::string &key,
984
const std::string &state)
986
if (boost::iequals(key, "ROW_FORMAT"))
988
if (boost::iequals(state, "COMPRESSED"))
991
if (boost::iequals(state, "COMPACT"))
994
if (boost::iequals(state, "DYNAMIC"))
997
if (boost::iequals(state, "REDUNDANT"))
1004
static ib_tbl_fmt_t parse_ib_table_format(const std::string &value)
1006
if (boost::iequals(value, "REDUNDANT"))
1007
return IB_TBL_REDUNDANT;
1008
else if (boost::iequals(value, "COMPACT"))
1009
return IB_TBL_COMPACT;
1010
else if (boost::iequals(value, "DYNAMIC"))
1011
return IB_TBL_DYNAMIC;
1012
else if (boost::iequals(value, "COMPRESSED"))
1013
return IB_TBL_COMPRESSED;
1015
assert(false); /* You need to add possible table formats here */
1016
return IB_TBL_COMPACT;
1019
int HailDBEngine::doCreateTable(Session &session,
1021
const drizzled::TableIdentifier &identifier,
1022
drizzled::message::Table& table_message)
1024
ib_tbl_sch_t haildb_table_schema= NULL;
1025
// ib_idx_sch_t haildb_pkey= NULL;
1026
ib_trx_t haildb_schema_transaction;
1027
ib_id_t haildb_table_id;
1028
ib_err_t haildb_err= DB_SUCCESS;
1029
string haildb_table_name;
1030
bool has_explicit_pkey= false;
1034
if (table_message.type() == message::Table::TEMPORARY)
1036
ib_bool_t create_db_err= ib_database_create(GLOBAL_TEMPORARY_EXT);
1037
if (create_db_err != IB_TRUE)
1041
TableIdentifier_to_haildb_name(identifier, &haildb_table_name);
1043
ib_tbl_fmt_t haildb_table_format= IB_TBL_COMPACT;
1045
const size_t num_engine_options= table_message.engine().options_size();
1046
for (size_t x= 0; x < num_engine_options; x++)
1048
const message::Engine::Option &engine_option= table_message.engine().options(x);
1049
if (boost::iequals(engine_option.name(), "ROW_FORMAT"))
1051
haildb_table_format= parse_ib_table_format(engine_option.state());
1055
haildb_err= ib_table_schema_create(haildb_table_name.c_str(),
1056
&haildb_table_schema,
1057
haildb_table_format, 0);
1059
if (haildb_err != DB_SUCCESS)
1061
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1062
ER_CANT_CREATE_TABLE,
1063
_("Cannot create table %s. HailDB Error %d (%s)\n"),
1064
haildb_table_name.c_str(), haildb_err, ib_strerror(haildb_err));
1065
return ib_err_t_to_drizzle_error(haildb_err);
1068
for (int colnr= 0; colnr < table_message.field_size() ; colnr++)
1070
const message::Table::Field field = table_message.field(colnr);
1072
int field_err= create_table_add_field(haildb_table_schema, field,
1075
if (haildb_err != DB_SUCCESS || field_err != 0)
1076
ib_table_schema_delete(haildb_table_schema); /* cleanup */
1078
if (haildb_err != DB_SUCCESS)
1080
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1081
ER_CANT_CREATE_TABLE,
1082
_("Cannot create field %s on table %s."
1083
" HailDB Error %d (%s)\n"),
1084
field.name().c_str(), haildb_table_name.c_str(),
1085
haildb_err, ib_strerror(haildb_err));
1086
return ib_err_t_to_drizzle_error(haildb_err);
1092
bool has_primary= false;
1093
for (int indexnr= 0; indexnr < table_message.indexes_size() ; indexnr++)
1095
message::Table::Index *index = table_message.mutable_indexes(indexnr);
1097
ib_idx_sch_t haildb_index;
1099
haildb_err= ib_table_schema_add_index(haildb_table_schema, index->name().c_str(),
1101
if (haildb_err != DB_SUCCESS)
1104
if (index->is_primary())
1107
haildb_err= ib_index_schema_set_clustered(haildb_index);
1108
has_explicit_pkey= true;
1109
if (haildb_err != DB_SUCCESS)
1113
if (index->is_unique())
1115
haildb_err= ib_index_schema_set_unique(haildb_index);
1116
if (haildb_err != DB_SUCCESS)
1120
if (index->type() == message::Table::Index::UNKNOWN_INDEX)
1121
index->set_type(message::Table::Index::BTREE);
1123
for (int partnr= 0; partnr < index->index_part_size(); partnr++)
1125
const message::Table::Index::IndexPart part= index->index_part(partnr);
1126
const message::Table::Field::FieldType part_type= table_message.field(part.fieldnr()).type();
1127
uint64_t compare_length= 0;
1129
if (part_type == message::Table::Field::BLOB
1130
|| part_type == message::Table::Field::VARCHAR)
1131
compare_length= part.compare_length();
1133
haildb_err= ib_index_schema_add_col(haildb_index,
1134
table_message.field(part.fieldnr()).name().c_str(),
1136
if (haildb_err != DB_SUCCESS)
1140
if (! has_primary && index->is_unique())
1142
haildb_err= ib_index_schema_set_clustered(haildb_index);
1143
has_explicit_pkey= true;
1144
if (haildb_err != DB_SUCCESS)
1150
if (! has_explicit_pkey)
1152
ib_idx_sch_t haildb_index;
1154
haildb_err= ib_table_schema_add_col(haildb_table_schema, "hidden_primary_key_col",
1155
IB_INT, IB_COL_NOT_NULL, 0, 8);
1157
haildb_err= ib_table_schema_add_index(haildb_table_schema, "HIDDEN_PRIMARY",
1159
if (haildb_err != DB_SUCCESS)
1162
haildb_err= ib_index_schema_set_clustered(haildb_index);
1163
if (haildb_err != DB_SUCCESS)
1166
haildb_err= ib_index_schema_add_col(haildb_index, "hidden_primary_key_col", 0);
1167
if (haildb_err != DB_SUCCESS)
1171
haildb_schema_transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
1172
haildb_err= ib_schema_lock_exclusive(haildb_schema_transaction);
1173
if (haildb_err != DB_SUCCESS)
1175
ib_err_t rollback_err= ib_trx_rollback(haildb_schema_transaction);
1176
ib_table_schema_delete(haildb_table_schema);
1178
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1179
ER_CANT_CREATE_TABLE,
1180
_("Cannot Lock HailDB Data Dictionary. HailDB Error %d (%s)\n"),
1181
haildb_err, ib_strerror(haildb_err));
1183
assert (rollback_err == DB_SUCCESS);
1185
return HA_ERR_GENERIC;
1188
haildb_err= ib_table_create(haildb_schema_transaction, haildb_table_schema,
1191
if (haildb_err != DB_SUCCESS)
1193
ib_err_t rollback_err= ib_trx_rollback(haildb_schema_transaction);
1194
ib_table_schema_delete(haildb_table_schema);
1196
if (haildb_err == DB_TABLE_IS_BEING_USED)
1199
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1200
ER_CANT_CREATE_TABLE,
1201
_("Cannot create table %s. HailDB Error %d (%s)\n"),
1202
haildb_table_name.c_str(),
1203
haildb_err, ib_strerror(haildb_err));
1205
assert (rollback_err == DB_SUCCESS);
1206
return HA_ERR_GENERIC;
1209
if (table_message.type() == message::Table::TEMPORARY)
1211
session.getMessageCache().storeTableMessage(identifier, table_message);
1212
haildb_err= DB_SUCCESS;
1215
haildb_err= store_table_message(haildb_schema_transaction,
1216
haildb_table_name.c_str(),
1219
if (haildb_err == DB_SUCCESS)
1220
haildb_err= ib_trx_commit(haildb_schema_transaction);
1222
haildb_err= ib_trx_rollback(haildb_schema_transaction);
1225
ib_table_schema_delete(haildb_table_schema);
1227
if (haildb_err != DB_SUCCESS)
1229
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1230
ER_CANT_CREATE_TABLE,
1231
_("Cannot create table %s. HailDB Error %d (%s)\n"),
1232
haildb_table_name.c_str(),
1233
haildb_err, ib_strerror(haildb_err));
1234
return ib_err_t_to_drizzle_error(haildb_err);
1240
static int delete_table_message_from_haildb(ib_trx_t transaction, const char* table_name)
1243
ib_tpl_t search_tuple;
1247
err= ib_cursor_open_table(HAILDB_TABLE_DEFINITIONS_TABLE, transaction, &cursor);
1248
if (err != DB_SUCCESS)
1251
search_tuple= ib_clust_search_tuple_create(cursor);
1253
err= ib_col_set_value(search_tuple, 0, table_name, strlen(table_name));
1254
if (err != DB_SUCCESS)
1257
// ib_cursor_set_match_mode(cursor, IB_EXACT_MATCH);
1259
err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
1260
if (err == DB_RECORD_NOT_FOUND || res != 0)
1263
err= ib_cursor_delete_row(cursor);
1264
assert (err == DB_SUCCESS);
1267
ib_err_t rollback_err= ib_cursor_close(cursor);
1268
if (err == DB_SUCCESS)
1271
ib_tuple_delete(search_tuple);
1276
int HailDBEngine::doDropTable(Session &session,
1277
const TableIdentifier &identifier)
1279
ib_trx_t haildb_schema_transaction;
1280
ib_err_t haildb_err;
1281
string haildb_table_name;
1283
TableIdentifier_to_haildb_name(identifier, &haildb_table_name);
1285
haildb_schema_transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
1286
haildb_err= ib_schema_lock_exclusive(haildb_schema_transaction);
1287
if (haildb_err != DB_SUCCESS)
1289
ib_err_t rollback_err= ib_trx_rollback(haildb_schema_transaction);
1291
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1292
ER_CANT_DELETE_FILE,
1293
_("Cannot Lock HailDB Data Dictionary. HailDB Error %d (%s)\n"),
1294
haildb_err, ib_strerror(haildb_err));
1296
assert (rollback_err == DB_SUCCESS);
1298
return HA_ERR_GENERIC;
1301
if (identifier.getType() == message::Table::TEMPORARY)
1303
session.getMessageCache().removeTableMessage(identifier);
1304
delete_table_message_from_haildb(haildb_schema_transaction,
1305
haildb_table_name.c_str());
1309
if (delete_table_message_from_haildb(haildb_schema_transaction, haildb_table_name.c_str()) != DB_SUCCESS)
1311
ib_schema_unlock(haildb_schema_transaction);
1312
ib_err_t rollback_err= ib_trx_rollback(haildb_schema_transaction);
1313
assert(rollback_err == DB_SUCCESS);
1314
return HA_ERR_GENERIC;
1318
haildb_err= ib_table_drop(haildb_schema_transaction, haildb_table_name.c_str());
1320
if (haildb_err == DB_TABLE_NOT_FOUND)
1322
haildb_err= ib_trx_rollback(haildb_schema_transaction);
1323
assert(haildb_err == DB_SUCCESS);
1326
else if (haildb_err != DB_SUCCESS)
1328
ib_err_t rollback_err= ib_trx_rollback(haildb_schema_transaction);
1330
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1331
ER_CANT_DELETE_FILE,
1332
_("Cannot DROP table %s. HailDB Error %d (%s)\n"),
1333
haildb_table_name.c_str(),
1334
haildb_err, ib_strerror(haildb_err));
1336
assert(rollback_err == DB_SUCCESS);
1338
return HA_ERR_GENERIC;
1341
haildb_err= ib_trx_commit(haildb_schema_transaction);
1342
if (haildb_err != DB_SUCCESS)
1344
ib_err_t rollback_err= ib_trx_rollback(haildb_schema_transaction);
1346
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1347
ER_CANT_DELETE_FILE,
1348
_("Cannot DROP table %s. HailDB Error %d (%s)\n"),
1349
haildb_table_name.c_str(),
1350
haildb_err, ib_strerror(haildb_err));
1352
assert(rollback_err == DB_SUCCESS);
1353
return HA_ERR_GENERIC;
1359
static ib_err_t rename_table_message(ib_trx_t transaction, const TableIdentifier &from_identifier, const TableIdentifier &to_identifier)
1362
ib_tpl_t search_tuple;
1363
ib_tpl_t read_tuple;
1364
ib_tpl_t update_tuple;
1367
ib_err_t rollback_err;
1368
const char *message;
1369
ib_ulint_t message_len;
1370
drizzled::message::Table table_message;
1371
string from_haildb_table_name;
1372
string to_haildb_table_name;
1375
string serialized_message;
1376
ib_col_meta_t col_meta;
1378
TableIdentifier_to_haildb_name(from_identifier, &from_haildb_table_name);
1379
TableIdentifier_to_haildb_name(to_identifier, &to_haildb_table_name);
1381
from= from_haildb_table_name.c_str();
1382
to= to_haildb_table_name.c_str();
1384
err= ib_cursor_open_table(HAILDB_TABLE_DEFINITIONS_TABLE, transaction, &cursor);
1385
if (err != DB_SUCCESS)
1387
rollback_err= ib_trx_rollback(transaction);
1388
assert(rollback_err == DB_SUCCESS);
1392
search_tuple= ib_clust_search_tuple_create(cursor);
1393
read_tuple= ib_clust_read_tuple_create(cursor);
1395
err= ib_col_set_value(search_tuple, 0, from, strlen(from));
1396
if (err != DB_SUCCESS)
1399
// ib_cursor_set_match_mode(cursor, IB_EXACT_MATCH);
1401
err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
1402
if (err == DB_RECORD_NOT_FOUND || res != 0)
1405
err= ib_cursor_read_row(cursor, read_tuple);
1406
if (err == DB_RECORD_NOT_FOUND || res != 0)
1409
message= (const char*)ib_col_get_value(read_tuple, 1);
1410
message_len= ib_col_get_meta(read_tuple, 1, &col_meta);
1412
if (table_message.ParseFromArray(message, message_len) == false)
1415
table_message.set_name(to_identifier.getTableName());
1416
table_message.set_schema(to_identifier.getSchemaName());
1418
update_tuple= ib_clust_read_tuple_create(cursor);
1420
err= ib_tuple_copy(update_tuple, read_tuple);
1421
assert(err == DB_SUCCESS);
1423
err= ib_col_set_value(update_tuple, 0, to, strlen(to));
1426
table_message.SerializeToString(&serialized_message);
1433
err= ib_col_set_value(update_tuple, 1, serialized_message.c_str(),
1434
serialized_message.length());
1436
err= ib_cursor_update_row(cursor, read_tuple, update_tuple);
1439
ib_tuple_delete(update_tuple);
1440
ib_tuple_delete(read_tuple);
1441
ib_tuple_delete(search_tuple);
1443
err= ib_cursor_close(cursor);
1449
int HailDBEngine::doRenameTable(drizzled::Session &session,
1450
const drizzled::TableIdentifier &from,
1451
const drizzled::TableIdentifier &to)
1453
ib_trx_t haildb_schema_transaction;
1455
string from_haildb_table_name;
1456
string to_haildb_table_name;
1458
if (to.getType() == message::Table::TEMPORARY
1459
&& from.getType() == message::Table::TEMPORARY)
1461
session.getMessageCache().renameTableMessage(from, to);
1465
TableIdentifier_to_haildb_name(from, &from_haildb_table_name);
1466
TableIdentifier_to_haildb_name(to, &to_haildb_table_name);
1468
haildb_schema_transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
1469
err= ib_schema_lock_exclusive(haildb_schema_transaction);
1470
if (err != DB_SUCCESS)
1472
push_warning_printf(&session, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
1473
ER_CANT_DELETE_FILE,
1474
_("Cannot Lock HailDB Data Dictionary. HailDB Error %d (%s)\n"),
1475
err, ib_strerror(err));
1480
err= ib_table_rename(haildb_schema_transaction,
1481
from_haildb_table_name.c_str(),
1482
to_haildb_table_name.c_str());
1483
if (err != DB_SUCCESS)
1486
err= rename_table_message(haildb_schema_transaction, from, to);
1488
if (err != DB_SUCCESS)
1491
err= ib_trx_commit(haildb_schema_transaction);
1492
if (err != DB_SUCCESS)
1497
ib_err_t rollback_err= ib_schema_unlock(haildb_schema_transaction);
1498
assert(rollback_err == DB_SUCCESS);
1499
rollback_err= ib_trx_rollback(haildb_schema_transaction);
1500
assert(rollback_err == DB_SUCCESS);
1501
return ib_err_t_to_drizzle_error(err);
1504
void HailDBEngine::getTableNamesInSchemaFromHailDB(
1505
const drizzled::SchemaIdentifier &schema,
1506
drizzled::plugin::TableNameList *set_of_names,
1507
drizzled::TableIdentifiers *identifiers)
1509
ib_trx_t transaction;
1512
Why not use getPath()?
1514
string search_string(schema.getSchemaName());
1516
boost::algorithm::to_lower(search_string);
1518
search_string.append("/");
1520
transaction = ib_trx_begin(IB_TRX_REPEATABLE_READ);
1521
ib_err_t haildb_err= ib_schema_lock_exclusive(transaction);
1522
assert(haildb_err == DB_SUCCESS); /* FIXME: doGetTableNames needs to be able to return error */
1524
if (search_string.compare("data_dictionary/") == 0)
1528
BOOST_FOREACH(std::string table_name, haildb_system_table_names)
1530
set_of_names->insert(table_name);
1535
BOOST_FOREACH(std::string table_name, haildb_system_table_names)
1537
identifiers->push_back(TableIdentifier(schema.getSchemaName(),
1543
haildb_err= ib_cursor_open_table("SYS_TABLES", transaction, &cursor);
1544
assert(haildb_err == DB_SUCCESS); /* FIXME */
1546
ib_tpl_t read_tuple;
1547
ib_tpl_t search_tuple;
1549
read_tuple= ib_clust_read_tuple_create(cursor);
1550
search_tuple= ib_clust_search_tuple_create(cursor);
1552
haildb_err= ib_col_set_value(search_tuple, 0, search_string.c_str(),
1553
search_string.length());
1554
assert (haildb_err == DB_SUCCESS); // FIXME
1557
haildb_err = ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
1558
// fixme: check error above
1560
while (haildb_err == DB_SUCCESS)
1562
haildb_err= ib_cursor_read_row(cursor, read_tuple);
1564
const char *table_name;
1566
ib_col_meta_t column_metadata;
1568
table_name= (const char*)ib_col_get_value(read_tuple, 0);
1569
table_name_len= ib_col_get_meta(read_tuple, 0, &column_metadata);
1571
if (search_string.compare(0, search_string.length(),
1572
table_name, search_string.length()) == 0)
1574
const char *just_table_name= strchr(table_name, '/');
1575
assert(just_table_name);
1576
just_table_name++; /* skip over '/' */
1578
set_of_names->insert(just_table_name);
1580
identifiers->push_back(TableIdentifier(schema.getSchemaName(), just_table_name));
1584
haildb_err= ib_cursor_next(cursor);
1585
read_tuple= ib_tuple_clear(read_tuple);
1588
ib_tuple_delete(read_tuple);
1589
ib_tuple_delete(search_tuple);
1591
haildb_err= ib_cursor_close(cursor);
1592
assert(haildb_err == DB_SUCCESS); // FIXME
1594
haildb_err= ib_trx_commit(transaction);
1595
assert(haildb_err == DB_SUCCESS); // FIXME
1598
void HailDBEngine::doGetTableIdentifiers(drizzled::CachedDirectory &,
1599
const drizzled::SchemaIdentifier &schema,
1600
drizzled::TableIdentifiers &identifiers)
1602
getTableNamesInSchemaFromHailDB(schema, NULL, &identifiers);
1605
static int read_table_message_from_haildb(const char* table_name, drizzled::message::Table *table_message)
1607
ib_trx_t transaction;
1608
ib_tpl_t search_tuple;
1609
ib_tpl_t read_tuple;
1611
const char *message;
1612
ib_ulint_t message_len;
1613
ib_col_meta_t col_meta;
1616
ib_err_t rollback_err;
1618
transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
1619
err= ib_schema_lock_exclusive(transaction);
1620
if (err != DB_SUCCESS)
1622
rollback_err= ib_trx_rollback(transaction);
1623
assert(rollback_err == DB_SUCCESS);
1627
err= ib_cursor_open_table(HAILDB_TABLE_DEFINITIONS_TABLE, transaction, &cursor);
1628
if (err != DB_SUCCESS)
1630
rollback_err= ib_trx_rollback(transaction);
1631
assert(rollback_err == DB_SUCCESS);
1635
search_tuple= ib_clust_search_tuple_create(cursor);
1636
read_tuple= ib_clust_read_tuple_create(cursor);
1638
err= ib_col_set_value(search_tuple, 0, table_name, strlen(table_name));
1639
if (err != DB_SUCCESS)
1642
// ib_cursor_set_match_mode(cursor, IB_EXACT_MATCH);
1644
err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
1645
if (err == DB_RECORD_NOT_FOUND || res != 0)
1648
err= ib_cursor_read_row(cursor, read_tuple);
1649
if (err == DB_RECORD_NOT_FOUND || res != 0)
1652
message= (const char*)ib_col_get_value(read_tuple, 1);
1653
message_len= ib_col_get_meta(read_tuple, 1, &col_meta);
1655
if (table_message->ParseFromArray(message, message_len) == false)
1658
ib_tuple_delete(search_tuple);
1659
ib_tuple_delete(read_tuple);
1660
err= ib_cursor_close(cursor);
1661
if (err != DB_SUCCESS)
1662
goto rollback_close_err;
1663
err= ib_trx_commit(transaction);
1664
if (err != DB_SUCCESS)
1665
goto rollback_close_err;
1670
ib_tuple_delete(search_tuple);
1671
ib_tuple_delete(read_tuple);
1672
rollback_err= ib_cursor_close(cursor);
1673
assert(rollback_err == DB_SUCCESS);
1675
ib_schema_unlock(transaction);
1676
rollback_err= ib_trx_rollback(transaction);
1677
assert(rollback_err == DB_SUCCESS);
1679
if (strcmp(table_name, HAILDB_TABLE_DEFINITIONS_TABLE) == 0)
1681
message::Engine *engine= table_message->mutable_engine();
1682
engine->set_name("InnoDB");
1683
table_message->set_name("haildb_table_definitions");
1684
table_message->set_schema("data_dictionary");
1685
table_message->set_type(message::Table::STANDARD);
1686
table_message->set_creation_timestamp(0);
1687
table_message->set_update_timestamp(0);
1689
message::Table::TableOptions *options= table_message->mutable_options();
1690
options->set_collation_id(my_charset_bin.number);
1691
options->set_collation(my_charset_bin.name);
1693
message::Table::Field *field= table_message->add_field();
1694
field->set_name("table_name");
1695
field->set_type(message::Table::Field::VARCHAR);
1696
message::Table::Field::StringFieldOptions *stropt= field->mutable_string_options();
1697
stropt->set_length(IB_MAX_TABLE_NAME_LEN);
1698
stropt->set_collation_id(my_charset_bin.number);
1699
stropt->set_collation(my_charset_bin.name);
1701
field= table_message->add_field();
1702
field->set_name("message");
1703
field->set_type(message::Table::Field::BLOB);
1704
stropt= field->mutable_string_options();
1705
stropt->set_collation_id(my_charset_bin.number);
1706
stropt->set_collation(my_charset_bin.name);
1708
message::Table::Index *index= table_message->add_indexes();
1709
index->set_name("PRIMARY");
1710
index->set_is_primary(true);
1711
index->set_is_unique(true);
1712
index->set_type(message::Table::Index::BTREE);
1713
index->set_key_length(IB_MAX_TABLE_NAME_LEN);
1714
message::Table::Index::IndexPart *part= index->add_index_part();
1715
part->set_fieldnr(0);
1716
part->set_compare_length(IB_MAX_TABLE_NAME_LEN);
1724
int HailDBEngine::doGetTableDefinition(Session &session,
1725
const TableIdentifier &identifier,
1726
drizzled::message::Table &table)
1728
ib_crsr_t haildb_cursor= NULL;
1729
string haildb_table_name;
1731
/* Check temporary tables!? */
1732
if (session.getMessageCache().getTableMessage(identifier, table))
1735
TableIdentifier_to_haildb_name(identifier, &haildb_table_name);
1737
if (ib_cursor_open_table(haildb_table_name.c_str(), NULL, &haildb_cursor) != DB_SUCCESS)
1740
ib_err_t err= ib_cursor_close(haildb_cursor);
1742
assert (err == DB_SUCCESS);
1744
if (read_table_message_from_haildb(haildb_table_name.c_str(), &table) != 0)
1746
if (get_haildb_system_table_message(haildb_table_name.c_str(), &table) == 0)
1753
bool HailDBEngine::doDoesTableExist(Session &,
1754
const TableIdentifier& identifier)
1756
ib_crsr_t haildb_cursor;
1757
string haildb_table_name;
1759
TableIdentifier_to_haildb_name(identifier, &haildb_table_name);
1761
boost::unordered_set<string>::iterator iter= haildb_system_table_names.find(identifier.getTableName());
1762
if (iter != haildb_system_table_names.end())
1765
if (ib_cursor_open_table(haildb_table_name.c_str(), NULL, &haildb_cursor) != DB_SUCCESS)
1768
ib_err_t err= ib_cursor_close(haildb_cursor);
1769
assert(err == DB_SUCCESS);
1774
const char *HailDBCursor::index_type(uint32_t)
1779
static ib_err_t write_row_to_haildb_tuple(Field **fields, ib_tpl_t tuple)
1782
ib_err_t err= DB_ERROR;
1784
for (Field **field= fields; *field; field++, colnr++)
1786
if (! (**field).isWriteSet() && (**field).is_null())
1789
if ((**field).is_null())
1791
err= ib_col_set_value(tuple, colnr, NULL, IB_SQL_NULL);
1792
assert(err == DB_SUCCESS);
1796
if ((**field).type() == DRIZZLE_TYPE_VARCHAR)
1798
/* To get around the length bytes (1 or 2) at (**field).ptr
1799
we can use Field_varstring::val_str to a String
1800
to get a pointer to the real string without copying it.
1803
(**field).setReadSet();
1804
(**field).val_str(&str);
1805
err= ib_col_set_value(tuple, colnr, str.ptr(), str.length());
1807
else if ((**field).type() == DRIZZLE_TYPE_ENUM)
1809
err= ib_tuple_write_u32(tuple, colnr, *((ib_u32_t*)(*field)->ptr));
1811
else if ((**field).type() == DRIZZLE_TYPE_DATE)
1813
(**field).setReadSet();
1814
err= ib_tuple_write_u32(tuple, colnr, (*field)->val_int());
1816
else if ((**field).type() == DRIZZLE_TYPE_BLOB)
1818
Field_blob *blob= reinterpret_cast<Field_blob*>(*field);
1819
unsigned char* blob_ptr;
1820
uint32_t blob_length= blob->get_length();
1821
blob->get_ptr(&blob_ptr);
1822
err= ib_col_set_value(tuple, colnr, blob_ptr, blob_length);
1826
err= ib_col_set_value(tuple, colnr, (*field)->ptr, (*field)->data_length());
1829
assert (err == DB_SUCCESS);
1835
static uint64_t innobase_get_int_col_max_value(const Field* field)
1837
uint64_t max_value = 0;
1839
switch(field->key_type()) {
1841
case HA_KEYTYPE_BINARY:
1842
max_value = 0xFFULL;
1845
case HA_KEYTYPE_ULONG_INT:
1846
max_value = 0xFFFFFFFFULL;
1848
case HA_KEYTYPE_LONG_INT:
1849
max_value = 0x7FFFFFFFULL;
1852
case HA_KEYTYPE_ULONGLONG:
1853
max_value = 0xFFFFFFFFFFFFFFFFULL;
1855
case HA_KEYTYPE_LONGLONG:
1856
max_value = 0x7FFFFFFFFFFFFFFFULL;
1858
case HA_KEYTYPE_DOUBLE:
1859
/* We use the maximum as per IEEE754-2008 standard, 2^53 */
1860
max_value = 0x20000000000000ULL;
1869
int HailDBCursor::doInsertRecord(unsigned char *record)
1874
ib_trx_t transaction= *get_trx(getTable()->in_use);
1876
tuple= ib_clust_read_tuple_create(cursor);
1878
ib_cursor_attach_trx(cursor, transaction);
1880
err= ib_cursor_first(cursor);
1881
if (current_session->lex->sql_command == SQLCOM_CREATE_TABLE
1882
&& err == DB_MISSING_HISTORY)
1884
/* See https://bugs.launchpad.net/drizzle/+bug/556978
1886
* In CREATE SELECT, transaction is started in ::store_lock
1887
* at the start of the statement, before the table is created.
1888
* This means the table doesn't exist in our snapshot,
1889
* and we get a DB_MISSING_HISTORY error on ib_cursor_first().
1890
* The way to get around this is to here, restart the transaction
1896
HailDBEngine *storage_engine= static_cast<HailDBEngine*>(getEngine());
1897
err= ib_cursor_reset(cursor);
1898
storage_engine->doCommit(current_session, true);
1899
storage_engine->doStartTransaction(current_session, START_TRANS_NO_OPTIONS);
1900
transaction= *get_trx(getTable()->in_use);
1901
assert(err == DB_SUCCESS);
1902
ib_cursor_attach_trx(cursor, transaction);
1903
err= ib_cursor_first(cursor);
1906
assert(err == DB_SUCCESS || err == DB_END_OF_INDEX);
1909
if (getTable()->next_number_field)
1911
update_auto_increment();
1913
uint64_t temp_auto= getTable()->next_number_field->val_int();
1915
if (temp_auto <= innobase_get_int_col_max_value(getTable()->next_number_field))
1919
uint64_t fetched_auto= share->auto_increment_value;
1921
if (temp_auto >= fetched_auto)
1923
uint64_t store_value= temp_auto+1;
1924
if (store_value == 0)
1927
if (share->auto_increment_value.compare_and_swap(store_value, fetched_auto) == fetched_auto)
1937
write_row_to_haildb_tuple(getTable()->getFields(), tuple);
1939
if (share->has_hidden_primary_key)
1941
err= ib_tuple_write_u64(tuple, getTable()->getShare()->fields, share->hidden_pkey_auto_increment_value.fetch_and_increment());
1944
err= ib_cursor_insert_row(cursor, tuple);
1946
if (err == DB_DUPLICATE_KEY)
1948
if (write_can_replace)
1950
store_key_value_from_haildb(getTable()->key_info + getTable()->getShare()->getPrimaryKey(),
1951
ref, ref_length, record);
1953
ib_tpl_t search_tuple= ib_clust_search_tuple_create(cursor);
1955
fill_ib_search_tpl_from_drizzle_key(search_tuple,
1956
getTable()->key_info + 0,
1960
err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
1961
assert(err == DB_SUCCESS);
1962
ib_tuple_delete(search_tuple);
1964
tuple= ib_tuple_clear(tuple);
1965
err= ib_cursor_delete_row(cursor);
1967
err= ib_cursor_first(cursor);
1968
assert(err == DB_SUCCESS || err == DB_END_OF_INDEX);
1970
write_row_to_haildb_tuple(getTable()->getFields(), tuple);
1972
err= ib_cursor_insert_row(cursor, tuple);
1973
assert(err==DB_SUCCESS); // probably be nice and process errors
1976
ret= HA_ERR_FOUND_DUPP_KEY;
1978
else if (err != DB_SUCCESS)
1979
ret= ib_err_t_to_drizzle_error(err);
1981
tuple= ib_tuple_clear(tuple);
1982
ib_tuple_delete(tuple);
1983
err= ib_cursor_reset(cursor);
1988
int HailDBCursor::doUpdateRecord(const unsigned char *,
1991
ib_tpl_t update_tuple;
1994
update_tuple= ib_clust_read_tuple_create(cursor);
1996
err= ib_tuple_copy(update_tuple, tuple);
1997
assert(err == DB_SUCCESS);
1999
write_row_to_haildb_tuple(getTable()->getFields(), update_tuple);
2001
err= ib_cursor_update_row(cursor, tuple, update_tuple);
2003
ib_tuple_delete(update_tuple);
2005
advance_cursor= true;
2007
if (err == DB_SUCCESS)
2009
else if (err == DB_DUPLICATE_KEY)
2010
return HA_ERR_FOUND_DUPP_KEY;
2015
int HailDBCursor::doDeleteRecord(const unsigned char *)
2019
err= ib_cursor_delete_row(cursor);
2020
if (err != DB_SUCCESS)
2023
advance_cursor= true;
2027
int HailDBCursor::delete_all_rows(void)
2029
/* I *think* ib_truncate is non-transactional....
2030
so only support TRUNCATE and not DELETE FROM t;
2031
(this is what ha_haildb does)
2033
if (session_sql_command(getTable()->in_use) != SQLCOM_TRUNCATE)
2034
return HA_ERR_WRONG_COMMAND;
2039
ib_trx_t transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
2041
ib_cursor_attach_trx(cursor, transaction);
2043
err= ib_schema_lock_exclusive(transaction);
2044
if (err != DB_SUCCESS)
2046
ib_err_t rollback_err= ib_trx_rollback(transaction);
2048
push_warning_printf(getTable()->in_use, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
2049
ER_CANT_DELETE_FILE,
2050
_("Cannot Lock HailDB Data Dictionary. HailDB Error %d (%s)\n"),
2051
err, ib_strerror(err));
2053
assert (rollback_err == DB_SUCCESS);
2055
return HA_ERR_GENERIC;
2058
share->auto_increment_value.fetch_and_store(1);
2060
err= ib_cursor_truncate(&cursor, &id);
2061
if (err != DB_SUCCESS)
2064
ib_schema_unlock(transaction);
2065
/* ib_cursor_truncate commits on success */
2067
err= ib_cursor_open_table_using_id(id, NULL, &cursor);
2068
if (err != DB_SUCCESS)
2074
ib_schema_unlock(transaction);
2075
ib_err_t rollback_err= ib_trx_rollback(transaction);
2076
assert(rollback_err == DB_SUCCESS);
2080
int HailDBCursor::doStartTableScan(bool)
2083
ib_trx_t transaction;
2087
in_table_scan= true;
2089
transaction= *get_trx(getTable()->in_use);
2091
assert(transaction != NULL);
2093
ib_cursor_attach_trx(cursor, transaction);
2095
err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
2096
assert(err == DB_SUCCESS); // FIXME
2098
tuple= ib_clust_read_tuple_create(cursor);
2100
err= ib_cursor_first(cursor);
2101
if (err != DB_SUCCESS && err != DB_END_OF_INDEX)
2103
previous_error= ib_err_t_to_drizzle_error(err);
2104
err= ib_cursor_reset(cursor);
2105
return previous_error;
2108
advance_cursor= false;
2114
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)
2117
ptrdiff_t row_offset= buf - table->getInsertRecord();
2119
err= ib_cursor_read_row(cursor, tuple);
2121
if (err != DB_SUCCESS) // FIXME
2122
return HA_ERR_END_OF_FILE;
2126
/* We need the primary key for ::position() to work */
2127
if (table->getShare()->getPrimaryKey() != MAX_KEY)
2128
table->mark_columns_used_by_index_no_reset(table->getShare()->getPrimaryKey());
2130
for (Field **field= table->getFields() ; *field ; field++, colnr++)
2132
if (! (**field).isReadSet())
2135
(**field).move_field_offset(row_offset);
2137
(**field).setWriteSet();
2139
uint32_t length= ib_col_get_len(tuple, colnr);
2140
if (length == IB_SQL_NULL)
2142
(**field).set_null();
2146
(**field).set_notnull();
2148
if ((**field).type() == DRIZZLE_TYPE_VARCHAR)
2150
(*field)->store((const char*)ib_col_get_value(tuple, colnr),
2154
else if ((**field).type() == DRIZZLE_TYPE_DATE)
2157
err= ib_tuple_read_u32(tuple, colnr, &date_read);
2158
(*field)->store(date_read);
2160
else if ((**field).type() == DRIZZLE_TYPE_BLOB)
2162
if (blobroot == NULL)
2163
(reinterpret_cast<Field_blob*>(*field))->set_ptr(length,
2164
(unsigned char*)ib_col_get_value(tuple,
2168
if (*blobroot == NULL)
2170
*blobroot= new drizzled::memory::Root();
2171
(**blobroot).init_alloc_root();
2174
unsigned char *blob_ptr= (unsigned char*)(**blobroot).alloc_root(length);
2175
memcpy(blob_ptr, ib_col_get_value(tuple, colnr), length);
2176
(reinterpret_cast<Field_blob*>(*field))->set_ptr(length, blob_ptr);
2181
ib_col_copy_value(tuple, colnr, (*field)->ptr, (*field)->data_length());
2184
(**field).move_field_offset(-row_offset);
2188
if (has_hidden_primary_key)
2190
err= ib_tuple_read_u64(tuple, colnr, hidden_pkey);
2196
int HailDBCursor::rnd_next(unsigned char *buf)
2202
return previous_error;
2205
err= ib_cursor_next(cursor);
2207
tuple= ib_tuple_clear(tuple);
2208
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2209
share->has_hidden_primary_key,
2210
&hidden_autoinc_pkey_position);
2212
advance_cursor= true;
2216
int HailDBCursor::doEndTableScan()
2220
ib_tuple_delete(tuple);
2221
err= ib_cursor_reset(cursor);
2222
assert(err == DB_SUCCESS);
2223
in_table_scan= false;
2228
int HailDBCursor::rnd_pos(unsigned char *buf, unsigned char *pos)
2233
ib_tpl_t search_tuple= ib_clust_search_tuple_create(cursor);
2235
if (share->has_hidden_primary_key)
2237
err= ib_col_set_value(search_tuple, 0,
2238
((uint64_t*)(pos)), sizeof(uint64_t));
2243
if (getTable()->getShare()->getPrimaryKey() != MAX_KEY)
2244
keynr= getTable()->getShare()->getPrimaryKey();
2246
keynr= get_first_unique_index(*getTable());
2248
fill_ib_search_tpl_from_drizzle_key(search_tuple,
2249
getTable()->key_info + keynr,
2253
err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
2254
assert(err == DB_SUCCESS);
2260
ib_tuple_delete(search_tuple);
2262
tuple= ib_tuple_clear(tuple);
2265
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2266
share->has_hidden_primary_key,
2267
&hidden_autoinc_pkey_position);
2269
advance_cursor= true;
2274
static void store_key_value_from_haildb(KeyInfo *key_info, unsigned char* ref, int ref_len, const unsigned char *record)
2276
KeyPartInfo* key_part= key_info->key_part;
2277
KeyPartInfo* end= key_info->key_part + key_info->key_parts;
2278
unsigned char* ref_start= ref;
2280
memset(ref, 0, ref_len);
2282
for (; key_part != end; key_part++)
2286
if(key_part->null_bit)
2288
*ref= is_null= record[key_part->null_offset] & key_part->null_bit;
2292
Field *field= key_part->field;
2294
if (field->type() == DRIZZLE_TYPE_VARCHAR)
2298
ref+= key_part->length + 2; /* 2 bytes for length */
2303
field->val_str(&str);
2305
*ref++= (char)(str.length() & 0x000000ff);
2306
*ref++= (char)((str.length()>>8) & 0x000000ff);
2308
memcpy(ref, str.ptr(), str.length());
2309
ref+= key_part->length;
2316
ref+= key_part->length;
2320
memcpy(ref, record+key_part->offset, key_part->length);
2321
ref+= key_part->length;
2326
assert(ref == ref_start + ref_len);
2329
void HailDBCursor::position(const unsigned char *record)
2331
if (share->has_hidden_primary_key)
2332
*((uint64_t*) ref)= hidden_autoinc_pkey_position;
2336
if (getTable()->getShare()->getPrimaryKey() != MAX_KEY)
2337
keynr= getTable()->getShare()->getPrimaryKey();
2339
keynr= get_first_unique_index(*getTable());
2341
store_key_value_from_haildb(getTable()->key_info + keynr,
2342
ref, ref_length, record);
2348
double HailDBCursor::scan_time()
2350
ib_table_stats_t table_stats;
2353
err= ib_get_table_statistics(cursor, &table_stats, sizeof(table_stats));
2355
/* Approximate I/O seeks for full table scan */
2356
return (double) (table_stats.stat_clustered_index_size / 16384);
2359
int HailDBCursor::info(uint32_t flag)
2361
ib_table_stats_t table_stats;
2364
if (flag & HA_STATUS_VARIABLE)
2366
err= ib_get_table_statistics(cursor, &table_stats, sizeof(table_stats));
2368
stats.records= table_stats.stat_n_rows;
2370
if (table_stats.stat_n_rows < 2)
2374
stats.data_file_length= table_stats.stat_clustered_index_size;
2375
stats.index_file_length= table_stats.stat_sum_of_other_index_sizes;
2377
stats.mean_rec_length= stats.data_file_length / stats.records;
2380
if (flag & HA_STATUS_AUTO)
2381
stats.auto_increment_value= 1;
2385
int HailDBCursor::doStartIndexScan(uint32_t keynr, bool)
2387
ib_trx_t transaction= *get_trx(getTable()->in_use);
2389
active_index= keynr;
2391
ib_cursor_attach_trx(cursor, transaction);
2393
if (active_index == 0 && ! share->has_hidden_primary_key)
2395
tuple= ib_clust_read_tuple_create(cursor);
2401
err= ib_index_get_id(table_path_to_haildb_name(getShare()->getPath()),
2402
getShare()->getKeyInfo(keynr).name,
2404
if (err != DB_SUCCESS)
2407
err= ib_cursor_close(cursor);
2408
assert(err == DB_SUCCESS);
2409
err= ib_cursor_open_index_using_id(index_id, transaction, &cursor);
2411
if (err != DB_SUCCESS)
2414
tuple= ib_clust_read_tuple_create(cursor);
2415
ib_cursor_set_cluster_access(cursor);
2418
ib_err_t err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
2419
assert(err == DB_SUCCESS);
2421
advance_cursor= false;
2425
static ib_srch_mode_t ha_rkey_function_to_ib_srch_mode(drizzled::ha_rkey_function find_flag)
2429
case HA_READ_KEY_EXACT:
2431
case HA_READ_KEY_OR_NEXT:
2433
case HA_READ_KEY_OR_PREV:
2435
case HA_READ_AFTER_KEY:
2437
case HA_READ_BEFORE_KEY:
2439
case HA_READ_PREFIX:
2441
case HA_READ_PREFIX_LAST:
2443
case HA_READ_PREFIX_LAST_OR_PREV:
2445
case HA_READ_MBR_CONTAIN:
2446
case HA_READ_MBR_INTERSECT:
2447
case HA_READ_MBR_WITHIN:
2448
case HA_READ_MBR_DISJOINT:
2449
case HA_READ_MBR_EQUAL:
2450
assert(false); /* these just exist in the enum, not used. */
2454
/* Must return or compiler complains about reaching end of function */
2455
return (ib_srch_mode_t)0;
2458
static void fill_ib_search_tpl_from_drizzle_key(ib_tpl_t search_tuple,
2459
const drizzled::KeyInfo *key_info,
2460
const unsigned char *key_ptr,
2463
KeyPartInfo *key_part= key_info->key_part;
2464
KeyPartInfo *end= key_part + key_info->key_parts;
2465
const unsigned char *buff= key_ptr;
2470
for(; key_part != end && buff < key_ptr + key_len; key_part++)
2472
Field *field= key_part->field;
2473
bool is_null= false;
2475
if (key_part->null_bit)
2480
err= ib_col_set_value(search_tuple, fieldnr, NULL, IB_SQL_NULL);
2481
assert(err == DB_SUCCESS);
2486
if (field->type() == DRIZZLE_TYPE_VARCHAR)
2490
buff+= key_part->length + 2; /* 2 bytes length */
2494
int length= *buff + (*(buff + 1) << 8);
2496
err= ib_col_set_value(search_tuple, fieldnr, buff, length);
2497
assert(err == DB_SUCCESS);
2499
buff+= key_part->length;
2501
else if (field->type() == DRIZZLE_TYPE_DATE)
2503
uint32_t date_int= static_cast<uint32_t>(field->val_int());
2504
err= ib_col_set_value(search_tuple, fieldnr, &date_int, 4);
2505
buff+= key_part->length;
2512
buff+= key_part->length;
2516
err= ib_col_set_value(search_tuple, fieldnr,
2517
buff, key_part->length);
2518
assert(err == DB_SUCCESS);
2520
buff+= key_part->length;
2526
assert(buff == key_ptr + key_len);
2529
int HailDBCursor::haildb_index_read(unsigned char *buf,
2530
const unsigned char *key_ptr,
2532
drizzled::ha_rkey_function find_flag,
2533
bool allocate_blobs)
2535
ib_tpl_t search_tuple;
2539
ib_srch_mode_t search_mode;
2541
search_mode= ha_rkey_function_to_ib_srch_mode(find_flag);
2543
if (active_index == 0 && ! share->has_hidden_primary_key)
2544
search_tuple= ib_clust_search_tuple_create(cursor);
2546
search_tuple= ib_sec_search_tuple_create(cursor);
2548
fill_ib_search_tpl_from_drizzle_key(search_tuple,
2549
getTable()->key_info + active_index,
2552
err= ib_cursor_moveto(cursor, search_tuple, search_mode, &res);
2553
ib_tuple_delete(search_tuple);
2555
if ((err == DB_RECORD_NOT_FOUND || err == DB_END_OF_INDEX))
2557
getTable()->status= STATUS_NOT_FOUND;
2558
return HA_ERR_KEY_NOT_FOUND;
2561
if (err != DB_SUCCESS)
2563
return ib_err_t_to_drizzle_error(err);
2566
tuple= ib_tuple_clear(tuple);
2567
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2568
share->has_hidden_primary_key,
2569
&hidden_autoinc_pkey_position,
2570
(allocate_blobs)? &blobroot : NULL);
2572
getTable()->status= 0;
2574
getTable()->status= STATUS_NOT_FOUND;
2576
advance_cursor= true;
2581
int HailDBCursor::index_read(unsigned char *buf,
2582
const unsigned char *key_ptr,
2584
drizzled::ha_rkey_function find_flag)
2586
return haildb_index_read(buf, key_ptr, key_len, find_flag, false);
2589
/* This is straight from cursor.cc, but it's private there :( */
2590
uint32_t HailDBCursor::calculate_key_len(uint32_t key_position,
2591
key_part_map keypart_map_arg)
2593
/* works only with key prefixes */
2594
assert(((keypart_map_arg + 1) & keypart_map_arg) == 0);
2596
KeyPartInfo *key_part_found= getTable()->getShare()->getKeyInfo(key_position).key_part;
2597
KeyPartInfo *end_key_part_found= key_part_found + getTable()->getShare()->getKeyInfo(key_position).key_parts;
2600
while (key_part_found < end_key_part_found && keypart_map_arg)
2602
length+= key_part_found->store_length;
2603
keypart_map_arg >>= 1;
2610
int HailDBCursor::haildb_index_read_map(unsigned char * buf,
2611
const unsigned char *key,
2612
key_part_map keypart_map,
2613
enum ha_rkey_function find_flag,
2614
bool allocate_blobs)
2616
uint32_t key_len= calculate_key_len(active_index, keypart_map);
2617
return haildb_index_read(buf, key, key_len, find_flag, allocate_blobs);
2620
int HailDBCursor::index_read_idx_map(unsigned char * buf,
2622
const unsigned char * key,
2623
key_part_map keypart_map,
2624
enum ha_rkey_function find_flag)
2627
error= doStartIndexScan(index, 0);
2630
error= haildb_index_read_map(buf, key, keypart_map, find_flag, true);
2631
error1= doEndIndexScan();
2633
return error ? error : error1;
2636
int HailDBCursor::reset()
2639
blobroot->free_root(MYF(0));
2644
int HailDBCursor::index_next(unsigned char *buf)
2646
int ret= HA_ERR_END_OF_FILE;
2650
ib_err_t err= ib_cursor_next(cursor);
2651
if (err == DB_END_OF_INDEX)
2652
return HA_ERR_END_OF_FILE;
2655
tuple= ib_tuple_clear(tuple);
2656
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2657
share->has_hidden_primary_key,
2658
&hidden_autoinc_pkey_position);
2660
advance_cursor= true;
2664
int HailDBCursor::doEndIndexScan()
2666
active_index= MAX_KEY;
2668
return doEndTableScan();
2671
int HailDBCursor::index_prev(unsigned char *buf)
2673
int ret= HA_ERR_END_OF_FILE;
2678
err= ib_cursor_prev(cursor);
2679
if (err != DB_SUCCESS)
2681
if (err == DB_END_OF_INDEX)
2682
return HA_ERR_END_OF_FILE;
2688
tuple= ib_tuple_clear(tuple);
2689
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2690
share->has_hidden_primary_key,
2691
&hidden_autoinc_pkey_position);
2693
advance_cursor= true;
2699
int HailDBCursor::index_first(unsigned char *buf)
2701
int ret= HA_ERR_END_OF_FILE;
2704
err= ib_cursor_first(cursor);
2705
if (err != DB_SUCCESS)
2706
return ib_err_t_to_drizzle_error(err);
2708
tuple= ib_tuple_clear(tuple);
2709
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2710
share->has_hidden_primary_key,
2711
&hidden_autoinc_pkey_position);
2713
advance_cursor= true;
2719
int HailDBCursor::index_last(unsigned char *buf)
2721
int ret= HA_ERR_END_OF_FILE;
2724
err= ib_cursor_last(cursor);
2725
if (err != DB_SUCCESS)
2726
return ib_err_t_to_drizzle_error(err);
2728
tuple= ib_tuple_clear(tuple);
2729
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2730
share->has_hidden_primary_key,
2731
&hidden_autoinc_pkey_position);
2732
advance_cursor= true;
2737
int HailDBCursor::extra(enum ha_extra_function operation)
2741
case HA_EXTRA_FLUSH:
2743
blobroot->free_root(MYF(0));
2745
case HA_EXTRA_WRITE_CAN_REPLACE:
2746
write_can_replace= true;
2748
case HA_EXTRA_WRITE_CANNOT_REPLACE:
2749
write_can_replace= false;
2758
static int create_table_message_table()
2760
ib_tbl_sch_t schema;
2761
ib_idx_sch_t index_schema;
2762
ib_trx_t transaction;
2764
ib_err_t err, rollback_err;
2765
ib_bool_t create_db_err;
2767
create_db_err= ib_database_create("data_dictionary");
2768
if (create_db_err != IB_TRUE)
2771
err= ib_table_schema_create(HAILDB_TABLE_DEFINITIONS_TABLE, &schema,
2773
if (err != DB_SUCCESS)
2776
err= ib_table_schema_add_col(schema, "table_name", IB_VARCHAR, IB_COL_NONE, 0,
2777
IB_MAX_TABLE_NAME_LEN);
2778
if (err != DB_SUCCESS)
2781
err= ib_table_schema_add_col(schema, "message", IB_BLOB, IB_COL_NONE, 0, 0);
2782
if (err != DB_SUCCESS)
2785
err= ib_table_schema_add_index(schema, "PRIMARY_KEY", &index_schema);
2786
if (err != DB_SUCCESS)
2789
err= ib_index_schema_add_col(index_schema, "table_name", 0);
2790
if (err != DB_SUCCESS)
2792
err= ib_index_schema_set_clustered(index_schema);
2793
if (err != DB_SUCCESS)
2796
transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
2797
err= ib_schema_lock_exclusive(transaction);
2798
if (err != DB_SUCCESS)
2801
err= ib_table_create(transaction, schema, &table_id);
2802
if (err != DB_SUCCESS)
2805
err= ib_trx_commit(transaction);
2806
if (err != DB_SUCCESS)
2809
ib_table_schema_delete(schema);
2813
ib_schema_unlock(transaction);
2814
rollback_err= ib_trx_rollback(transaction);
2815
assert(rollback_err == DB_SUCCESS);
2817
ib_table_schema_delete(schema);
2821
static char* innobase_log_group_home_dir = NULL;
2822
static bool innobase_use_doublewrite= true;
2823
static unsigned long innobase_fast_shutdown= 1;
2824
static bool srv_file_per_table= false;
2825
static bool innobase_adaptive_hash_index;
2826
static bool srv_adaptive_flushing;
2827
static bool innobase_print_verbose_log;
2828
static bool innobase_rollback_on_timeout;
2829
static bool innobase_create_status_file;
2830
static bool srv_use_sys_malloc;
2831
static char* innobase_file_format_name = const_cast<char *>("Barracuda");
2832
static char* innobase_unix_file_flush_method = NULL;
2833
static unsigned long srv_flush_log_at_trx_commit;
2834
static unsigned long srv_max_buf_pool_modified_pct;
2835
static unsigned long srv_max_purge_lag;
2836
static unsigned long innobase_lru_old_blocks_pct;
2837
static unsigned long innobase_lru_block_access_recency;
2838
static unsigned long innobase_read_io_threads;
2839
static unsigned long innobase_write_io_threads;
2840
typedef constrained_check<unsigned int, 1000, 1> autoextend_constraint;
2841
static autoextend_constraint srv_auto_extend_increment;
2842
static unsigned long innobase_lock_wait_timeout;
2843
static unsigned long srv_n_spin_wait_rounds;
2844
typedef constrained_check<size_t, SIZE_MAX, 5242880, 1048576> buffer_pool_constraint;
2845
static buffer_pool_constraint innobase_buffer_pool_size;
2846
typedef constrained_check<size_t, SIZE_MAX, 512, 1024> additional_mem_pool_constraint;
2847
static additional_mem_pool_constraint innobase_additional_mem_pool_size;
2848
static bool innobase_use_checksums= true;
2849
typedef constrained_check<unsigned int, UINT_MAX, 100> io_capacity_constraint;
2850
static io_capacity_constraint srv_io_capacity;
2852
static long innobase_open_files;
2853
static long innobase_force_recovery;
2854
static long innobase_log_buffer_size;
2855
static char default_haildb_data_file_path[]= "ibdata1:10M:autoextend";
2856
static char* haildb_data_file_path= NULL;
2858
static int64_t haildb_log_file_size;
2859
static int64_t haildb_log_files_in_group;
2861
static int haildb_init(drizzled::module::Context &context)
2863
haildb_system_table_names.insert(std::string("HAILDB_SYS_TABLES"));
2864
haildb_system_table_names.insert(std::string("HAILDB_SYS_COLUMNS"));
2865
haildb_system_table_names.insert(std::string("HAILDB_SYS_INDEXES"));
2866
haildb_system_table_names.insert(std::string("HAILDB_SYS_FIELDS"));
2867
haildb_system_table_names.insert(std::string("HAILDB_SYS_FOREIGN"));
2868
haildb_system_table_names.insert(std::string("HAILDB_SYS_FOREIGN_COLS"));
2870
const module::option_map &vm= context.getOptions();
2872
/* Inverted Booleans */
2874
innobase_adaptive_hash_index= (vm.count("disable-adaptive-hash-index")) ? false : true;
2875
srv_adaptive_flushing= (vm.count("disable-adaptive-flushing")) ? false : true;
2876
innobase_use_checksums= (vm.count("disable-checksums")) ? false : true;
2877
innobase_use_doublewrite= (vm.count("disable-doublewrite")) ? false : true;
2878
innobase_print_verbose_log= (vm.count("disable-print-verbose-log")) ? false : true;
2879
srv_use_sys_malloc= (vm.count("use-internal-malloc")) ? false : true;
2881
if (vm.count("fast-shutdown"))
2883
if (innobase_fast_shutdown > 2)
2885
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of fast-shutdown"));
2890
if (vm.count("flush-log-at-trx-commit"))
2892
if (srv_flush_log_at_trx_commit > 2)
2894
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of flush-log-at-trx-commit"));
2899
if (vm.count("force-recovery"))
2901
if (innobase_force_recovery > 6)
2903
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of force-recovery"));
2908
if (vm.count("log-file-size"))
2910
if (haildb_log_file_size > INT64_MAX || haildb_log_file_size < 1*1024*1024L)
2912
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of log-file-size"));
2915
haildb_log_file_size/= 1024*1024L;
2916
haildb_log_file_size*= 1024*1024L;
2919
if (vm.count("log-files-in-group"))
2921
if (haildb_log_files_in_group > 100 || haildb_log_files_in_group < 2)
2923
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of log-files-in-group"));
2928
if (vm.count("lock-wait-timeout"))
2930
if (innobase_lock_wait_timeout > 1024*1024*1024 || innobase_lock_wait_timeout < 1)
2932
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of lock-wait-timeout"));
2937
if (vm.count("log-buffer-size"))
2939
if (innobase_log_buffer_size > LONG_MAX || innobase_log_buffer_size < 256*1024L)
2941
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of log-buffer-size"));
2944
innobase_log_buffer_size/= 1024;
2945
innobase_log_buffer_size*= 1024;
2948
if (vm.count("lru-old-blocks-pct"))
2950
if (innobase_lru_old_blocks_pct > 95 || innobase_lru_old_blocks_pct < 5)
2952
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of lru-old-blocks-pct"));
2957
if (vm.count("lru-block-access-recency"))
2959
if (innobase_lru_block_access_recency > ULONG_MAX)
2961
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of lru-block-access-recency"));
2966
if (vm.count("max-dirty-pages-pct"))
2968
if (srv_max_buf_pool_modified_pct > 99)
2970
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of max-dirty-pages-pct"));
2975
if (vm.count("max-purge-lag"))
2977
if (srv_max_purge_lag > (unsigned long)~0L)
2979
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of max-purge-lag"));
2984
if (vm.count("open-files"))
2986
if (innobase_open_files > LONG_MAX || innobase_open_files < 10L)
2988
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of open-files"));
2993
if (vm.count("read-io-threads"))
2995
if (innobase_read_io_threads > 64 || innobase_read_io_threads < 1)
2997
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of read-io-threads"));
3002
if (vm.count("sync-spin-loops"))
3004
if (srv_n_spin_wait_rounds > (unsigned long)~0L)
3006
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of sync_spin_loops"));
3011
if (vm.count("file-format"))
3013
innobase_file_format_name= const_cast<char *>(vm["file-format"].as<string>().c_str());
3016
if (vm.count("log-group-home-dir"))
3018
innobase_log_group_home_dir= const_cast<char *>(vm["log-group-home-dir"].as<string>().c_str());
3021
if (vm.count("flush-method"))
3023
innobase_unix_file_flush_method= const_cast<char *>(vm["flush-method"].as<string>().c_str());
3026
if (vm.count("data-file-path"))
3028
haildb_data_file_path= const_cast<char *>(vm["data-file-path"].as<string>().c_str());
3034
if (err != DB_SUCCESS)
3038
if (vm.count("data-home-dir"))
3040
err= ib_cfg_set_text("data_home_dir", vm["data-home-dir"].as<string>().c_str());
3041
if (err != DB_SUCCESS)
3045
if (innobase_log_group_home_dir)
3047
err= ib_cfg_set_text("log_group_home_dir", innobase_log_group_home_dir);
3048
if (err != DB_SUCCESS)
3052
if (haildb_data_file_path == NULL)
3053
haildb_data_file_path= default_haildb_data_file_path;
3055
if (innobase_print_verbose_log)
3056
err= ib_cfg_set_bool_on("print_verbose_log");
3058
err= ib_cfg_set_bool_off("print_verbose_log");
3060
if (err != DB_SUCCESS)
3063
if (innobase_rollback_on_timeout)
3064
err= ib_cfg_set_bool_on("rollback_on_timeout");
3066
err= ib_cfg_set_bool_off("rollback_on_timeout");
3068
if (err != DB_SUCCESS)
3071
if (innobase_use_doublewrite)
3072
err= ib_cfg_set_bool_on("doublewrite");
3074
err= ib_cfg_set_bool_off("doublewrite");
3076
if (err != DB_SUCCESS)
3079
if (innobase_adaptive_hash_index)
3080
err= ib_cfg_set_bool_on("adaptive_hash_index");
3082
err= ib_cfg_set_bool_off("adaptive_hash_index");
3084
if (err != DB_SUCCESS)
3087
if (srv_adaptive_flushing)
3088
err= ib_cfg_set_bool_on("adaptive_flushing");
3090
err= ib_cfg_set_bool_off("adaptive_flushing");
3092
if (err != DB_SUCCESS)
3095
err= ib_cfg_set_int("additional_mem_pool_size", static_cast<size_t>(innobase_additional_mem_pool_size));
3096
if (err != DB_SUCCESS)
3099
err= ib_cfg_set_int("autoextend_increment", static_cast<unsigned int>(srv_auto_extend_increment));
3100
if (err != DB_SUCCESS)
3103
err= ib_cfg_set_int("buffer_pool_size", static_cast<size_t>(innobase_buffer_pool_size));
3104
if (err != DB_SUCCESS)
3107
err= ib_cfg_set_int("io_capacity", static_cast<unsigned int>(srv_io_capacity));
3108
if (err != DB_SUCCESS)
3111
if (srv_file_per_table)
3112
err= ib_cfg_set_bool_on("file_per_table");
3114
err= ib_cfg_set_bool_off("file_per_table");
3116
if (err != DB_SUCCESS)
3119
err= ib_cfg_set_int("flush_log_at_trx_commit", srv_flush_log_at_trx_commit);
3120
if (err != DB_SUCCESS)
3123
if (innobase_unix_file_flush_method)
3125
err= ib_cfg_set_text("flush_method", innobase_unix_file_flush_method);
3126
if (err != DB_SUCCESS)
3130
err= ib_cfg_set_int("force_recovery", innobase_force_recovery);
3131
if (err != DB_SUCCESS)
3134
err= ib_cfg_set_text("data_file_path", haildb_data_file_path);
3135
if (err != DB_SUCCESS)
3138
err= ib_cfg_set_int("log_file_size", haildb_log_file_size);
3139
if (err != DB_SUCCESS)
3142
err= ib_cfg_set_int("log_buffer_size", innobase_log_buffer_size);
3143
if (err != DB_SUCCESS)
3146
err= ib_cfg_set_int("log_files_in_group", haildb_log_files_in_group);
3147
if (err != DB_SUCCESS)
3150
err= ib_cfg_set_int("checksums", innobase_use_checksums);
3151
if (err != DB_SUCCESS)
3154
err= ib_cfg_set_int("lock_wait_timeout", innobase_lock_wait_timeout);
3155
if (err != DB_SUCCESS)
3158
err= ib_cfg_set_int("max_dirty_pages_pct", srv_max_buf_pool_modified_pct);
3159
if (err != DB_SUCCESS)
3162
err= ib_cfg_set_int("max_purge_lag", srv_max_purge_lag);
3163
if (err != DB_SUCCESS)
3166
err= ib_cfg_set_int("open_files", innobase_open_files);
3167
if (err != DB_SUCCESS)
3170
err= ib_cfg_set_int("read_io_threads", innobase_read_io_threads);
3171
if (err != DB_SUCCESS)
3174
err= ib_cfg_set_int("write_io_threads", innobase_write_io_threads);
3175
if (err != DB_SUCCESS)
3178
err= ib_cfg_set_int("sync_spin_loops", srv_n_spin_wait_rounds);
3179
if (err != DB_SUCCESS)
3182
if (srv_use_sys_malloc)
3183
err= ib_cfg_set_bool_on("use_sys_malloc");
3185
err= ib_cfg_set_bool_off("use_sys_malloc");
3187
if (err != DB_SUCCESS)
3190
err= ib_startup(innobase_file_format_name);
3191
if (err != DB_SUCCESS)
3194
create_table_message_table();
3196
haildb_engine= new HailDBEngine("InnoDB");
3197
context.add(haildb_engine);
3198
context.registerVariable(new sys_var_bool_ptr_readonly("adaptive_hash_index",
3199
&innobase_adaptive_hash_index));
3200
context.registerVariable(new sys_var_bool_ptr_readonly("adaptive_flushing",
3201
&srv_adaptive_flushing));
3202
context.registerVariable(new sys_var_constrained_value_readonly<size_t>("additional_mem_pool_size",innobase_additional_mem_pool_size));
3203
context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("autoextend_increment", srv_auto_extend_increment));
3204
context.registerVariable(new sys_var_constrained_value_readonly<size_t>("buffer_pool_size", innobase_buffer_pool_size));
3205
context.registerVariable(new sys_var_bool_ptr_readonly("checksums",
3206
&innobase_use_checksums));
3207
context.registerVariable(new sys_var_bool_ptr_readonly("doublewrite",
3208
&innobase_use_doublewrite));
3209
context.registerVariable(new sys_var_const_string_val("data_home_dir",
3210
vm.count("data-home-dir") ? vm["data-home-dir"].as<string>() : ""));
3211
context.registerVariable(new sys_var_constrained_value_readonly<unsigned int>("io_capacity", srv_io_capacity));
3213
haildb_datadict_dump_func_initialize(context);
3214
config_table_function_initialize(context);
3215
status_table_function_initialize(context);
3219
fprintf(stderr, _("Error starting HailDB %d (%s)\n"),
3220
err, ib_strerror(err));
3225
HailDBEngine::~HailDBEngine()
3228
ib_shutdown_t shutdown_flag= IB_SHUTDOWN_NORMAL;
3230
if (innobase_fast_shutdown == 1)
3231
shutdown_flag= IB_SHUTDOWN_NO_IBUFMERGE_PURGE;
3232
else if (innobase_fast_shutdown == 2)
3233
shutdown_flag= IB_SHUTDOWN_NO_BUFPOOL_FLUSH;
3235
err= ib_shutdown(shutdown_flag);
3237
if (err != DB_SUCCESS)
3239
fprintf(stderr,"Error %d shutting down HailDB!\n", err);
3244
static char haildb_file_format_name_storage[100];
3246
static int haildb_file_format_name_validate(Session*, drizzle_sys_var*,
3248
drizzle_value *value)
3252
int len= sizeof(buff);
3253
const char *format= value->val_str(value, buff, &len);
3255
*static_cast<const char**>(save)= NULL;
3260
err= ib_cfg_set_text("file_format", format);
3262
if (err == DB_SUCCESS)
3264
strncpy(haildb_file_format_name_storage, format, sizeof(haildb_file_format_name_storage));;
3265
haildb_file_format_name_storage[sizeof(haildb_file_format_name_storage)-1]= 0;
3267
*static_cast<const char**>(save)= haildb_file_format_name_storage;
3274
static void haildb_file_format_name_update(Session*, drizzle_sys_var*,
3281
assert(var_ptr != NULL);
3282
assert(save != NULL);
3284
format= *static_cast<const char*const*>(save);
3286
/* Format is already set in validate */
3287
memmove(haildb_file_format_name_storage, format, sizeof(haildb_file_format_name_storage));;
3288
haildb_file_format_name_storage[sizeof(haildb_file_format_name_storage)-1]= 0;
3290
*static_cast<const char**>(var_ptr)= haildb_file_format_name_storage;
3293
static void haildb_lru_old_blocks_pct_update(Session*, drizzle_sys_var*,
3300
pct= *static_cast<const unsigned long*>(save);
3302
ib_err_t err= ib_cfg_set_int("lru_old_blocks_pct", pct);
3303
if (err == DB_SUCCESS)
3304
innobase_lru_old_blocks_pct= pct;
3307
static void haildb_lru_block_access_recency_update(Session*, drizzle_sys_var*,
3314
ms= *static_cast<const unsigned long*>(save);
3316
ib_err_t err= ib_cfg_set_int("lru_block_access_recency", ms);
3318
if (err == DB_SUCCESS)
3319
innobase_lru_block_access_recency= ms;
3322
static void haildb_status_file_update(Session*, drizzle_sys_var*,
3327
bool status_file_enabled;
3330
status_file_enabled= *static_cast<const bool*>(save);
3333
if (status_file_enabled)
3334
err= ib_cfg_set_bool_on("status_file");
3336
err= ib_cfg_set_bool_off("status_file");
3338
if (err == DB_SUCCESS)
3339
innobase_create_status_file= status_file_enabled;
3342
static DRIZZLE_SYSVAR_ULONG(fast_shutdown, innobase_fast_shutdown,
3343
PLUGIN_VAR_OPCMDARG,
3344
"Speeds up the shutdown process of the HailDB storage engine. Possible "
3345
"values are 0, 1 (faster)"
3346
" or 2 (fastest - crash-like)"
3348
NULL, NULL, 1, 0, 2, 0);
3350
static DRIZZLE_SYSVAR_BOOL(file_per_table, srv_file_per_table,
3351
PLUGIN_VAR_NOCMDARG,
3352
"Stores each HailDB table to an .ibd file in the database dir.",
3355
static DRIZZLE_SYSVAR_STR(file_format, innobase_file_format_name,
3356
PLUGIN_VAR_RQCMDARG,
3357
"File format to use for new tables in .ibd files.",
3358
haildb_file_format_name_validate,
3359
haildb_file_format_name_update, "Barracuda");
3361
static DRIZZLE_SYSVAR_ULONG(flush_log_at_trx_commit, srv_flush_log_at_trx_commit,
3362
PLUGIN_VAR_OPCMDARG,
3363
"Set to 0 (write and flush once per second),"
3364
" 1 (write and flush at each commit)"
3365
" or 2 (write at commit, flush once per second).",
3366
NULL, NULL, 1, 0, 2, 0);
3368
static DRIZZLE_SYSVAR_STR(flush_method, innobase_unix_file_flush_method,
3369
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
3370
"With which method to flush data.", NULL, NULL, NULL);
3372
static DRIZZLE_SYSVAR_LONG(force_recovery, innobase_force_recovery,
3373
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
3374
"Helps to save your data in case the disk image of the database becomes corrupt.",
3375
NULL, NULL, 0, 0, 6, 0);
3377
static DRIZZLE_SYSVAR_STR(data_file_path, haildb_data_file_path,
3378
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
3379
"Path to individual files and their sizes.",
3382
static DRIZZLE_SYSVAR_STR(log_group_home_dir, innobase_log_group_home_dir,
3383
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
3384
"Path to HailDB log files.", NULL, NULL, NULL);
3386
static DRIZZLE_SYSVAR_LONGLONG(log_file_size, haildb_log_file_size,
3387
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
3388
"Size of each log file in a log group.",
3389
NULL, NULL, 20*1024*1024L, 1*1024*1024L, INT64_MAX, 1024*1024L);
3391
static DRIZZLE_SYSVAR_LONGLONG(log_files_in_group, haildb_log_files_in_group,
3392
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
3393
"Number of log files in the log group. HailDB writes to the files in a circular fashion. Value 3 is recommended here.",
3394
NULL, NULL, 2, 2, 100, 0);
3396
static DRIZZLE_SYSVAR_ULONG(lock_wait_timeout, innobase_lock_wait_timeout,
3397
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
3398
"Timeout in seconds an HailDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout.",
3399
NULL, NULL, 5, 1, 1024 * 1024 * 1024, 0);
3401
static DRIZZLE_SYSVAR_LONG(log_buffer_size, innobase_log_buffer_size,
3402
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
3403
"The size of the buffer which HailDB uses to write log to the log files on disk.",
3404
NULL, NULL, 8*1024*1024L, 256*1024L, LONG_MAX, 1024);
3406
static DRIZZLE_SYSVAR_ULONG(lru_old_blocks_pct, innobase_lru_old_blocks_pct,
3407
PLUGIN_VAR_RQCMDARG,
3408
"Sets the point in the LRU list from where all pages are classified as "
3409
"old (Advanced users)",
3411
haildb_lru_old_blocks_pct_update, 37, 5, 95, 0);
3413
static DRIZZLE_SYSVAR_ULONG(lru_block_access_recency, innobase_lru_block_access_recency,
3414
PLUGIN_VAR_RQCMDARG,
3415
"Milliseconds between accesses to a block at which it is made young. "
3416
"0=disabled (Advanced users)",
3418
haildb_lru_block_access_recency_update, 0, 0, ULONG_MAX, 0);
3421
static DRIZZLE_SYSVAR_ULONG(max_dirty_pages_pct, srv_max_buf_pool_modified_pct,
3422
PLUGIN_VAR_RQCMDARG,
3423
"Percentage of dirty pages allowed in bufferpool.",
3424
NULL, NULL, 75, 0, 99, 0);
3426
static DRIZZLE_SYSVAR_ULONG(max_purge_lag, srv_max_purge_lag,
3427
PLUGIN_VAR_RQCMDARG,
3428
"Desired maximum length of the purge queue (0 = no limit)",
3429
NULL, NULL, 0, 0, ~0L, 0);
3431
static DRIZZLE_SYSVAR_BOOL(rollback_on_timeout, innobase_rollback_on_timeout,
3432
PLUGIN_VAR_OPCMDARG | PLUGIN_VAR_READONLY,
3433
"Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)",
3436
static DRIZZLE_SYSVAR_LONG(open_files, innobase_open_files,
3437
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
3438
"How many files at the maximum HailDB keeps open at the same time.",
3439
NULL, NULL, 300L, 10L, LONG_MAX, 0);
3441
static DRIZZLE_SYSVAR_ULONG(read_io_threads, innobase_read_io_threads,
3442
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
3443
"Number of background read I/O threads in HailDB.",
3444
NULL, NULL, 4, 1, 64, 0);
3446
static DRIZZLE_SYSVAR_ULONG(write_io_threads, innobase_write_io_threads,
3447
PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
3448
"Number of background write I/O threads in HailDB.",
3449
NULL, NULL, 4, 1, 64, 0);
3451
static DRIZZLE_SYSVAR_BOOL(print_verbose_log, innobase_print_verbose_log,
3452
PLUGIN_VAR_NOCMDARG,
3453
"Disable if you want to reduce the number of messages written to the log (default: enabled).",
3456
static DRIZZLE_SYSVAR_BOOL(status_file, innobase_create_status_file,
3457
PLUGIN_VAR_OPCMDARG,
3458
"Enable SHOW HAILDB STATUS output in the log",
3459
NULL, haildb_status_file_update, false);
3461
static DRIZZLE_SYSVAR_ULONG(sync_spin_loops, srv_n_spin_wait_rounds,
3462
PLUGIN_VAR_RQCMDARG,
3463
"Count of spin-loop rounds in HailDB mutexes (30 by default)",
3464
NULL, NULL, 30L, 0L, ~0L, 0);
3466
static DRIZZLE_SYSVAR_BOOL(use_sys_malloc, srv_use_sys_malloc,
3467
PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
3468
"Use OS memory allocator instead of HailDB's internal memory allocator",
3471
static void init_options(drizzled::module::option_context &context)
3473
context("disable-adaptive-hash-index",
3474
N_("Disable HailDB adaptive hash index (enabled by default)."));
3475
context("disable-adaptive-flushing",
3476
N_("Do not attempt to flush dirty pages to avoid IO bursts at checkpoints."));
3477
context("additional-mem-pool-size",
3478
po::value<additional_mem_pool_constraint>(&innobase_additional_mem_pool_size)->default_value(8*1024*1024L),
3479
N_("Size of a memory pool HailDB uses to store data dictionary information and other internal data structures."));
3480
context("autoextend-increment",
3481
po::value<autoextend_constraint>(&srv_auto_extend_increment)->default_value(8),
3482
N_("Data file autoextend increment in megabytes"));
3483
context("buffer-pool-size",
3484
po::value<buffer_pool_constraint>(&innobase_buffer_pool_size)->default_value(128*1024*1024L),
3485
N_("The size of the memory buffer HailDB uses to cache data and indexes of its tables."));
3486
context("data-home-dir",
3487
po::value<string>(),
3488
N_("The common part for HailDB table spaces."));
3489
context("disable-checksums",
3490
N_("Disable HailDB checksums validation (enabled by default)."));
3491
context("disable-doublewrite",
3492
N_("Disable HailDB doublewrite buffer (enabled by default)."));
3493
context("io-capacity",
3494
po::value<io_capacity_constraint>(&srv_io_capacity)->default_value(200),
3495
N_("Number of IOPs the server can do. Tunes the background IO rate"));
3496
context("fast-shutdown",
3497
po::value<unsigned long>(&innobase_fast_shutdown)->default_value(1),
3498
N_("Speeds up the shutdown process of the HailDB storage engine. Possible values are 0, 1 (faster) or 2 (fastest - crash-like)."));
3499
context("file-per-table",
3500
po::value<bool>(&srv_file_per_table)->default_value(false)->zero_tokens(),
3501
N_("Stores each HailDB table to an .ibd file in the database dir."));
3502
context("file-format",
3503
po::value<string>(),
3504
N_("File format to use for new tables in .ibd files."));
3505
context("flush-log-at-trx-commit",
3506
po::value<unsigned long>(&srv_flush_log_at_trx_commit)->default_value(1),
3507
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)."));
3508
context("flush-method",
3509
po::value<string>(),
3510
N_("With which method to flush data."));
3511
context("force-recovery",
3512
po::value<long>(&innobase_force_recovery)->default_value(0),
3513
N_("Helps to save your data in case the disk image of the database becomes corrupt."));
3514
context("data-file-path",
3515
po::value<string>(),
3516
N_("Path to individual files and their sizes."));
3517
context("log-group-home-dir",
3518
po::value<string>(),
3519
N_("Path to individual files and their sizes."));
3520
context("log-group-home-dir",
3521
po::value<string>(),
3522
N_("Path to HailDB log files."));
3523
context("log-file-size",
3524
po::value<int64_t>(&haildb_log_file_size)->default_value(20*1024*1024L),
3525
N_("Size of each log file in a log group."));
3526
context("haildb-log-files-in-group",
3527
po::value<int64_t>(&haildb_log_files_in_group)->default_value(2),
3528
N_("Number of log files in the log group. HailDB writes to the files in a circular fashion. Value 3 is recommended here."));
3529
context("lock-wait-timeout",
3530
po::value<unsigned long>(&innobase_lock_wait_timeout)->default_value(5),
3531
N_("Timeout in seconds an HailDB transaction may wait for a lock before being rolled back. Values above 100000000 disable the timeout."));
3532
context("log-buffer-size",
3533
po::value<long>(&innobase_log_buffer_size)->default_value(8*1024*1024L),
3534
N_("The size of the buffer which HailDB uses to write log to the log files on disk."));
3535
context("lru-old-blocks-pct",
3536
po::value<unsigned long>(&innobase_lru_old_blocks_pct)->default_value(37),
3537
N_("Sets the point in the LRU list from where all pages are classified as old (Advanced users)"));
3538
context("lru-block-access-recency",
3539
po::value<unsigned long>(&innobase_lru_block_access_recency)->default_value(0),
3540
N_("Milliseconds between accesses to a block at which it is made young. 0=disabled (Advanced users)"));
3541
context("max-dirty-pages-pct",
3542
po::value<unsigned long>(&srv_max_buf_pool_modified_pct)->default_value(75),
3543
N_("Percentage of dirty pages allowed in bufferpool."));
3544
context("max-purge-lag",
3545
po::value<unsigned long>(&srv_max_purge_lag)->default_value(0),
3546
N_("Desired maximum length of the purge queue (0 = no limit)"));
3547
context("rollback-on-timeout",
3548
po::value<bool>(&innobase_rollback_on_timeout)->default_value(false)->zero_tokens(),
3549
N_("Roll back the complete transaction on lock wait timeout, for 4.x compatibility (disabled by default)"));
3550
context("open-files",
3551
po::value<long>(&innobase_open_files)->default_value(300),
3552
N_("How many files at the maximum HailDB keeps open at the same time."));
3553
context("read-io-threads",
3554
po::value<unsigned long>(&innobase_read_io_threads)->default_value(4),
3555
N_("Number of background read I/O threads in HailDB."));
3556
context("write-io-threads",
3557
po::value<unsigned long>(&innobase_write_io_threads)->default_value(4),
3558
N_("Number of background write I/O threads in HailDB."));
3559
context("disable-print-verbose-log",
3560
N_("Disable if you want to reduce the number of messages written to the log (default: enabled)."));
3561
context("status-file",
3562
po::value<bool>(&innobase_create_status_file)->default_value(false)->zero_tokens(),
3563
N_("Enable SHOW HAILDB STATUS output in the log"));
3564
context("sync-spin-loops",
3565
po::value<unsigned long>(&srv_n_spin_wait_rounds)->default_value(30L),
3566
N_("Count of spin-loop rounds in HailDB mutexes (30 by default)"));
3567
context("use-internal-malloc",
3568
N_("Use HailDB's internal memory allocator instead of the OS memory allocator"));
3571
static drizzle_sys_var* innobase_system_variables[]= {
3572
DRIZZLE_SYSVAR(fast_shutdown),
3573
DRIZZLE_SYSVAR(file_per_table),
3574
DRIZZLE_SYSVAR(file_format),
3575
DRIZZLE_SYSVAR(flush_log_at_trx_commit),
3576
DRIZZLE_SYSVAR(flush_method),
3577
DRIZZLE_SYSVAR(force_recovery),
3578
DRIZZLE_SYSVAR(log_group_home_dir),
3579
DRIZZLE_SYSVAR(data_file_path),
3580
DRIZZLE_SYSVAR(lock_wait_timeout),
3581
DRIZZLE_SYSVAR(log_file_size),
3582
DRIZZLE_SYSVAR(log_files_in_group),
3583
DRIZZLE_SYSVAR(log_buffer_size),
3584
DRIZZLE_SYSVAR(lru_old_blocks_pct),
3585
DRIZZLE_SYSVAR(lru_block_access_recency),
3586
DRIZZLE_SYSVAR(max_dirty_pages_pct),
3587
DRIZZLE_SYSVAR(max_purge_lag),
3588
DRIZZLE_SYSVAR(open_files),
3589
DRIZZLE_SYSVAR(read_io_threads),
3590
DRIZZLE_SYSVAR(rollback_on_timeout),
3591
DRIZZLE_SYSVAR(write_io_threads),
3592
DRIZZLE_SYSVAR(print_verbose_log),
3593
DRIZZLE_SYSVAR(status_file),
3594
DRIZZLE_SYSVAR(sync_spin_loops),
3595
DRIZZLE_SYSVAR(use_sys_malloc),
3599
DRIZZLE_DECLARE_PLUGIN
3605
"Transactional Storage Engine using the HailDB Library",
3607
haildb_init, /* Plugin Init */
3608
innobase_system_variables, /* system variables */
3609
init_options /* config options */
3611
DRIZZLE_DECLARE_PLUGIN_END;