~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/haildb/haildb_engine.cc

modified transaction docs

Show diffs side-by-side

added added

removed removed

Lines of Context:
21
21
 
22
22
/*****************************************************************************
23
23
 
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.
26
26
 
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
/***********************************************************************
47
47
 
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.
50
50
 
51
51
Portions of this file contain modifications contributed and copyrighted
52
52
by Percona Inc.. Those modifications are
71
71
***********************************************************************/
72
72
 
73
73
 
74
 
#include <config.h>
 
74
#include "config.h"
75
75
#include <drizzled/table.h>
76
76
#include <drizzled/error.h>
77
 
#include <drizzled/internal/my_pthread.h>
 
77
#include "drizzled/internal/my_pthread.h"
78
78
#include <drizzled/plugin/transactional_storage_engine.h>
79
79
#include <drizzled/plugin/error_message.h>
80
80
 
88
88
#include <map>
89
89
#include <fstream>
90
90
#include <drizzled/message/table.pb.h>
91
 
#include <drizzled/internal/m_string.h>
 
91
#include "drizzled/internal/m_string.h"
92
92
 
93
 
#include <drizzled/global_charset_info.h>
 
93
#include "drizzled/global_charset_info.h"
94
94
 
95
95
#include "haildb_datadict_dump_func.h"
96
96
#include "config_table_function.h"
101
101
#include "haildb_engine.h"
102
102
 
103
103
#include <drizzled/field.h>
104
 
#include <drizzled/field/blob.h>
105
 
#include <drizzled/field/enum.h>
 
104
#include "drizzled/field/timestamp.h" // needed for UPDATE NOW()
 
105
#include "drizzled/field/blob.h"
 
106
#include "drizzled/field/enum.h"
106
107
#include <drizzled/session.h>
 
108
#include <boost/program_options.hpp>
107
109
#include <drizzled/module/option_map.h>
 
110
#include <iostream>
108
111
#include <drizzled/charset.h>
109
 
#include <drizzled/current_session.h>
110
 
 
111
 
#include <iostream>
112
112
 
113
113
namespace po= boost::program_options;
114
 
#include <boost/program_options.hpp>
115
114
#include <boost/algorithm/string.hpp>
116
115
 
117
116
using namespace std;
118
117
using namespace google;
119
118
using namespace drizzled;
120
119
 
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);
 
120
int read_row_from_haildb(unsigned char* buf, ib_crsr_t cursor, ib_tpl_t tuple, Table* table, bool has_hidden_primary_key, uint64_t *hidden_pkey, drizzled::memory::Root **blobroot= NULL);
122
121
static void fill_ib_search_tpl_from_drizzle_key(ib_tpl_t search_tuple,
123
122
                                                const drizzled::KeyInfo *key_info,
124
123
                                                const unsigned char *key_ptr,
167
166
 
168
167
  int doCreateTable(Session&,
169
168
                    Table& table_arg,
170
 
                    const drizzled::identifier::Table &identifier,
 
169
                    const drizzled::TableIdentifier &identifier,
171
170
                    drizzled::message::Table& proto);
172
171
 
173
 
  int doDropTable(Session&, const identifier::Table &identifier);
 
172
  int doDropTable(Session&, const TableIdentifier &identifier);
174
173
 
175
174
  int doRenameTable(drizzled::Session&,
176
 
                    const drizzled::identifier::Table&,
177
 
                    const drizzled::identifier::Table&);
 
175
                    const drizzled::TableIdentifier&,
 
176
                    const drizzled::TableIdentifier&);
178
177
 
179
178
  int doGetTableDefinition(Session& session,
180
 
                           const identifier::Table &identifier,
 
179
                           const TableIdentifier &identifier,
181
180
                           drizzled::message::Table &table_proto);
182
181
 
183
 
  bool doDoesTableExist(Session&, const identifier::Table &identifier);
 
182
  bool doDoesTableExist(Session&, const TableIdentifier &identifier);
184
183
 
185
184
private:
186
 
  void getTableNamesInSchemaFromHailDB(const drizzled::identifier::Schema &schema,
 
185
  void getTableNamesInSchemaFromHailDB(const drizzled::SchemaIdentifier &schema,
187
186
                                       drizzled::plugin::TableNameList *set_of_names,
188
 
                                       drizzled::identifier::Table::vector *identifiers);
 
187
                                       drizzled::TableIdentifier::vector *identifiers);
189
188
 
190
189
public:
191
190
  void doGetTableIdentifiers(drizzled::CachedDirectory &,
192
 
                             const drizzled::identifier::Schema &schema,
193
 
                             drizzled::identifier::Table::vector &identifiers);
 
191
                             const drizzled::SchemaIdentifier &schema,
 
192
                             drizzled::TableIdentifier::vector &identifiers);
194
193
 
195
194
  /* The following defines can be increased if necessary */
196
195
  uint32_t max_supported_keys()          const { return 1000; }
241
240
/* This is a superset of the map from innobase plugin.
242
241
   Unlike innobase plugin we don't act on errors here, we just
243
242
   map error codes. */
244
 
static int ib_err_t_to_drizzle_error(Session* session, ib_err_t err)
 
243
static int ib_err_t_to_drizzle_error(ib_err_t err)
245
244
{
246
245
  switch (err)
247
246
  {
271
270
    return HA_ERR_NO_ACTIVE_RECORD;
272
271
 
273
272
  case DB_DEADLOCK:
274
 
    /* HailDB will roll back a transaction itself due to DB_DEADLOCK.
275
 
       This means we have to tell Drizzle about it */
276
 
    session->markTransactionForRollback(true);
277
273
    return HA_ERR_LOCK_DEADLOCK;
278
274
 
279
275
  case DB_LOCK_WAIT_TIMEOUT:
280
 
    session->markTransactionForRollback(false);
281
276
    return HA_ERR_LOCK_WAIT_TIMEOUT;
282
277
 
283
278
  case DB_NO_REFERENCED_ROW:
356
351
  (void)options;
357
352
 
358
353
  transaction= get_trx(session);
359
 
  isolation_level= tx_isolation_to_ib_trx_level(session->getTxIsolation());
 
354
  isolation_level= tx_isolation_to_ib_trx_level((enum_tx_isolation)session_tx_isolation(session));
360
355
  *transaction= ib_trx_begin(isolation_level);
361
356
 
362
 
  return *transaction == NULL;
 
357
  return 0;
363
358
}
364
359
 
365
360
void HailDBEngine::doStartStatement(Session *session)
393
388
  err= ib_savepoint_rollback(*transaction, savepoint.getName().c_str(),
394
389
                             savepoint.getName().length());
395
390
 
396
 
  return ib_err_t_to_drizzle_error(session, err);
 
391
  return ib_err_t_to_drizzle_error(err);
397
392
}
398
393
 
399
394
int HailDBEngine::doReleaseSavepoint(Session* session,
405
400
  err= ib_savepoint_release(*transaction, savepoint.getName().c_str(),
406
401
                            savepoint.getName().length());
407
402
  if (err != DB_SUCCESS)
408
 
    return ib_err_t_to_drizzle_error(session, err);
 
403
    return ib_err_t_to_drizzle_error(err);
409
404
 
410
405
  return 0;
411
406
}
415
410
  ib_err_t err;
416
411
  ib_trx_t *transaction= get_trx(session);
417
412
 
418
 
  if (all)
 
413
  if (all || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
419
414
  {
420
415
    err= ib_trx_commit(*transaction);
421
416
 
422
417
    if (err != DB_SUCCESS)
423
 
      return ib_err_t_to_drizzle_error(session, err);
 
418
      return ib_err_t_to_drizzle_error(err);
424
419
 
425
420
    *transaction= NULL;
426
421
  }
433
428
  ib_err_t err;
434
429
  ib_trx_t *transaction= get_trx(session);
435
430
 
436
 
  if (all)
 
431
  if (all || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
437
432
  {
438
 
    if (ib_trx_state(*transaction) == IB_TRX_NOT_STARTED)
439
 
      err= ib_trx_release(*transaction);
440
 
    else
441
 
      err= ib_trx_rollback(*transaction);
 
433
    err= ib_trx_rollback(*transaction);
442
434
 
443
435
    if (err != DB_SUCCESS)
444
 
      return ib_err_t_to_drizzle_error(session, err);
 
436
      return ib_err_t_to_drizzle_error(err);
445
437
 
446
438
    *transaction= NULL;
447
439
  }
448
440
  else
449
441
  {
450
 
    if (ib_trx_state(*transaction) == IB_TRX_NOT_STARTED)
451
 
      return 0;
452
 
 
453
442
    err= ib_savepoint_rollback(*transaction, statement_savepoint_name.c_str(),
454
443
                               statement_savepoint_name.length());
455
444
    if (err != DB_SUCCESS)
456
 
      return ib_err_t_to_drizzle_error(session, err);
 
445
      return ib_err_t_to_drizzle_error(err);
457
446
  }
458
447
 
459
448
  return 0;
497
486
  else
498
487
  {
499
488
    assert (err == DB_SUCCESS);
500
 
    err= ib_tuple_read_u64(tuple, getTable()->getShare()->sizeFields(), &nr);
 
489
    err= ib_tuple_read_u64(tuple, getTable()->getShare()->fields, &nr);
501
490
    nr++;
502
491
  }
503
492
  ib_tuple_delete(tuple);
538
527
  doEndIndexScan();
539
528
  (void) extra(HA_EXTRA_NO_KEYREAD);
540
529
 
541
 
  if (getTable()->getShare()->getTableMessage()->options().auto_increment_value() > nr)
542
 
    nr= getTable()->getShare()->getTableMessage()->options().auto_increment_value();
 
530
  if (getTable()->getShare()->getTableProto()->options().auto_increment_value() > nr)
 
531
    nr= getTable()->getShare()->getTableProto()->options().auto_increment_value();
543
532
 
544
533
  return nr;
545
534
}
652
641
 
653
642
  /* the below is adapted from ha_innodb.cc */
654
643
 
655
 
  const uint32_t sql_command = session->getSqlCommand();
 
644
  const uint32_t sql_command = session_sql_command(session);
656
645
 
657
646
  if (sql_command == SQLCOM_DROP_TABLE) {
658
647
 
683
672
    unexpected if an obsolete consistent read view would be
684
673
    used. */
685
674
 
686
 
    enum_tx_isolation isolation_level= session->getTxIsolation();
 
675
    enum_tx_isolation isolation_level= session_tx_isolation(session);
687
676
 
688
677
    if (isolation_level != ISO_SERIALIZABLE
689
678
        && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
726
715
 
727
716
    if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
728
717
         && lock_type <= TL_WRITE)
729
 
        && ! session->doing_tablespace_operation()
 
718
        && !session_tablespace_op(session)
730
719
        && sql_command != SQLCOM_TRUNCATE
731
720
        && sql_command != SQLCOM_CREATE_TABLE) {
732
721
 
803
792
  return &name[l];
804
793
}
805
794
 
806
 
static void TableIdentifier_to_haildb_name(const identifier::Table &identifier, std::string *str)
 
795
static void TableIdentifier_to_haildb_name(const TableIdentifier &identifier, std::string *str)
807
796
{
808
797
  str->assign(table_path_to_haildb_name(identifier.getPath().c_str()));
809
798
}
832
821
int HailDBCursor::open(const char *name, int, uint32_t)
833
822
{
834
823
  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);
 
824
  ib_err_t err= ib_cursor_open_table(haildb_table_name, NULL, &cursor);
836
825
  bool has_hidden_primary_key= false;
837
826
  ib_id_t idx_id;
838
827
 
839
828
  if (err != DB_SUCCESS)
840
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
841
 
 
842
 
  err= ib_cursor_open_table_using_id(table_id, NULL, &cursor);
843
 
  cursor_is_sec_index= false;
844
 
 
845
 
  if (err != DB_SUCCESS)
846
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
829
    return ib_err_t_to_drizzle_error(err);
847
830
 
848
831
  err= ib_index_get_id(haildb_table_name, "HIDDEN_PRIMARY", &idx_id);
849
832
 
874
857
{
875
858
  ib_err_t err= ib_cursor_close(cursor);
876
859
  if (err != DB_SUCCESS)
877
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
860
    return ib_err_t_to_drizzle_error(err);
878
861
 
879
862
  free_share();
880
863
 
907
890
{
908
891
  ib_col_attr_t column_attr= IB_COL_NONE;
909
892
 
910
 
  if (field.has_constraints() && field.constraints().is_notnull())
 
893
  if (field.has_constraints() && ! field.constraints().is_nullable())
911
894
    column_attr= IB_COL_NOT_NULL;
912
895
 
913
896
  switch (field.type())
938
921
    *err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
939
922
                                  column_attr, 0, 4);
940
923
    break;
941
 
  case message::Table::Field::EPOCH:
 
924
  case message::Table::Field::TIMESTAMP:
942
925
    *err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
943
926
                                  column_attr, 0, 8);
944
927
    break;
1038
1021
 
1039
1022
int HailDBEngine::doCreateTable(Session &session,
1040
1023
                                        Table& table_obj,
1041
 
                                        const drizzled::identifier::Table &identifier,
 
1024
                                        const drizzled::TableIdentifier &identifier,
1042
1025
                                        drizzled::message::Table& table_message)
1043
1026
{
1044
1027
  ib_tbl_sch_t haildb_table_schema= NULL;
1082
1065
                        ER_CANT_CREATE_TABLE,
1083
1066
                        _("Cannot create table %s. HailDB Error %d (%s)\n"),
1084
1067
                        haildb_table_name.c_str(), haildb_err, ib_strerror(haildb_err));
1085
 
    return ib_err_t_to_drizzle_error(&session, haildb_err);
 
1068
    return ib_err_t_to_drizzle_error(haildb_err);
1086
1069
  }
1087
1070
 
1088
1071
  for (int colnr= 0; colnr < table_message.field_size() ; colnr++)
1103
1086
                            " HailDB Error %d (%s)\n"),
1104
1087
                          field.name().c_str(), haildb_table_name.c_str(),
1105
1088
                          haildb_err, ib_strerror(haildb_err));
1106
 
      return ib_err_t_to_drizzle_error(&session, haildb_err);
 
1089
      return ib_err_t_to_drizzle_error(haildb_err);
1107
1090
    }
1108
1091
    if (field_err != 0)
1109
1092
      return field_err;
1251
1234
                        _("Cannot create table %s. HailDB Error %d (%s)\n"),
1252
1235
                        haildb_table_name.c_str(),
1253
1236
                        haildb_err, ib_strerror(haildb_err));
1254
 
    return ib_err_t_to_drizzle_error(&session, haildb_err);
 
1237
    return ib_err_t_to_drizzle_error(haildb_err);
1255
1238
  }
1256
1239
 
1257
1240
  return 0;
1294
1277
}
1295
1278
 
1296
1279
int HailDBEngine::doDropTable(Session &session,
1297
 
                                      const identifier::Table &identifier)
 
1280
                                      const TableIdentifier &identifier)
1298
1281
{
1299
1282
  ib_trx_t haildb_schema_transaction;
1300
1283
  ib_err_t haildb_err;
1376
1359
  return 0;
1377
1360
}
1378
1361
 
1379
 
static ib_err_t rename_table_message(ib_trx_t transaction, const identifier::Table &from_identifier, const identifier::Table &to_identifier)
 
1362
static ib_err_t rename_table_message(ib_trx_t transaction, const TableIdentifier &from_identifier, const TableIdentifier &to_identifier)
1380
1363
{
1381
1364
  ib_crsr_t cursor;
1382
1365
  ib_tpl_t search_tuple;
1467
1450
}
1468
1451
 
1469
1452
int HailDBEngine::doRenameTable(drizzled::Session &session,
1470
 
                                        const drizzled::identifier::Table &from,
1471
 
                                        const drizzled::identifier::Table &to)
 
1453
                                        const drizzled::TableIdentifier &from,
 
1454
                                        const drizzled::TableIdentifier &to)
1472
1455
{
1473
1456
  ib_trx_t haildb_schema_transaction;
1474
1457
  ib_err_t err;
1518
1501
  assert(rollback_err == DB_SUCCESS);
1519
1502
  rollback_err= ib_trx_rollback(haildb_schema_transaction);
1520
1503
  assert(rollback_err == DB_SUCCESS);
1521
 
  return ib_err_t_to_drizzle_error(&session, err);
 
1504
  return ib_err_t_to_drizzle_error(err);
1522
1505
}
1523
1506
 
1524
1507
void HailDBEngine::getTableNamesInSchemaFromHailDB(
1525
 
                                 const drizzled::identifier::Schema &schema,
 
1508
                                 const drizzled::SchemaIdentifier &schema,
1526
1509
                                 drizzled::plugin::TableNameList *set_of_names,
1527
 
                                 drizzled::identifier::Table::vector *identifiers)
 
1510
                                 drizzled::TableIdentifier::vector *identifiers)
1528
1511
{
1529
1512
  ib_trx_t   transaction;
1530
1513
  ib_crsr_t  cursor;
1554
1537
    {
1555
1538
      BOOST_FOREACH(std::string table_name, haildb_system_table_names)
1556
1539
      {
1557
 
        identifiers->push_back(identifier::Table(schema.getSchemaName(),
 
1540
        identifiers->push_back(TableIdentifier(schema.getSchemaName(),
1558
1541
                                               table_name));
1559
1542
      }
1560
1543
    }
1597
1580
      if (set_of_names)
1598
1581
        set_of_names->insert(just_table_name);
1599
1582
      if (identifiers)
1600
 
        identifiers->push_back(identifier::Table(schema.getSchemaName(), just_table_name));
 
1583
        identifiers->push_back(TableIdentifier(schema.getSchemaName(), just_table_name));
1601
1584
    }
1602
1585
 
1603
1586
 
1616
1599
}
1617
1600
 
1618
1601
void HailDBEngine::doGetTableIdentifiers(drizzled::CachedDirectory &,
1619
 
                                                 const drizzled::identifier::Schema &schema,
1620
 
                                                 drizzled::identifier::Table::vector &identifiers)
 
1602
                                                 const drizzled::SchemaIdentifier &schema,
 
1603
                                                 drizzled::TableIdentifier::vector &identifiers)
1621
1604
{
1622
1605
  getTableNamesInSchemaFromHailDB(schema, NULL, &identifiers);
1623
1606
}
1742
1725
}
1743
1726
 
1744
1727
int HailDBEngine::doGetTableDefinition(Session &session,
1745
 
                                               const identifier::Table &identifier,
 
1728
                                               const TableIdentifier &identifier,
1746
1729
                                               drizzled::message::Table &table)
1747
1730
{
1748
1731
  ib_crsr_t haildb_cursor= NULL;
1771
1754
}
1772
1755
 
1773
1756
bool HailDBEngine::doDoesTableExist(Session &,
1774
 
                                    const identifier::Table& identifier)
 
1757
                                    const TableIdentifier& identifier)
1775
1758
{
1776
1759
  ib_crsr_t haildb_cursor;
1777
1760
  string haildb_table_name;
1829
1812
      */
1830
1813
      String str;
1831
1814
      (**field).setReadSet();
1832
 
      (**field).val_str_internal(&str);
 
1815
      (**field).val_str(&str);
1833
1816
      err= ib_col_set_value(tuple, colnr, str.ptr(), str.length());
1834
1817
    }
1835
1818
    else if ((**field).type() == DRIZZLE_TYPE_ENUM)
1905
1888
 
1906
1889
  tuple= ib_clust_read_tuple_create(cursor);
1907
1890
 
1908
 
  if (cursor_is_sec_index)
1909
 
  {
1910
 
    err= ib_cursor_close(cursor);
1911
 
    assert(err == DB_SUCCESS);
1912
 
 
1913
 
    err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
1914
 
 
1915
 
    if (err != DB_SUCCESS)
1916
 
      return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
1917
 
 
1918
 
    cursor_is_sec_index= false;
1919
 
  }
1920
 
  else
1921
 
  {
1922
 
    ib_cursor_attach_trx(cursor, transaction);
1923
 
  }
 
1891
  ib_cursor_attach_trx(cursor, transaction);
1924
1892
 
1925
1893
  err= ib_cursor_first(cursor);
1926
 
  if (current_session->getLex()->sql_command == SQLCOM_CREATE_TABLE
 
1894
  if (current_session->lex->sql_command == SQLCOM_CREATE_TABLE
1927
1895
      && err == DB_MISSING_HISTORY)
1928
1896
  {
1929
1897
    /* See https://bugs.launchpad.net/drizzle/+bug/556978
1983
1951
 
1984
1952
  if (share->has_hidden_primary_key)
1985
1953
  {
1986
 
    err= ib_tuple_write_u64(tuple, getTable()->getShare()->sizeFields(),
1987
 
                            share->hidden_pkey_auto_increment_value.fetch_and_increment());
 
1954
    err= ib_tuple_write_u64(tuple, getTable()->getShare()->fields, share->hidden_pkey_auto_increment_value.fetch_and_increment());
1988
1955
  }
1989
1956
 
1990
1957
  err= ib_cursor_insert_row(cursor, tuple);
2022
1989
      ret= HA_ERR_FOUND_DUPP_KEY;
2023
1990
  }
2024
1991
  else if (err != DB_SUCCESS)
2025
 
    ret= ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
1992
    ret= ib_err_t_to_drizzle_error(err);
2026
1993
 
2027
1994
  tuple= ib_tuple_clear(tuple);
2028
1995
  ib_tuple_delete(tuple);
2044
2011
  if (tuple == NULL)
2045
2012
  {
2046
2013
    ib_trx_t transaction= *get_trx(getTable()->in_use);
2047
 
 
2048
 
    if (cursor_is_sec_index)
2049
 
    {
2050
 
      err= ib_cursor_close(cursor);
2051
 
      assert(err == DB_SUCCESS);
2052
 
 
2053
 
      err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2054
 
 
2055
 
      if (err != DB_SUCCESS)
2056
 
        return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2057
 
      cursor_is_sec_index= false;
2058
 
    }
2059
 
    else
2060
 
    {
2061
 
      ib_cursor_attach_trx(cursor, transaction);
2062
 
    }
 
2014
    ib_cursor_attach_trx(cursor, transaction);
2063
2015
 
2064
2016
    store_key_value_from_haildb(getTable()->key_info + getTable()->getShare()->getPrimaryKey(),
2065
2017
                                  ref, ref_length, old_data);
2105
2057
 
2106
2058
  advance_cursor= true;
2107
2059
 
2108
 
  return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2060
  if (err == DB_SUCCESS)
 
2061
    return 0;
 
2062
  else if (err == DB_DUPLICATE_KEY)
 
2063
    return HA_ERR_FOUND_DUPP_KEY;
 
2064
  else
 
2065
    return -1;
2109
2066
}
2110
2067
 
2111
2068
int HailDBCursor::doDeleteRecord(const unsigned char *)
2112
2069
{
2113
2070
  ib_err_t err;
2114
2071
 
2115
 
  assert(ib_cursor_is_positioned(cursor) == IB_TRUE);
2116
2072
  err= ib_cursor_delete_row(cursor);
 
2073
  if (err != DB_SUCCESS)
 
2074
    return -1; // FIXME
2117
2075
 
2118
2076
  advance_cursor= true;
2119
 
 
2120
 
  return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2077
  return 0;
2121
2078
}
2122
2079
 
2123
2080
int HailDBCursor::delete_all_rows(void)
2124
2081
{
2125
2082
  /* I *think* ib_truncate is non-transactional....
2126
2083
     so only support TRUNCATE and not DELETE FROM t;
2127
 
     (this is what ha_innodb does)
 
2084
     (this is what ha_haildb does)
2128
2085
  */
2129
 
  if (getTable()->in_use->getSqlCommand() != SQLCOM_TRUNCATE)
 
2086
  if (session_sql_command(getTable()->in_use) != SQLCOM_TRUNCATE)
2130
2087
    return HA_ERR_WRONG_COMMAND;
2131
2088
 
2132
2089
  ib_id_t id;
2134
2091
 
2135
2092
  ib_trx_t transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
2136
2093
 
2137
 
  if (cursor_is_sec_index)
2138
 
  {
2139
 
    err= ib_cursor_close(cursor);
2140
 
    assert(err == DB_SUCCESS);
2141
 
 
2142
 
    err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2143
 
 
2144
 
    if (err != DB_SUCCESS)
2145
 
      return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2146
 
    cursor_is_sec_index= false;
2147
 
  }
2148
 
  else
2149
 
  {
2150
 
    ib_cursor_attach_trx(cursor, transaction);
2151
 
  }
 
2094
  ib_cursor_attach_trx(cursor, transaction);
2152
2095
 
2153
2096
  err= ib_schema_lock_exclusive(transaction);
2154
2097
  if (err != DB_SUCCESS)
2184
2127
  ib_schema_unlock(transaction);
2185
2128
  ib_err_t rollback_err= ib_trx_rollback(transaction);
2186
2129
  assert(rollback_err == DB_SUCCESS);
2187
 
  return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2130
  return err;
2188
2131
}
2189
2132
 
2190
2133
int HailDBCursor::doStartTableScan(bool)
2191
2134
{
2192
 
  ib_err_t err= DB_SUCCESS;
 
2135
  ib_err_t err;
2193
2136
  ib_trx_t transaction;
2194
2137
 
2195
2138
  if (in_table_scan)
2200
2143
 
2201
2144
  assert(transaction != NULL);
2202
2145
 
2203
 
  if (cursor_is_sec_index)
2204
 
  {
2205
 
    err= ib_cursor_close(cursor);
2206
 
    assert(err == DB_SUCCESS);
2207
 
 
2208
 
    err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2209
 
    cursor_is_sec_index= false;
2210
 
  }
2211
 
  else
2212
 
  {
2213
 
    ib_cursor_attach_trx(cursor, transaction);
2214
 
  }
2215
 
 
2216
 
  if (err != DB_SUCCESS)
2217
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2146
  ib_cursor_attach_trx(cursor, transaction);
2218
2147
 
2219
2148
  err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
2220
2149
  assert(err == DB_SUCCESS); // FIXME
2224
2153
  err= ib_cursor_first(cursor);
2225
2154
  if (err != DB_SUCCESS && err != DB_END_OF_INDEX)
2226
2155
  {
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);
 
2156
    previous_error= ib_err_t_to_drizzle_error(err);
 
2157
    err= ib_cursor_reset(cursor);
 
2158
    return previous_error;
2230
2159
  }
2231
2160
 
2232
2161
  advance_cursor= false;
2233
2162
 
 
2163
  previous_error= 0;
2234
2164
  return(0);
2235
2165
}
2236
2166
 
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)
 
2167
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)
2238
2168
{
2239
2169
  ib_err_t err;
2240
2170
  ptrdiff_t row_offset= buf - table->getInsertRecord();
2241
2171
 
2242
2172
  err= ib_cursor_read_row(cursor, tuple);
2243
2173
 
2244
 
  if (err == DB_RECORD_NOT_FOUND)
 
2174
  if (err != DB_SUCCESS) // FIXME
2245
2175
    return HA_ERR_END_OF_FILE;
2246
 
  if (err != DB_SUCCESS)
2247
 
    return ib_err_t_to_drizzle_error(session, err);
2248
2176
 
2249
2177
  int colnr= 0;
2250
2178
 
2255
2183
  for (Field **field= table->getFields() ; *field ; field++, colnr++)
2256
2184
  {
2257
2185
    if (! (**field).isReadSet())
2258
 
      (**field).setReadSet(); /* Fucking broken API screws us royally. */
 
2186
      continue;
2259
2187
 
2260
2188
    (**field).move_field_offset(row_offset);
2261
2189
 
2309
2237
 
2310
2238
    (**field).move_field_offset(-row_offset);
2311
2239
 
2312
 
    if (err != DB_SUCCESS)
2313
 
      return ib_err_t_to_drizzle_error(session, err);
2314
2240
  }
2315
2241
 
2316
2242
  if (has_hidden_primary_key)
2318
2244
    err= ib_tuple_read_u64(tuple, colnr, hidden_pkey);
2319
2245
  }
2320
2246
 
2321
 
  return ib_err_t_to_drizzle_error(session, err);
 
2247
  return 0;
2322
2248
}
2323
2249
 
2324
2250
int HailDBCursor::rnd_next(unsigned char *buf)
2326
2252
  ib_err_t err;
2327
2253
  int ret;
2328
2254
 
 
2255
  if (previous_error)
 
2256
    return previous_error;
 
2257
 
2329
2258
  if (advance_cursor)
2330
 
  {
2331
2259
    err= ib_cursor_next(cursor);
2332
 
    if (err != DB_SUCCESS)
2333
 
      return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2334
 
  }
2335
2260
 
2336
2261
  tuple= ib_tuple_clear(tuple);
2337
 
  ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2338
 
                            getTable(),
 
2262
  ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2339
2263
                            share->has_hidden_primary_key,
2340
2264
                            &hidden_autoinc_pkey_position);
2341
2265
 
2352
2276
  err= ib_cursor_reset(cursor);
2353
2277
  assert(err == DB_SUCCESS);
2354
2278
  in_table_scan= false;
2355
 
  return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2279
  previous_error= 0;
 
2280
  return 0;
2356
2281
}
2357
2282
 
2358
2283
int HailDBCursor::rnd_pos(unsigned char *buf, unsigned char *pos)
2366
2291
  {
2367
2292
    err= ib_col_set_value(search_tuple, 0,
2368
2293
                          ((uint64_t*)(pos)), sizeof(uint64_t));
2369
 
    if (err != DB_SUCCESS)
2370
 
      return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2371
2294
  }
2372
2295
  else
2373
2296
  {
2383
2306
  }
2384
2307
 
2385
2308
  err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
2386
 
  if (err != DB_SUCCESS)
2387
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2309
  assert(err == DB_SUCCESS);
2388
2310
 
2389
2311
  assert(res==0);
2390
2312
  if (res != 0)
2395
2317
  tuple= ib_tuple_clear(tuple);
2396
2318
 
2397
2319
  if (ret == 0)
2398
 
    ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2399
 
                              getTable(),
 
2320
    ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2400
2321
                              share->has_hidden_primary_key,
2401
2322
                              &hidden_autoinc_pkey_position);
2402
2323
 
2434
2355
      }
2435
2356
 
2436
2357
      String str;
2437
 
      field->val_str_internal(&str);
 
2358
      field->val_str(&str);
2438
2359
 
2439
2360
      *ref++= (char)(str.length() & 0x000000ff);
2440
2361
      *ref++= (char)((str.length()>>8) & 0x000000ff);
2522
2443
 
2523
2444
    err= ib_get_duplicate_key(transaction, &err_table_name, &err_index_name);
2524
2445
 
2525
 
    errkey= UINT32_MAX;
 
2446
    errkey= -1;
2526
2447
 
2527
2448
    for (unsigned int i = 0; i < getTable()->getShare()->keys; i++)
2528
2449
    {
2535
2456
 
2536
2457
  }
2537
2458
 
2538
 
  if (flag & HA_STATUS_CONST)
2539
 
  {
2540
 
    for (unsigned int i = 0; i < getTable()->getShare()->sizeKeys(); i++)
2541
 
    {
2542
 
      const char* index_name= getTable()->key_info[i].name;
2543
 
      uint64_t ncols;
2544
 
      int64_t *n_diff;
2545
 
      ha_rows rec_per_key;
2546
 
 
2547
 
      err= ib_get_index_stat_n_diff_key_vals(cursor, index_name,
2548
 
                                             &ncols, &n_diff);
2549
 
 
2550
 
      if (err != DB_SUCCESS)
2551
 
        return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2552
 
 
2553
 
      for (unsigned int j=0; j < getTable()->key_info[i].key_parts; j++)
2554
 
      {
2555
 
        if (n_diff[j+1] == 0)
2556
 
          rec_per_key= stats.records;
2557
 
        else
2558
 
          rec_per_key= stats.records / n_diff[j+1];
2559
 
 
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. */
2563
 
 
2564
 
        rec_per_key= rec_per_key / 2;
2565
 
 
2566
 
        if (rec_per_key == 0)
2567
 
          rec_per_key= 1;
2568
 
 
2569
 
        getTable()->key_info[i].rec_per_key[j]=
2570
 
          rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
2571
 
          (ulong) rec_per_key;
2572
 
      }
2573
 
 
2574
 
      free(n_diff);
2575
 
    }
2576
 
  }
2577
 
 
2578
2459
  return(0);
2579
2460
}
2580
2461
 
2581
2462
int HailDBCursor::doStartIndexScan(uint32_t keynr, bool)
2582
2463
{
2583
 
  ib_err_t err;
2584
2464
  ib_trx_t transaction= *get_trx(getTable()->in_use);
2585
2465
 
2586
2466
  active_index= keynr;
2587
2467
 
 
2468
  ib_cursor_attach_trx(cursor, transaction);
 
2469
 
2588
2470
  if (active_index == 0 && ! share->has_hidden_primary_key)
2589
2471
  {
2590
 
    if (cursor_is_sec_index)
2591
 
    {
2592
 
      err= ib_cursor_close(cursor);
2593
 
      assert(err == DB_SUCCESS);
2594
 
 
2595
 
      err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2596
 
 
2597
 
      if (err != DB_SUCCESS)
2598
 
        return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2599
 
 
2600
 
    }
2601
 
    else
2602
 
    {
2603
 
      ib_cursor_attach_trx(cursor, transaction);
2604
 
    }
2605
 
 
2606
 
    cursor_is_sec_index= false;
2607
2472
    tuple= ib_clust_read_tuple_create(cursor);
2608
2473
  }
2609
2474
  else
2610
2475
  {
 
2476
    ib_err_t err;
2611
2477
    ib_id_t index_id;
2612
2478
    err= ib_index_get_id(table_path_to_haildb_name(getShare()->getPath()),
2613
2479
                         getShare()->getKeyInfo(keynr).name,
2614
2480
                         &index_id);
2615
2481
    if (err != DB_SUCCESS)
2616
 
      return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2482
      return -1;
2617
2483
 
2618
2484
    err= ib_cursor_close(cursor);
2619
2485
    assert(err == DB_SUCCESS);
2620
 
 
2621
2486
    err= ib_cursor_open_index_using_id(index_id, transaction, &cursor);
2622
2487
 
2623
2488
    if (err != DB_SUCCESS)
2624
 
      return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2625
 
 
2626
 
    cursor_is_sec_index= true;
 
2489
      return -1;
2627
2490
 
2628
2491
    tuple= ib_clust_read_tuple_create(cursor);
2629
2492
    ib_cursor_set_cluster_access(cursor);
2630
2493
  }
2631
2494
 
2632
 
  err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
 
2495
  ib_err_t err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
2633
2496
  assert(err == DB_SUCCESS);
2634
2497
 
2635
2498
  advance_cursor= false;
2774
2637
 
2775
2638
  if (err != DB_SUCCESS)
2776
2639
  {
2777
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2640
    return ib_err_t_to_drizzle_error(err);
2778
2641
  }
2779
2642
 
2780
2643
  tuple= ib_tuple_clear(tuple);
2781
 
  ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2782
 
                            getTable(),
 
2644
  ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2783
2645
                            share->has_hidden_primary_key,
2784
2646
                            &hidden_autoinc_pkey_position,
2785
2647
                            (allocate_blobs)? &blobroot : NULL);
2856
2718
  return 0;
2857
2719
}
2858
2720
 
2859
 
int HailDBCursor::analyze(Session*)
2860
 
{
2861
 
  ib_err_t err;
2862
 
 
2863
 
  err= ib_update_table_statistics(cursor);
2864
 
 
2865
 
  return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2866
 
}
2867
 
 
2868
2721
int HailDBCursor::index_next(unsigned char *buf)
2869
2722
{
2870
2723
  int ret= HA_ERR_END_OF_FILE;
2877
2730
  }
2878
2731
 
2879
2732
  tuple= ib_tuple_clear(tuple);
2880
 
  ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2881
 
                            getTable(),
 
2733
  ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2882
2734
                            share->has_hidden_primary_key,
2883
2735
                            &hidden_autoinc_pkey_position);
2884
2736
 
2906
2758
      if (err == DB_END_OF_INDEX)
2907
2759
        return HA_ERR_END_OF_FILE;
2908
2760
      else
2909
 
        return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2761
        return -1; // FIXME
2910
2762
    }
2911
2763
  }
2912
2764
 
2913
2765
  tuple= ib_tuple_clear(tuple);
2914
 
  ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2915
 
                            getTable(),
 
2766
  ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2916
2767
                            share->has_hidden_primary_key,
2917
2768
                            &hidden_autoinc_pkey_position);
2918
2769
 
2929
2780
 
2930
2781
  err= ib_cursor_first(cursor);
2931
2782
  if (err != DB_SUCCESS)
2932
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2783
    return ib_err_t_to_drizzle_error(err);
2933
2784
 
2934
2785
  tuple= ib_tuple_clear(tuple);
2935
 
  ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2936
 
                            getTable(),
 
2786
  ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2937
2787
                            share->has_hidden_primary_key,
2938
2788
                            &hidden_autoinc_pkey_position);
2939
2789
 
2950
2800
 
2951
2801
  err= ib_cursor_last(cursor);
2952
2802
  if (err != DB_SUCCESS)
2953
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2803
    return ib_err_t_to_drizzle_error(err);
2954
2804
 
2955
2805
  tuple= ib_tuple_clear(tuple);
2956
 
  ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2957
 
                            getTable(),
 
2806
  ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2958
2807
                            share->has_hidden_primary_key,
2959
2808
                            &hidden_autoinc_pkey_position);
2960
2809
  advance_cursor= true;
3147
2996
  bool r= false;
3148
2997
  va_list args;
3149
2998
  va_start(args, fmt);
3150
 
  if (not shutdown_in_progress)
3151
 
  {
3152
 
    r= plugin::ErrorMessage::vprintf(error::WARN, fmt, args);
3153
 
  }
 
2999
  if (! shutdown_in_progress)
 
3000
    r= plugin::ErrorMessage::vprintf(NULL, ERRMSG_LVL_WARN, fmt, args);
3154
3001
  else
3155
 
  {
3156
3002
    vfprintf(stderr, fmt, args);
3157
 
  }
3158
3003
  va_end(args);
3159
3004
 
3160
3005
  return (! r==true);
3539
3384
  "Transactional Storage Engine using the HailDB Library",
3540
3385
  PLUGIN_LICENSE_GPL,
3541
3386
  haildb_init,     /* Plugin Init */
3542
 
  NULL, /* depends */
 
3387
  NULL, /* system variables */
3543
3388
  init_options                /* config options   */
3544
3389
}
3545
3390
DRIZZLE_DECLARE_PLUGIN_END;