22
22
/*****************************************************************************
24
Copyright (C) 2000, 2009, MySQL AB & Innobase Oy. All Rights Reserved.
25
Copyright (C) 2008, 2009 Google Inc.
24
Copyright (c) 2000, 2009, MySQL AB & Innobase Oy. All Rights Reserved.
25
Copyright (c) 2008, 2009 Google Inc.
27
27
Portions of this file contain modifications contributed and copyrighted by
28
28
Google, Inc. Those modifications are gratefully acknowledged and are described
45
45
*****************************************************************************/
46
46
/***********************************************************************
48
Copyright (C) 1995, 2009, Innobase Oy. All Rights Reserved.
49
Copyright (C) 2009, Percona Inc.
48
Copyright (c) 1995, 2009, Innobase Oy. All Rights Reserved.
49
Copyright (c) 2009, Percona Inc.
51
51
Portions of this file contain modifications contributed and copyrighted
52
52
by Percona Inc.. Those modifications are
101
99
#include "haildb_engine.h"
103
101
#include <drizzled/field.h>
104
#include <drizzled/field/blob.h>
105
#include <drizzled/field/enum.h>
102
#include "drizzled/field/timestamp.h" // needed for UPDATE NOW()
103
#include "drizzled/field/blob.h"
104
#include "drizzled/field/enum.h"
106
105
#include <drizzled/session.h>
106
#include <boost/program_options.hpp>
107
107
#include <drizzled/module/option_map.h>
108
109
#include <drizzled/charset.h>
109
#include <drizzled/current_session.h>
113
111
namespace po= boost::program_options;
114
#include <boost/program_options.hpp>
115
112
#include <boost/algorithm/string.hpp>
117
114
using namespace std;
118
115
using namespace google;
119
116
using namespace drizzled;
121
int read_row_from_haildb(Session *session, unsigned char* buf, ib_crsr_t cursor, ib_tpl_t tuple, Table* table, bool has_hidden_primary_key, uint64_t *hidden_pkey, drizzled::memory::Root **blobroot= NULL);
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);
122
119
static void fill_ib_search_tpl_from_drizzle_key(ib_tpl_t search_tuple,
123
120
const drizzled::KeyInfo *key_info,
124
121
const unsigned char *key_ptr,
168
165
int doCreateTable(Session&,
169
166
Table& table_arg,
170
const drizzled::identifier::Table &identifier,
167
const drizzled::TableIdentifier &identifier,
171
168
drizzled::message::Table& proto);
173
int doDropTable(Session&, const identifier::Table &identifier);
170
int doDropTable(Session&, const TableIdentifier &identifier);
175
172
int doRenameTable(drizzled::Session&,
176
const drizzled::identifier::Table&,
177
const drizzled::identifier::Table&);
173
const drizzled::TableIdentifier&,
174
const drizzled::TableIdentifier&);
179
176
int doGetTableDefinition(Session& session,
180
const identifier::Table &identifier,
177
const TableIdentifier &identifier,
181
178
drizzled::message::Table &table_proto);
183
bool doDoesTableExist(Session&, const identifier::Table &identifier);
180
bool doDoesTableExist(Session&, const TableIdentifier &identifier);
186
void getTableNamesInSchemaFromHailDB(const drizzled::identifier::Schema &schema,
183
void getTableNamesInSchemaFromHailDB(const drizzled::SchemaIdentifier &schema,
187
184
drizzled::plugin::TableNameList *set_of_names,
188
drizzled::identifier::Table::vector *identifiers);
185
drizzled::TableIdentifier::vector *identifiers);
191
188
void doGetTableIdentifiers(drizzled::CachedDirectory &,
192
const drizzled::identifier::Schema &schema,
193
drizzled::identifier::Table::vector &identifiers);
189
const drizzled::SchemaIdentifier &schema,
190
drizzled::TableIdentifier::vector &identifiers);
195
192
/* The following defines can be increased if necessary */
196
193
uint32_t max_supported_keys() const { return 1000; }
434
427
ib_trx_t *transaction= get_trx(session);
429
if (all || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
438
if (ib_trx_state(*transaction) == IB_TRX_NOT_STARTED)
439
err= ib_trx_release(*transaction);
441
err= ib_trx_rollback(*transaction);
431
err= ib_trx_rollback(*transaction);
443
433
if (err != DB_SUCCESS)
444
return ib_err_t_to_drizzle_error(session, err);
434
return ib_err_t_to_drizzle_error(err);
446
436
*transaction= NULL;
450
if (ib_trx_state(*transaction) == IB_TRX_NOT_STARTED)
453
440
err= ib_savepoint_rollback(*transaction, statement_savepoint_name.c_str(),
454
441
statement_savepoint_name.length());
455
442
if (err != DB_SUCCESS)
456
return ib_err_t_to_drizzle_error(session, err);
443
return ib_err_t_to_drizzle_error(err);
832
818
int HailDBCursor::open(const char *name, int, uint32_t)
834
820
const char* haildb_table_name= table_path_to_haildb_name(name);
835
ib_err_t err= ib_table_get_id(haildb_table_name, &table_id);
821
ib_err_t err= ib_cursor_open_table(haildb_table_name, NULL, &cursor);
836
822
bool has_hidden_primary_key= false;
839
825
if (err != DB_SUCCESS)
840
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
842
err= ib_cursor_open_table_using_id(table_id, NULL, &cursor);
843
cursor_is_sec_index= false;
845
if (err != DB_SUCCESS)
846
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
826
return ib_err_t_to_drizzle_error(err);
848
828
err= ib_index_get_id(haildb_table_name, "HIDDEN_PRIMARY", &idx_id);
1518
1498
assert(rollback_err == DB_SUCCESS);
1519
1499
rollback_err= ib_trx_rollback(haildb_schema_transaction);
1520
1500
assert(rollback_err == DB_SUCCESS);
1521
return ib_err_t_to_drizzle_error(&session, err);
1501
return ib_err_t_to_drizzle_error(err);
1524
1504
void HailDBEngine::getTableNamesInSchemaFromHailDB(
1525
const drizzled::identifier::Schema &schema,
1505
const drizzled::SchemaIdentifier &schema,
1526
1506
drizzled::plugin::TableNameList *set_of_names,
1527
drizzled::identifier::Table::vector *identifiers)
1507
drizzled::TableIdentifier::vector *identifiers)
1529
1509
ib_trx_t transaction;
1530
1510
ib_crsr_t cursor;
1796
1776
return("BTREE");
1799
static ib_err_t write_row_to_haildb_tuple(const unsigned char* buf,
1800
Field **fields, ib_tpl_t tuple)
1779
static ib_err_t write_row_to_haildb_tuple(Field **fields, ib_tpl_t tuple)
1803
1782
ib_err_t err= DB_ERROR;
1804
ptrdiff_t row_offset= buf - (*fields)->getTable()->getInsertRecord();
1806
1784
for (Field **field= fields; *field; field++, colnr++)
1808
(**field).move_field_offset(row_offset);
1810
1786
if (! (**field).isWriteSet() && (**field).is_null())
1812
(**field).move_field_offset(-row_offset);
1816
1789
if ((**field).is_null())
1818
1791
err= ib_col_set_value(tuple, colnr, NULL, IB_SQL_NULL);
1819
1792
assert(err == DB_SUCCESS);
1820
(**field).move_field_offset(-row_offset);
1906
1876
tuple= ib_clust_read_tuple_create(cursor);
1908
if (cursor_is_sec_index)
1910
err= ib_cursor_close(cursor);
1911
assert(err == DB_SUCCESS);
1913
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
1915
if (err != DB_SUCCESS)
1916
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
1918
cursor_is_sec_index= false;
1922
ib_cursor_attach_trx(cursor, transaction);
1878
ib_cursor_attach_trx(cursor, transaction);
1925
1880
err= ib_cursor_first(cursor);
1926
if (current_session->getLex()->sql_command == SQLCOM_CREATE_TABLE
1881
if (current_session->lex->sql_command == SQLCOM_CREATE_TABLE
1927
1882
&& err == DB_MISSING_HISTORY)
1929
1884
/* See https://bugs.launchpad.net/drizzle/+bug/556978
1982
write_row_to_haildb_tuple(record, getTable()->getFields(), tuple);
1937
write_row_to_haildb_tuple(getTable()->getFields(), tuple);
1984
1939
if (share->has_hidden_primary_key)
1986
err= ib_tuple_write_u64(tuple, getTable()->getShare()->sizeFields(),
1987
share->hidden_pkey_auto_increment_value.fetch_and_increment());
1941
err= ib_tuple_write_u64(tuple, getTable()->getShare()->fields, share->hidden_pkey_auto_increment_value.fetch_and_increment());
1990
1944
err= ib_cursor_insert_row(cursor, tuple);
2022
1976
ret= HA_ERR_FOUND_DUPP_KEY;
2024
1978
else if (err != DB_SUCCESS)
2025
ret= ib_err_t_to_drizzle_error(getTable()->getSession(), err);
1979
ret= ib_err_t_to_drizzle_error(err);
2027
1981
tuple= ib_tuple_clear(tuple);
2028
1982
ib_tuple_delete(tuple);
2030
1983
err= ib_cursor_reset(cursor);
2035
int HailDBCursor::doUpdateRecord(const unsigned char *old_data,
2036
unsigned char *new_data)
1988
int HailDBCursor::doUpdateRecord(const unsigned char *,
2038
1991
ib_tpl_t update_tuple;
2040
bool created_tuple= false;
2042
1994
update_tuple= ib_clust_read_tuple_create(cursor);
2046
ib_trx_t transaction= *get_trx(getTable()->in_use);
2048
if (cursor_is_sec_index)
2050
err= ib_cursor_close(cursor);
2051
assert(err == DB_SUCCESS);
2053
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2055
if (err != DB_SUCCESS)
2056
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2057
cursor_is_sec_index= false;
2061
ib_cursor_attach_trx(cursor, transaction);
2064
store_key_value_from_haildb(getTable()->key_info + getTable()->getShare()->getPrimaryKey(),
2065
ref, ref_length, old_data);
2067
ib_tpl_t search_tuple= ib_clust_search_tuple_create(cursor);
2069
fill_ib_search_tpl_from_drizzle_key(search_tuple,
2070
getTable()->key_info + 0,
2073
err= ib_cursor_set_lock_mode(cursor, IB_LOCK_X);
2074
assert(err == DB_SUCCESS);
2077
err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
2078
assert(err == DB_SUCCESS);
2080
tuple= ib_clust_read_tuple_create(cursor);
2082
err= ib_cursor_read_row(cursor, tuple);
2083
assert(err == DB_SUCCESS);// FIXME
2085
created_tuple= true;
2088
1996
err= ib_tuple_copy(update_tuple, tuple);
2089
1997
assert(err == DB_SUCCESS);
2091
write_row_to_haildb_tuple(new_data, getTable()->getFields(), update_tuple);
1999
write_row_to_haildb_tuple(getTable()->getFields(), update_tuple);
2093
2001
err= ib_cursor_update_row(cursor, tuple, update_tuple);
2095
2003
ib_tuple_delete(update_tuple);
2099
ib_err_t ib_err= ib_cursor_reset(cursor); //fixme check error
2100
assert(ib_err == DB_SUCCESS);
2101
tuple= ib_tuple_clear(tuple);
2102
ib_tuple_delete(tuple);
2106
2005
advance_cursor= true;
2108
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2007
if (err == DB_SUCCESS)
2009
else if (err == DB_DUPLICATE_KEY)
2010
return HA_ERR_FOUND_DUPP_KEY;
2111
2015
int HailDBCursor::doDeleteRecord(const unsigned char *)
2115
assert(ib_cursor_is_positioned(cursor) == IB_TRUE);
2116
2019
err= ib_cursor_delete_row(cursor);
2020
if (err != DB_SUCCESS)
2118
2023
advance_cursor= true;
2120
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2123
2027
int HailDBCursor::delete_all_rows(void)
2125
2029
/* I *think* ib_truncate is non-transactional....
2126
2030
so only support TRUNCATE and not DELETE FROM t;
2127
(this is what ha_innodb does)
2031
(this is what ha_haildb does)
2129
if (getTable()->in_use->getSqlCommand() != SQLCOM_TRUNCATE)
2033
if (session_sql_command(getTable()->in_use) != SQLCOM_TRUNCATE)
2130
2034
return HA_ERR_WRONG_COMMAND;
2135
2039
ib_trx_t transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
2137
if (cursor_is_sec_index)
2139
err= ib_cursor_close(cursor);
2140
assert(err == DB_SUCCESS);
2142
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2144
if (err != DB_SUCCESS)
2145
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2146
cursor_is_sec_index= false;
2150
ib_cursor_attach_trx(cursor, transaction);
2041
ib_cursor_attach_trx(cursor, transaction);
2153
2043
err= ib_schema_lock_exclusive(transaction);
2154
2044
if (err != DB_SUCCESS)
2201
2091
assert(transaction != NULL);
2203
if (cursor_is_sec_index)
2205
err= ib_cursor_close(cursor);
2206
assert(err == DB_SUCCESS);
2208
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2209
cursor_is_sec_index= false;
2213
ib_cursor_attach_trx(cursor, transaction);
2216
if (err != DB_SUCCESS)
2217
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2093
ib_cursor_attach_trx(cursor, transaction);
2219
2095
err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
2220
2096
assert(err == DB_SUCCESS); // FIXME
2224
2100
err= ib_cursor_first(cursor);
2225
2101
if (err != DB_SUCCESS && err != DB_END_OF_INDEX)
2227
int reset_err= ib_cursor_reset(cursor);
2228
assert(reset_err == DB_SUCCESS);
2229
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2103
previous_error= ib_err_t_to_drizzle_error(err);
2104
err= ib_cursor_reset(cursor);
2105
return previous_error;
2232
2108
advance_cursor= false;
2237
int read_row_from_haildb(Session *session, unsigned char* buf, ib_crsr_t cursor, ib_tpl_t tuple, Table* table, bool has_hidden_primary_key, uint64_t *hidden_pkey, drizzled::memory::Root **blobroot)
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)
2240
2117
ptrdiff_t row_offset= buf - table->getInsertRecord();
2242
2119
err= ib_cursor_read_row(cursor, tuple);
2244
if (err == DB_RECORD_NOT_FOUND)
2121
if (err != DB_SUCCESS) // FIXME
2245
2122
return HA_ERR_END_OF_FILE;
2246
if (err != DB_SUCCESS)
2247
return ib_err_t_to_drizzle_error(session, err);
2202
return previous_error;
2329
2204
if (advance_cursor)
2331
2205
err= ib_cursor_next(cursor);
2332
if (err != DB_SUCCESS)
2333
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2336
2207
tuple= ib_tuple_clear(tuple);
2337
ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2208
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2339
2209
share->has_hidden_primary_key,
2340
2210
&hidden_autoinc_pkey_position);
2514
2380
if (flag & HA_STATUS_AUTO)
2515
2381
stats.auto_increment_value= 1;
2517
if (flag & HA_STATUS_ERRKEY) {
2518
const char *err_table_name;
2519
const char *err_index_name;
2521
ib_trx_t transaction= *get_trx(getTable()->in_use);
2523
err= ib_get_duplicate_key(transaction, &err_table_name, &err_index_name);
2527
for (unsigned int i = 0; i < getTable()->getShare()->keys; i++)
2529
if (strcmp(err_index_name, getTable()->key_info[i].name) == 0)
2538
if (flag & HA_STATUS_CONST)
2540
for (unsigned int i = 0; i < getTable()->getShare()->sizeKeys(); i++)
2542
const char* index_name= getTable()->key_info[i].name;
2545
ha_rows rec_per_key;
2547
err= ib_get_index_stat_n_diff_key_vals(cursor, index_name,
2550
if (err != DB_SUCCESS)
2551
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2553
for (unsigned int j=0; j < getTable()->key_info[i].key_parts; j++)
2555
if (n_diff[j+1] == 0)
2556
rec_per_key= stats.records;
2558
rec_per_key= stats.records / n_diff[j+1];
2560
/* We import this heuristic from ha_innodb, which says
2561
that MySQL favours table scans too much over index searches,
2562
so we pretend our index selectivity is 2 times better. */
2564
rec_per_key= rec_per_key / 2;
2566
if (rec_per_key == 0)
2569
getTable()->key_info[i].rec_per_key[j]=
2570
rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
2571
(ulong) rec_per_key;
2581
2385
int HailDBCursor::doStartIndexScan(uint32_t keynr, bool)
2584
2387
ib_trx_t transaction= *get_trx(getTable()->in_use);
2586
2389
active_index= keynr;
2391
ib_cursor_attach_trx(cursor, transaction);
2588
2393
if (active_index == 0 && ! share->has_hidden_primary_key)
2590
if (cursor_is_sec_index)
2592
err= ib_cursor_close(cursor);
2593
assert(err == DB_SUCCESS);
2595
err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2597
if (err != DB_SUCCESS)
2598
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2603
ib_cursor_attach_trx(cursor, transaction);
2606
cursor_is_sec_index= false;
2607
2395
tuple= ib_clust_read_tuple_create(cursor);
2611
2400
ib_id_t index_id;
2612
2401
err= ib_index_get_id(table_path_to_haildb_name(getShare()->getPath()),
2613
2402
getShare()->getKeyInfo(keynr).name,
2615
2404
if (err != DB_SUCCESS)
2616
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2618
2407
err= ib_cursor_close(cursor);
2619
2408
assert(err == DB_SUCCESS);
2621
2409
err= ib_cursor_open_index_using_id(index_id, transaction, &cursor);
2623
2411
if (err != DB_SUCCESS)
2624
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2626
cursor_is_sec_index= true;
2628
2414
tuple= ib_clust_read_tuple_create(cursor);
2629
2415
ib_cursor_set_cluster_access(cursor);
2632
err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
2418
ib_err_t err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
2633
2419
assert(err == DB_SUCCESS);
2635
2421
advance_cursor= false;
2775
2561
if (err != DB_SUCCESS)
2777
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2563
return ib_err_t_to_drizzle_error(err);
2780
2566
tuple= ib_tuple_clear(tuple);
2781
ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2567
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2783
2568
share->has_hidden_primary_key,
2784
2569
&hidden_autoinc_pkey_position,
2785
2570
(allocate_blobs)? &blobroot : NULL);
2906
2681
if (err == DB_END_OF_INDEX)
2907
2682
return HA_ERR_END_OF_FILE;
2909
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2913
2688
tuple= ib_tuple_clear(tuple);
2914
ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2689
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2916
2690
share->has_hidden_primary_key,
2917
2691
&hidden_autoinc_pkey_position);
2930
2704
err= ib_cursor_first(cursor);
2931
2705
if (err != DB_SUCCESS)
2932
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2706
return ib_err_t_to_drizzle_error(err);
2934
2708
tuple= ib_tuple_clear(tuple);
2935
ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2709
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2937
2710
share->has_hidden_primary_key,
2938
2711
&hidden_autoinc_pkey_position);
2951
2724
err= ib_cursor_last(cursor);
2952
2725
if (err != DB_SUCCESS)
2953
return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2726
return ib_err_t_to_drizzle_error(err);
2955
2728
tuple= ib_tuple_clear(tuple);
2956
ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2729
ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2958
2730
share->has_hidden_primary_key,
2959
2731
&hidden_autoinc_pkey_position);
2960
2732
advance_cursor= true;
3139
extern "C" int haildb_errmsg_callback(ib_msg_stream_t, const char *fmt, ...);
3142
extern bool volatile shutdown_in_progress;
3145
extern "C" int haildb_errmsg_callback(ib_msg_stream_t, const char *fmt, ...)
3149
va_start(args, fmt);
3150
if (not shutdown_in_progress)
3152
r= plugin::ErrorMessage::vprintf(error::WARN, fmt, args);
3156
vfprintf(stderr, fmt, args);
3163
2912
static int haildb_init(drizzled::module::Context &context)