~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/haildb/haildb_engine.cc

  • Committer: Andrew Hutchings
  • Date: 2010-12-15 18:59:55 UTC
  • mto: This revision was merged to the branch mainline in revision 2006.
  • Revision ID: andrew@linuxjedi.co.uk-20101215185955-q12lkja8hdnpjqg7
Make the test look for drizzleadmin failure instead of success as this test is not possible to fix for success on our FreeBSD 8.0 box

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
101
101
#include "haildb_engine.h"
102
102
 
103
103
#include <drizzled/field.h>
 
104
#include "drizzled/field/timestamp.h" // needed for UPDATE NOW()
104
105
#include "drizzled/field/blob.h"
105
106
#include "drizzled/field/enum.h"
106
107
#include <drizzled/session.h>
116
117
using namespace google;
117
118
using namespace drizzled;
118
119
 
119
 
int read_row_from_haildb(Session *session, unsigned char* buf, ib_crsr_t cursor, ib_tpl_t tuple, Table* table, bool has_hidden_primary_key, uint64_t *hidden_pkey, drizzled::memory::Root **blobroot= NULL);
 
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);
120
121
static void fill_ib_search_tpl_from_drizzle_key(ib_tpl_t search_tuple,
121
122
                                                const drizzled::KeyInfo *key_info,
122
123
                                                const unsigned char *key_ptr,
165
166
 
166
167
  int doCreateTable(Session&,
167
168
                    Table& table_arg,
168
 
                    const drizzled::identifier::Table &identifier,
 
169
                    const drizzled::TableIdentifier &identifier,
169
170
                    drizzled::message::Table& proto);
170
171
 
171
 
  int doDropTable(Session&, const identifier::Table &identifier);
 
172
  int doDropTable(Session&, const TableIdentifier &identifier);
172
173
 
173
174
  int doRenameTable(drizzled::Session&,
174
 
                    const drizzled::identifier::Table&,
175
 
                    const drizzled::identifier::Table&);
 
175
                    const drizzled::TableIdentifier&,
 
176
                    const drizzled::TableIdentifier&);
176
177
 
177
178
  int doGetTableDefinition(Session& session,
178
 
                           const identifier::Table &identifier,
 
179
                           const TableIdentifier &identifier,
179
180
                           drizzled::message::Table &table_proto);
180
181
 
181
 
  bool doDoesTableExist(Session&, const identifier::Table &identifier);
 
182
  bool doDoesTableExist(Session&, const TableIdentifier &identifier);
182
183
 
183
184
private:
184
 
  void getTableNamesInSchemaFromHailDB(const drizzled::identifier::Schema &schema,
 
185
  void getTableNamesInSchemaFromHailDB(const drizzled::SchemaIdentifier &schema,
185
186
                                       drizzled::plugin::TableNameList *set_of_names,
186
 
                                       drizzled::identifier::Table::vector *identifiers);
 
187
                                       drizzled::TableIdentifier::vector *identifiers);
187
188
 
188
189
public:
189
190
  void doGetTableIdentifiers(drizzled::CachedDirectory &,
190
 
                             const drizzled::identifier::Schema &schema,
191
 
                             drizzled::identifier::Table::vector &identifiers);
 
191
                             const drizzled::SchemaIdentifier &schema,
 
192
                             drizzled::TableIdentifier::vector &identifiers);
192
193
 
193
194
  /* The following defines can be increased if necessary */
194
195
  uint32_t max_supported_keys()          const { return 1000; }
239
240
/* This is a superset of the map from innobase plugin.
240
241
   Unlike innobase plugin we don't act on errors here, we just
241
242
   map error codes. */
242
 
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)
243
244
{
244
245
  switch (err)
245
246
  {
269
270
    return HA_ERR_NO_ACTIVE_RECORD;
270
271
 
271
272
  case DB_DEADLOCK:
272
 
    /* HailDB will roll back a transaction itself due to DB_DEADLOCK.
273
 
       This means we have to tell Drizzle about it */
274
 
    session->markTransactionForRollback(true);
275
273
    return HA_ERR_LOCK_DEADLOCK;
276
274
 
277
275
  case DB_LOCK_WAIT_TIMEOUT:
353
351
  (void)options;
354
352
 
355
353
  transaction= get_trx(session);
356
 
  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));
357
355
  *transaction= ib_trx_begin(isolation_level);
358
356
 
359
 
  return *transaction == NULL;
 
357
  return 0;
360
358
}
361
359
 
362
360
void HailDBEngine::doStartStatement(Session *session)
390
388
  err= ib_savepoint_rollback(*transaction, savepoint.getName().c_str(),
391
389
                             savepoint.getName().length());
392
390
 
393
 
  return ib_err_t_to_drizzle_error(session, err);
 
391
  return ib_err_t_to_drizzle_error(err);
394
392
}
395
393
 
396
394
int HailDBEngine::doReleaseSavepoint(Session* session,
402
400
  err= ib_savepoint_release(*transaction, savepoint.getName().c_str(),
403
401
                            savepoint.getName().length());
404
402
  if (err != DB_SUCCESS)
405
 
    return ib_err_t_to_drizzle_error(session, err);
 
403
    return ib_err_t_to_drizzle_error(err);
406
404
 
407
405
  return 0;
408
406
}
412
410
  ib_err_t err;
413
411
  ib_trx_t *transaction= get_trx(session);
414
412
 
415
 
  if (all)
 
413
  if (all || (!session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
416
414
  {
417
415
    err= ib_trx_commit(*transaction);
418
416
 
419
417
    if (err != DB_SUCCESS)
420
 
      return ib_err_t_to_drizzle_error(session, err);
 
418
      return ib_err_t_to_drizzle_error(err);
421
419
 
422
420
    *transaction= NULL;
423
421
  }
430
428
  ib_err_t err;
431
429
  ib_trx_t *transaction= get_trx(session);
432
430
 
433
 
  if (all)
 
431
  if (all || !session_test_options(session, OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))
434
432
  {
435
 
    if (ib_trx_state(*transaction) == IB_TRX_NOT_STARTED)
436
 
      err= ib_trx_release(*transaction);
437
 
    else
438
 
      err= ib_trx_rollback(*transaction);
 
433
    err= ib_trx_rollback(*transaction);
439
434
 
440
435
    if (err != DB_SUCCESS)
441
 
      return ib_err_t_to_drizzle_error(session, err);
 
436
      return ib_err_t_to_drizzle_error(err);
442
437
 
443
438
    *transaction= NULL;
444
439
  }
445
440
  else
446
441
  {
447
 
    if (ib_trx_state(*transaction) == IB_TRX_NOT_STARTED)
448
 
      return 0;
449
 
 
450
442
    err= ib_savepoint_rollback(*transaction, statement_savepoint_name.c_str(),
451
443
                               statement_savepoint_name.length());
452
444
    if (err != DB_SUCCESS)
453
 
      return ib_err_t_to_drizzle_error(session, err);
 
445
      return ib_err_t_to_drizzle_error(err);
454
446
  }
455
447
 
456
448
  return 0;
494
486
  else
495
487
  {
496
488
    assert (err == DB_SUCCESS);
497
 
    err= ib_tuple_read_u64(tuple, getTable()->getShare()->sizeFields(), &nr);
 
489
    err= ib_tuple_read_u64(tuple, getTable()->getShare()->fields, &nr);
498
490
    nr++;
499
491
  }
500
492
  ib_tuple_delete(tuple);
501
 
  tuple= NULL;
502
493
  err= ib_cursor_reset(cursor);
503
494
  assert(err == DB_SUCCESS);
504
495
  return nr;
535
526
  doEndIndexScan();
536
527
  (void) extra(HA_EXTRA_NO_KEYREAD);
537
528
 
538
 
  if (getTable()->getShare()->getTableMessage()->options().auto_increment_value() > nr)
539
 
    nr= getTable()->getShare()->getTableMessage()->options().auto_increment_value();
 
529
  if (getTable()->getShare()->getTableProto()->options().auto_increment_value() > nr)
 
530
    nr= getTable()->getShare()->getTableProto()->options().auto_increment_value();
540
531
 
541
532
  return nr;
542
533
}
649
640
 
650
641
  /* the below is adapted from ha_innodb.cc */
651
642
 
652
 
  const uint32_t sql_command = session->getSqlCommand();
 
643
  const uint32_t sql_command = session_sql_command(session);
653
644
 
654
645
  if (sql_command == SQLCOM_DROP_TABLE) {
655
646
 
680
671
    unexpected if an obsolete consistent read view would be
681
672
    used. */
682
673
 
683
 
    enum_tx_isolation isolation_level= session->getTxIsolation();
 
674
    enum_tx_isolation isolation_level= session_tx_isolation(session);
684
675
 
685
676
    if (isolation_level != ISO_SERIALIZABLE
686
677
        && (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT)
723
714
 
724
715
    if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
725
716
         && lock_type <= TL_WRITE)
726
 
        && ! session->doing_tablespace_operation()
 
717
        && !session_tablespace_op(session)
727
718
        && sql_command != SQLCOM_TRUNCATE
728
719
        && sql_command != SQLCOM_CREATE_TABLE) {
729
720
 
800
791
  return &name[l];
801
792
}
802
793
 
803
 
static void TableIdentifier_to_haildb_name(const identifier::Table &identifier, std::string *str)
 
794
static void TableIdentifier_to_haildb_name(const TableIdentifier &identifier, std::string *str)
804
795
{
805
796
  str->assign(table_path_to_haildb_name(identifier.getPath().c_str()));
806
797
}
829
820
int HailDBCursor::open(const char *name, int, uint32_t)
830
821
{
831
822
  const char* haildb_table_name= table_path_to_haildb_name(name);
832
 
  ib_err_t err= ib_table_get_id(haildb_table_name, &table_id);
 
823
  ib_err_t err= ib_cursor_open_table(haildb_table_name, NULL, &cursor);
833
824
  bool has_hidden_primary_key= false;
834
825
  ib_id_t idx_id;
835
826
 
836
827
  if (err != DB_SUCCESS)
837
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
838
 
 
839
 
  err= ib_cursor_open_table_using_id(table_id, NULL, &cursor);
840
 
  cursor_is_sec_index= false;
841
 
 
842
 
  if (err != DB_SUCCESS)
843
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
828
    return ib_err_t_to_drizzle_error(err);
844
829
 
845
830
  err= ib_index_get_id(haildb_table_name, "HIDDEN_PRIMARY", &idx_id);
846
831
 
871
856
{
872
857
  ib_err_t err= ib_cursor_close(cursor);
873
858
  if (err != DB_SUCCESS)
874
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
859
    return ib_err_t_to_drizzle_error(err);
875
860
 
876
861
  free_share();
877
862
 
904
889
{
905
890
  ib_col_attr_t column_attr= IB_COL_NONE;
906
891
 
907
 
  if (field.has_constraints() && field.constraints().is_notnull())
 
892
  if (field.has_constraints() && ! field.constraints().is_nullable())
908
893
    column_attr= IB_COL_NOT_NULL;
909
894
 
910
895
  switch (field.type())
935
920
    *err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
936
921
                                  column_attr, 0, 4);
937
922
    break;
938
 
  case message::Table::Field::EPOCH:
 
923
  case message::Table::Field::TIMESTAMP:
939
924
    *err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
940
925
                                  column_attr, 0, 8);
941
926
    break;
1035
1020
 
1036
1021
int HailDBEngine::doCreateTable(Session &session,
1037
1022
                                        Table& table_obj,
1038
 
                                        const drizzled::identifier::Table &identifier,
 
1023
                                        const drizzled::TableIdentifier &identifier,
1039
1024
                                        drizzled::message::Table& table_message)
1040
1025
{
1041
1026
  ib_tbl_sch_t haildb_table_schema= NULL;
1079
1064
                        ER_CANT_CREATE_TABLE,
1080
1065
                        _("Cannot create table %s. HailDB Error %d (%s)\n"),
1081
1066
                        haildb_table_name.c_str(), haildb_err, ib_strerror(haildb_err));
1082
 
    return ib_err_t_to_drizzle_error(&session, haildb_err);
 
1067
    return ib_err_t_to_drizzle_error(haildb_err);
1083
1068
  }
1084
1069
 
1085
1070
  for (int colnr= 0; colnr < table_message.field_size() ; colnr++)
1100
1085
                            " HailDB Error %d (%s)\n"),
1101
1086
                          field.name().c_str(), haildb_table_name.c_str(),
1102
1087
                          haildb_err, ib_strerror(haildb_err));
1103
 
      return ib_err_t_to_drizzle_error(&session, haildb_err);
 
1088
      return ib_err_t_to_drizzle_error(haildb_err);
1104
1089
    }
1105
1090
    if (field_err != 0)
1106
1091
      return field_err;
1248
1233
                        _("Cannot create table %s. HailDB Error %d (%s)\n"),
1249
1234
                        haildb_table_name.c_str(),
1250
1235
                        haildb_err, ib_strerror(haildb_err));
1251
 
    return ib_err_t_to_drizzle_error(&session, haildb_err);
 
1236
    return ib_err_t_to_drizzle_error(haildb_err);
1252
1237
  }
1253
1238
 
1254
1239
  return 0;
1291
1276
}
1292
1277
 
1293
1278
int HailDBEngine::doDropTable(Session &session,
1294
 
                                      const identifier::Table &identifier)
 
1279
                                      const TableIdentifier &identifier)
1295
1280
{
1296
1281
  ib_trx_t haildb_schema_transaction;
1297
1282
  ib_err_t haildb_err;
1373
1358
  return 0;
1374
1359
}
1375
1360
 
1376
 
static ib_err_t rename_table_message(ib_trx_t transaction, const identifier::Table &from_identifier, const identifier::Table &to_identifier)
 
1361
static ib_err_t rename_table_message(ib_trx_t transaction, const TableIdentifier &from_identifier, const TableIdentifier &to_identifier)
1377
1362
{
1378
1363
  ib_crsr_t cursor;
1379
1364
  ib_tpl_t search_tuple;
1464
1449
}
1465
1450
 
1466
1451
int HailDBEngine::doRenameTable(drizzled::Session &session,
1467
 
                                        const drizzled::identifier::Table &from,
1468
 
                                        const drizzled::identifier::Table &to)
 
1452
                                        const drizzled::TableIdentifier &from,
 
1453
                                        const drizzled::TableIdentifier &to)
1469
1454
{
1470
1455
  ib_trx_t haildb_schema_transaction;
1471
1456
  ib_err_t err;
1515
1500
  assert(rollback_err == DB_SUCCESS);
1516
1501
  rollback_err= ib_trx_rollback(haildb_schema_transaction);
1517
1502
  assert(rollback_err == DB_SUCCESS);
1518
 
  return ib_err_t_to_drizzle_error(&session, err);
 
1503
  return ib_err_t_to_drizzle_error(err);
1519
1504
}
1520
1505
 
1521
1506
void HailDBEngine::getTableNamesInSchemaFromHailDB(
1522
 
                                 const drizzled::identifier::Schema &schema,
 
1507
                                 const drizzled::SchemaIdentifier &schema,
1523
1508
                                 drizzled::plugin::TableNameList *set_of_names,
1524
 
                                 drizzled::identifier::Table::vector *identifiers)
 
1509
                                 drizzled::TableIdentifier::vector *identifiers)
1525
1510
{
1526
1511
  ib_trx_t   transaction;
1527
1512
  ib_crsr_t  cursor;
1551
1536
    {
1552
1537
      BOOST_FOREACH(std::string table_name, haildb_system_table_names)
1553
1538
      {
1554
 
        identifiers->push_back(identifier::Table(schema.getSchemaName(),
 
1539
        identifiers->push_back(TableIdentifier(schema.getSchemaName(),
1555
1540
                                               table_name));
1556
1541
      }
1557
1542
    }
1594
1579
      if (set_of_names)
1595
1580
        set_of_names->insert(just_table_name);
1596
1581
      if (identifiers)
1597
 
        identifiers->push_back(identifier::Table(schema.getSchemaName(), just_table_name));
 
1582
        identifiers->push_back(TableIdentifier(schema.getSchemaName(), just_table_name));
1598
1583
    }
1599
1584
 
1600
1585
 
1613
1598
}
1614
1599
 
1615
1600
void HailDBEngine::doGetTableIdentifiers(drizzled::CachedDirectory &,
1616
 
                                                 const drizzled::identifier::Schema &schema,
1617
 
                                                 drizzled::identifier::Table::vector &identifiers)
 
1601
                                                 const drizzled::SchemaIdentifier &schema,
 
1602
                                                 drizzled::TableIdentifier::vector &identifiers)
1618
1603
{
1619
1604
  getTableNamesInSchemaFromHailDB(schema, NULL, &identifiers);
1620
1605
}
1739
1724
}
1740
1725
 
1741
1726
int HailDBEngine::doGetTableDefinition(Session &session,
1742
 
                                               const identifier::Table &identifier,
 
1727
                                               const TableIdentifier &identifier,
1743
1728
                                               drizzled::message::Table &table)
1744
1729
{
1745
1730
  ib_crsr_t haildb_cursor= NULL;
1768
1753
}
1769
1754
 
1770
1755
bool HailDBEngine::doDoesTableExist(Session &,
1771
 
                                    const identifier::Table& identifier)
 
1756
                                    const TableIdentifier& identifier)
1772
1757
{
1773
1758
  ib_crsr_t haildb_cursor;
1774
1759
  string haildb_table_name;
1793
1778
  return("BTREE");
1794
1779
}
1795
1780
 
1796
 
static ib_err_t write_row_to_haildb_tuple(const unsigned char* buf,
1797
 
                                          Field **fields, ib_tpl_t tuple)
 
1781
static ib_err_t write_row_to_haildb_tuple(Field **fields, ib_tpl_t tuple)
1798
1782
{
1799
1783
  int colnr= 0;
1800
1784
  ib_err_t err= DB_ERROR;
1801
 
  ptrdiff_t row_offset= buf - (*fields)->getTable()->getInsertRecord();
1802
1785
 
1803
1786
  for (Field **field= fields; *field; field++, colnr++)
1804
1787
  {
1805
 
    (**field).move_field_offset(row_offset);
1806
 
 
1807
1788
    if (! (**field).isWriteSet() && (**field).is_null())
1808
 
    {
1809
 
      (**field).move_field_offset(-row_offset);
1810
1789
      continue;
1811
 
    }
1812
1790
 
1813
1791
    if ((**field).is_null())
1814
1792
    {
1815
1793
      err= ib_col_set_value(tuple, colnr, NULL, IB_SQL_NULL);
1816
1794
      assert(err == DB_SUCCESS);
1817
 
      (**field).move_field_offset(-row_offset);
1818
1795
      continue;
1819
1796
    }
1820
1797
 
1826
1803
      */
1827
1804
      String str;
1828
1805
      (**field).setReadSet();
1829
 
      (**field).val_str_internal(&str);
 
1806
      (**field).val_str(&str);
1830
1807
      err= ib_col_set_value(tuple, colnr, str.ptr(), str.length());
1831
1808
    }
1832
1809
    else if ((**field).type() == DRIZZLE_TYPE_ENUM)
1852
1829
    }
1853
1830
 
1854
1831
    assert (err == DB_SUCCESS);
1855
 
 
1856
 
    (**field).move_field_offset(-row_offset);
1857
1832
  }
1858
1833
 
1859
1834
  return err;
1902
1877
 
1903
1878
  tuple= ib_clust_read_tuple_create(cursor);
1904
1879
 
1905
 
  if (cursor_is_sec_index)
1906
 
  {
1907
 
    err= ib_cursor_close(cursor);
1908
 
    assert(err == DB_SUCCESS);
1909
 
 
1910
 
    err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
1911
 
 
1912
 
    if (err != DB_SUCCESS)
1913
 
      return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
1914
 
 
1915
 
    cursor_is_sec_index= false;
1916
 
  }
1917
 
  else
1918
 
  {
1919
 
    ib_cursor_attach_trx(cursor, transaction);
1920
 
  }
 
1880
  ib_cursor_attach_trx(cursor, transaction);
1921
1881
 
1922
1882
  err= ib_cursor_first(cursor);
1923
1883
  if (current_session->lex->sql_command == SQLCOM_CREATE_TABLE
1976
1936
 
1977
1937
  }
1978
1938
 
1979
 
  write_row_to_haildb_tuple(record, getTable()->getFields(), tuple);
 
1939
  write_row_to_haildb_tuple(getTable()->getFields(), tuple);
1980
1940
 
1981
1941
  if (share->has_hidden_primary_key)
1982
1942
  {
1983
 
    err= ib_tuple_write_u64(tuple, getTable()->getShare()->sizeFields(),
1984
 
                            share->hidden_pkey_auto_increment_value.fetch_and_increment());
 
1943
    err= ib_tuple_write_u64(tuple, getTable()->getShare()->fields, share->hidden_pkey_auto_increment_value.fetch_and_increment());
1985
1944
  }
1986
1945
 
1987
1946
  err= ib_cursor_insert_row(cursor, tuple);
2010
1969
      err= ib_cursor_first(cursor);
2011
1970
      assert(err == DB_SUCCESS || err == DB_END_OF_INDEX);
2012
1971
 
2013
 
      write_row_to_haildb_tuple(record, getTable()->getFields(), tuple);
 
1972
      write_row_to_haildb_tuple(getTable()->getFields(), tuple);
2014
1973
 
2015
1974
      err= ib_cursor_insert_row(cursor, tuple);
2016
1975
      assert(err==DB_SUCCESS); // probably be nice and process errors
2019
1978
      ret= HA_ERR_FOUND_DUPP_KEY;
2020
1979
  }
2021
1980
  else if (err != DB_SUCCESS)
2022
 
    ret= ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
1981
    ret= ib_err_t_to_drizzle_error(err);
2023
1982
 
2024
1983
  tuple= ib_tuple_clear(tuple);
2025
1984
  ib_tuple_delete(tuple);
2026
 
  tuple= NULL;
2027
1985
  err= ib_cursor_reset(cursor);
2028
1986
 
2029
1987
  return ret;
2030
1988
}
2031
1989
 
2032
 
int HailDBCursor::doUpdateRecord(const unsigned char *old_data,
2033
 
                                 unsigned char *new_data)
 
1990
int HailDBCursor::doUpdateRecord(const unsigned char *,
 
1991
                                         unsigned char *)
2034
1992
{
2035
1993
  ib_tpl_t update_tuple;
2036
1994
  ib_err_t err;
2037
 
  bool created_tuple= false;
2038
1995
 
2039
1996
  update_tuple= ib_clust_read_tuple_create(cursor);
2040
1997
 
2041
 
  if (tuple == NULL)
2042
 
  {
2043
 
    ib_trx_t transaction= *get_trx(getTable()->in_use);
2044
 
 
2045
 
    if (cursor_is_sec_index)
2046
 
    {
2047
 
      err= ib_cursor_close(cursor);
2048
 
      assert(err == DB_SUCCESS);
2049
 
 
2050
 
      err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2051
 
 
2052
 
      if (err != DB_SUCCESS)
2053
 
        return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2054
 
      cursor_is_sec_index= false;
2055
 
    }
2056
 
    else
2057
 
    {
2058
 
      ib_cursor_attach_trx(cursor, transaction);
2059
 
    }
2060
 
 
2061
 
    store_key_value_from_haildb(getTable()->key_info + getTable()->getShare()->getPrimaryKey(),
2062
 
                                  ref, ref_length, old_data);
2063
 
 
2064
 
    ib_tpl_t search_tuple= ib_clust_search_tuple_create(cursor);
2065
 
 
2066
 
    fill_ib_search_tpl_from_drizzle_key(search_tuple,
2067
 
                                        getTable()->key_info + 0,
2068
 
                                        ref, ref_length);
2069
 
 
2070
 
    err= ib_cursor_set_lock_mode(cursor, IB_LOCK_X);
2071
 
    assert(err == DB_SUCCESS);
2072
 
 
2073
 
    int res;
2074
 
    err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
2075
 
    assert(err == DB_SUCCESS);
2076
 
 
2077
 
    tuple= ib_clust_read_tuple_create(cursor);
2078
 
 
2079
 
    err= ib_cursor_read_row(cursor, tuple);
2080
 
    assert(err == DB_SUCCESS);// FIXME
2081
 
 
2082
 
    created_tuple= true;
2083
 
  }
2084
 
 
2085
1998
  err= ib_tuple_copy(update_tuple, tuple);
2086
1999
  assert(err == DB_SUCCESS);
2087
2000
 
2088
 
  write_row_to_haildb_tuple(new_data, getTable()->getFields(), update_tuple);
 
2001
  write_row_to_haildb_tuple(getTable()->getFields(), update_tuple);
2089
2002
 
2090
2003
  err= ib_cursor_update_row(cursor, tuple, update_tuple);
2091
2004
 
2092
2005
  ib_tuple_delete(update_tuple);
2093
2006
 
2094
 
  if (created_tuple)
2095
 
  {
2096
 
    ib_err_t ib_err= ib_cursor_reset(cursor); //fixme check error
2097
 
    assert(ib_err == DB_SUCCESS);
2098
 
    tuple= ib_tuple_clear(tuple);
2099
 
    ib_tuple_delete(tuple);
2100
 
    tuple= NULL;
2101
 
  }
2102
 
 
2103
2007
  advance_cursor= true;
2104
2008
 
2105
 
  return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2009
  if (err == DB_SUCCESS)
 
2010
    return 0;
 
2011
  else if (err == DB_DUPLICATE_KEY)
 
2012
    return HA_ERR_FOUND_DUPP_KEY;
 
2013
  else
 
2014
    return -1;
2106
2015
}
2107
2016
 
2108
2017
int HailDBCursor::doDeleteRecord(const unsigned char *)
2109
2018
{
2110
2019
  ib_err_t err;
2111
2020
 
2112
 
  assert(ib_cursor_is_positioned(cursor) == IB_TRUE);
2113
2021
  err= ib_cursor_delete_row(cursor);
 
2022
  if (err != DB_SUCCESS)
 
2023
    return -1; // FIXME
2114
2024
 
2115
2025
  advance_cursor= true;
2116
 
 
2117
 
  return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2026
  return 0;
2118
2027
}
2119
2028
 
2120
2029
int HailDBCursor::delete_all_rows(void)
2121
2030
{
2122
2031
  /* I *think* ib_truncate is non-transactional....
2123
2032
     so only support TRUNCATE and not DELETE FROM t;
2124
 
     (this is what ha_innodb does)
 
2033
     (this is what ha_haildb does)
2125
2034
  */
2126
 
  if (getTable()->in_use->getSqlCommand() != SQLCOM_TRUNCATE)
 
2035
  if (session_sql_command(getTable()->in_use) != SQLCOM_TRUNCATE)
2127
2036
    return HA_ERR_WRONG_COMMAND;
2128
2037
 
2129
2038
  ib_id_t id;
2131
2040
 
2132
2041
  ib_trx_t transaction= ib_trx_begin(IB_TRX_REPEATABLE_READ);
2133
2042
 
2134
 
  if (cursor_is_sec_index)
2135
 
  {
2136
 
    err= ib_cursor_close(cursor);
2137
 
    assert(err == DB_SUCCESS);
2138
 
 
2139
 
    err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2140
 
 
2141
 
    if (err != DB_SUCCESS)
2142
 
      return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2143
 
    cursor_is_sec_index= false;
2144
 
  }
2145
 
  else
2146
 
  {
2147
 
    ib_cursor_attach_trx(cursor, transaction);
2148
 
  }
 
2043
  ib_cursor_attach_trx(cursor, transaction);
2149
2044
 
2150
2045
  err= ib_schema_lock_exclusive(transaction);
2151
2046
  if (err != DB_SUCCESS)
2181
2076
  ib_schema_unlock(transaction);
2182
2077
  ib_err_t rollback_err= ib_trx_rollback(transaction);
2183
2078
  assert(rollback_err == DB_SUCCESS);
2184
 
  return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2079
  return err;
2185
2080
}
2186
2081
 
2187
2082
int HailDBCursor::doStartTableScan(bool)
2188
2083
{
2189
 
  ib_err_t err= DB_SUCCESS;
 
2084
  ib_err_t err;
2190
2085
  ib_trx_t transaction;
2191
2086
 
2192
2087
  if (in_table_scan)
2197
2092
 
2198
2093
  assert(transaction != NULL);
2199
2094
 
2200
 
  if (cursor_is_sec_index)
2201
 
  {
2202
 
    err= ib_cursor_close(cursor);
2203
 
    assert(err == DB_SUCCESS);
2204
 
 
2205
 
    err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2206
 
    cursor_is_sec_index= false;
2207
 
  }
2208
 
  else
2209
 
  {
2210
 
    ib_cursor_attach_trx(cursor, transaction);
2211
 
  }
2212
 
 
2213
 
  if (err != DB_SUCCESS)
2214
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2095
  ib_cursor_attach_trx(cursor, transaction);
2215
2096
 
2216
2097
  err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
2217
2098
  assert(err == DB_SUCCESS); // FIXME
2221
2102
  err= ib_cursor_first(cursor);
2222
2103
  if (err != DB_SUCCESS && err != DB_END_OF_INDEX)
2223
2104
  {
2224
 
    int reset_err= ib_cursor_reset(cursor);
2225
 
    assert(reset_err == DB_SUCCESS);
2226
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2105
    previous_error= ib_err_t_to_drizzle_error(err);
 
2106
    err= ib_cursor_reset(cursor);
 
2107
    return previous_error;
2227
2108
  }
2228
2109
 
2229
2110
  advance_cursor= false;
2230
2111
 
 
2112
  previous_error= 0;
2231
2113
  return(0);
2232
2114
}
2233
2115
 
2234
 
int read_row_from_haildb(Session *session, unsigned char* buf, ib_crsr_t cursor, ib_tpl_t tuple, Table* table, bool has_hidden_primary_key, uint64_t *hidden_pkey, drizzled::memory::Root **blobroot)
 
2116
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)
2235
2117
{
2236
2118
  ib_err_t err;
2237
2119
  ptrdiff_t row_offset= buf - table->getInsertRecord();
2238
2120
 
2239
2121
  err= ib_cursor_read_row(cursor, tuple);
2240
2122
 
2241
 
  if (err == DB_RECORD_NOT_FOUND)
 
2123
  if (err != DB_SUCCESS) // FIXME
2242
2124
    return HA_ERR_END_OF_FILE;
2243
 
  if (err != DB_SUCCESS)
2244
 
    return ib_err_t_to_drizzle_error(session, err);
2245
2125
 
2246
2126
  int colnr= 0;
2247
2127
 
2252
2132
  for (Field **field= table->getFields() ; *field ; field++, colnr++)
2253
2133
  {
2254
2134
    if (! (**field).isReadSet())
2255
 
      (**field).setReadSet(); /* Fucking broken API screws us royally. */
 
2135
      continue;
2256
2136
 
2257
2137
    (**field).move_field_offset(row_offset);
2258
2138
 
2262
2142
    if (length == IB_SQL_NULL)
2263
2143
    {
2264
2144
      (**field).set_null();
2265
 
      (**field).move_field_offset(-row_offset);
2266
2145
      continue;
2267
2146
    }
2268
2147
    else
2306
2185
 
2307
2186
    (**field).move_field_offset(-row_offset);
2308
2187
 
2309
 
    if (err != DB_SUCCESS)
2310
 
      return ib_err_t_to_drizzle_error(session, err);
2311
2188
  }
2312
2189
 
2313
2190
  if (has_hidden_primary_key)
2315
2192
    err= ib_tuple_read_u64(tuple, colnr, hidden_pkey);
2316
2193
  }
2317
2194
 
2318
 
  return ib_err_t_to_drizzle_error(session, err);
 
2195
  return 0;
2319
2196
}
2320
2197
 
2321
2198
int HailDBCursor::rnd_next(unsigned char *buf)
2323
2200
  ib_err_t err;
2324
2201
  int ret;
2325
2202
 
 
2203
  if (previous_error)
 
2204
    return previous_error;
 
2205
 
2326
2206
  if (advance_cursor)
2327
 
  {
2328
2207
    err= ib_cursor_next(cursor);
2329
 
    if (err != DB_SUCCESS)
2330
 
      return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2331
 
  }
2332
2208
 
2333
2209
  tuple= ib_tuple_clear(tuple);
2334
 
  ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2335
 
                            getTable(),
 
2210
  ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2336
2211
                            share->has_hidden_primary_key,
2337
2212
                            &hidden_autoinc_pkey_position);
2338
2213
 
2345
2220
  ib_err_t err;
2346
2221
 
2347
2222
  ib_tuple_delete(tuple);
2348
 
  tuple= NULL;
2349
2223
  err= ib_cursor_reset(cursor);
2350
2224
  assert(err == DB_SUCCESS);
2351
2225
  in_table_scan= false;
2352
 
  return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2226
  previous_error= 0;
 
2227
  return 0;
2353
2228
}
2354
2229
 
2355
2230
int HailDBCursor::rnd_pos(unsigned char *buf, unsigned char *pos)
2363
2238
  {
2364
2239
    err= ib_col_set_value(search_tuple, 0,
2365
2240
                          ((uint64_t*)(pos)), sizeof(uint64_t));
2366
 
    if (err != DB_SUCCESS)
2367
 
      return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2368
2241
  }
2369
2242
  else
2370
2243
  {
2380
2253
  }
2381
2254
 
2382
2255
  err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
2383
 
  if (err != DB_SUCCESS)
2384
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2256
  assert(err == DB_SUCCESS);
2385
2257
 
2386
2258
  assert(res==0);
2387
2259
  if (res != 0)
2392
2264
  tuple= ib_tuple_clear(tuple);
2393
2265
 
2394
2266
  if (ret == 0)
2395
 
    ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2396
 
                              getTable(),
 
2267
    ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2397
2268
                              share->has_hidden_primary_key,
2398
2269
                              &hidden_autoinc_pkey_position);
2399
2270
 
2431
2302
      }
2432
2303
 
2433
2304
      String str;
2434
 
      field->val_str_internal(&str);
 
2305
      field->val_str(&str);
2435
2306
 
2436
2307
      *ref++= (char)(str.length() & 0x000000ff);
2437
2308
      *ref++= (char)((str.length()>>8) & 0x000000ff);
2510
2381
 
2511
2382
  if (flag & HA_STATUS_AUTO)
2512
2383
    stats.auto_increment_value= 1;
2513
 
 
2514
 
  if (flag & HA_STATUS_ERRKEY) {
2515
 
    const char *err_table_name;
2516
 
    const char *err_index_name;
2517
 
 
2518
 
    ib_trx_t transaction= *get_trx(getTable()->in_use);
2519
 
 
2520
 
    err= ib_get_duplicate_key(transaction, &err_table_name, &err_index_name);
2521
 
 
2522
 
    errkey= UINT32_MAX;
2523
 
 
2524
 
    for (unsigned int i = 0; i < getTable()->getShare()->keys; i++)
2525
 
    {
2526
 
      if (strcmp(err_index_name, getTable()->key_info[i].name) == 0)
2527
 
      {
2528
 
        errkey= i;
2529
 
        break;
2530
 
      }
2531
 
    }
2532
 
 
2533
 
  }
2534
 
 
2535
 
  if (flag & HA_STATUS_CONST)
2536
 
  {
2537
 
    for (unsigned int i = 0; i < getTable()->getShare()->sizeKeys(); i++)
2538
 
    {
2539
 
      const char* index_name= getTable()->key_info[i].name;
2540
 
      uint64_t ncols;
2541
 
      int64_t *n_diff;
2542
 
      ha_rows rec_per_key;
2543
 
 
2544
 
      err= ib_get_index_stat_n_diff_key_vals(cursor, index_name,
2545
 
                                             &ncols, &n_diff);
2546
 
 
2547
 
      if (err != DB_SUCCESS)
2548
 
        return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2549
 
 
2550
 
      for (unsigned int j=0; j < getTable()->key_info[i].key_parts; j++)
2551
 
      {
2552
 
        if (n_diff[j+1] == 0)
2553
 
          rec_per_key= stats.records;
2554
 
        else
2555
 
          rec_per_key= stats.records / n_diff[j+1];
2556
 
 
2557
 
        /* We import this heuristic from ha_innodb, which says
2558
 
           that MySQL favours table scans too much over index searches,
2559
 
           so we pretend our index selectivity is 2 times better. */
2560
 
 
2561
 
        rec_per_key= rec_per_key / 2;
2562
 
 
2563
 
        if (rec_per_key == 0)
2564
 
          rec_per_key= 1;
2565
 
 
2566
 
        getTable()->key_info[i].rec_per_key[j]=
2567
 
          rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
2568
 
          (ulong) rec_per_key;
2569
 
      }
2570
 
 
2571
 
      free(n_diff);
2572
 
    }
2573
 
  }
2574
 
 
2575
2384
  return(0);
2576
2385
}
2577
2386
 
2578
2387
int HailDBCursor::doStartIndexScan(uint32_t keynr, bool)
2579
2388
{
2580
 
  ib_err_t err;
2581
2389
  ib_trx_t transaction= *get_trx(getTable()->in_use);
2582
2390
 
2583
2391
  active_index= keynr;
2584
2392
 
 
2393
  ib_cursor_attach_trx(cursor, transaction);
 
2394
 
2585
2395
  if (active_index == 0 && ! share->has_hidden_primary_key)
2586
2396
  {
2587
 
    if (cursor_is_sec_index)
2588
 
    {
2589
 
      err= ib_cursor_close(cursor);
2590
 
      assert(err == DB_SUCCESS);
2591
 
 
2592
 
      err= ib_cursor_open_table_using_id(table_id, transaction, &cursor);
2593
 
 
2594
 
      if (err != DB_SUCCESS)
2595
 
        return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2596
 
 
2597
 
    }
2598
 
    else
2599
 
    {
2600
 
      ib_cursor_attach_trx(cursor, transaction);
2601
 
    }
2602
 
 
2603
 
    cursor_is_sec_index= false;
2604
2397
    tuple= ib_clust_read_tuple_create(cursor);
2605
2398
  }
2606
2399
  else
2607
2400
  {
 
2401
    ib_err_t err;
2608
2402
    ib_id_t index_id;
2609
2403
    err= ib_index_get_id(table_path_to_haildb_name(getShare()->getPath()),
2610
2404
                         getShare()->getKeyInfo(keynr).name,
2611
2405
                         &index_id);
2612
2406
    if (err != DB_SUCCESS)
2613
 
      return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2407
      return -1;
2614
2408
 
2615
2409
    err= ib_cursor_close(cursor);
2616
2410
    assert(err == DB_SUCCESS);
2617
 
 
2618
2411
    err= ib_cursor_open_index_using_id(index_id, transaction, &cursor);
2619
2412
 
2620
2413
    if (err != DB_SUCCESS)
2621
 
      return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2622
 
 
2623
 
    cursor_is_sec_index= true;
 
2414
      return -1;
2624
2415
 
2625
2416
    tuple= ib_clust_read_tuple_create(cursor);
2626
2417
    ib_cursor_set_cluster_access(cursor);
2627
2418
  }
2628
2419
 
2629
 
  err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
 
2420
  ib_err_t err= ib_cursor_set_lock_mode(cursor, ib_lock_mode);
2630
2421
  assert(err == DB_SUCCESS);
2631
2422
 
2632
2423
  advance_cursor= false;
2771
2562
 
2772
2563
  if (err != DB_SUCCESS)
2773
2564
  {
2774
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2565
    return ib_err_t_to_drizzle_error(err);
2775
2566
  }
2776
2567
 
2777
2568
  tuple= ib_tuple_clear(tuple);
2778
 
  ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2779
 
                            getTable(),
 
2569
  ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2780
2570
                            share->has_hidden_primary_key,
2781
2571
                            &hidden_autoinc_pkey_position,
2782
2572
                            (allocate_blobs)? &blobroot : NULL);
2853
2643
  return 0;
2854
2644
}
2855
2645
 
2856
 
int HailDBCursor::analyze(Session*)
2857
 
{
2858
 
  ib_err_t err;
2859
 
 
2860
 
  err= ib_update_table_statistics(cursor);
2861
 
 
2862
 
  return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
2863
 
}
2864
 
 
2865
2646
int HailDBCursor::index_next(unsigned char *buf)
2866
2647
{
2867
2648
  int ret= HA_ERR_END_OF_FILE;
2874
2655
  }
2875
2656
 
2876
2657
  tuple= ib_tuple_clear(tuple);
2877
 
  ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2878
 
                            getTable(),
 
2658
  ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2879
2659
                            share->has_hidden_primary_key,
2880
2660
                            &hidden_autoinc_pkey_position);
2881
2661
 
2903
2683
      if (err == DB_END_OF_INDEX)
2904
2684
        return HA_ERR_END_OF_FILE;
2905
2685
      else
2906
 
        return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2686
        return -1; // FIXME
2907
2687
    }
2908
2688
  }
2909
2689
 
2910
2690
  tuple= ib_tuple_clear(tuple);
2911
 
  ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2912
 
                            getTable(),
 
2691
  ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2913
2692
                            share->has_hidden_primary_key,
2914
2693
                            &hidden_autoinc_pkey_position);
2915
2694
 
2926
2705
 
2927
2706
  err= ib_cursor_first(cursor);
2928
2707
  if (err != DB_SUCCESS)
2929
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2708
    return ib_err_t_to_drizzle_error(err);
2930
2709
 
2931
2710
  tuple= ib_tuple_clear(tuple);
2932
 
  ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2933
 
                            getTable(),
 
2711
  ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2934
2712
                            share->has_hidden_primary_key,
2935
2713
                            &hidden_autoinc_pkey_position);
2936
2714
 
2947
2725
 
2948
2726
  err= ib_cursor_last(cursor);
2949
2727
  if (err != DB_SUCCESS)
2950
 
    return ib_err_t_to_drizzle_error(getTable()->getSession(), err);
 
2728
    return ib_err_t_to_drizzle_error(err);
2951
2729
 
2952
2730
  tuple= ib_tuple_clear(tuple);
2953
 
  ret= read_row_from_haildb(getTable()->getSession(), buf, cursor, tuple,
2954
 
                            getTable(),
 
2731
  ret= read_row_from_haildb(buf, cursor, tuple, getTable(),
2955
2732
                            share->has_hidden_primary_key,
2956
2733
                            &hidden_autoinc_pkey_position);
2957
2734
  advance_cursor= true;
3144
2921
  bool r= false;
3145
2922
  va_list args;
3146
2923
  va_start(args, fmt);
3147
 
  if (not shutdown_in_progress)
3148
 
  {
3149
 
    r= plugin::ErrorMessage::vprintf(error::WARN, fmt, args);
3150
 
  }
 
2924
  if (! shutdown_in_progress)
 
2925
    r= plugin::ErrorMessage::vprintf(NULL, ERRMSG_LVL_WARN, fmt, args);
3151
2926
  else
3152
 
  {
3153
2927
    vfprintf(stderr, fmt, args);
3154
 
  }
3155
2928
  va_end(args);
3156
2929
 
3157
2930
  return (! r==true);
3536
3309
  "Transactional Storage Engine using the HailDB Library",
3537
3310
  PLUGIN_LICENSE_GPL,
3538
3311
  haildb_init,     /* Plugin Init */
3539
 
  NULL, /* depends */
 
3312
  NULL, /* system variables */
3540
3313
  init_options                /* config options   */
3541
3314
}
3542
3315
DRIZZLE_DECLARE_PLUGIN_END;