~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/embedded_innodb/embedded_innodb_engine.cc

Merge Stewart.

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
Copyright (c) 2008, 2009 Google Inc.
26
26
 
27
27
Portions of this file contain modifications contributed and copyrighted by
28
 
Google, Inc. Those modifications are gratefully acknowledged and are described
 
28
staticGoogle, Inc. Those modifications are gratefully acknowledged and are described
29
29
briefly in the InnoDB documentation. The contributions by Google are
30
30
incorporated with their permission, and subject to the conditions contained in
31
31
the file COPYING.Google.
98
98
 
99
99
#include <drizzled/field.h>
100
100
#include "drizzled/field/timestamp.h" // needed for UPDATE NOW()
 
101
#include "drizzled/field/blob.h"
101
102
#include <drizzled/session.h>
102
103
 
103
104
using namespace std;
104
105
using namespace google;
105
106
using namespace drizzled;
106
107
 
107
 
int read_row_from_innodb(unsigned char* buf, ib_crsr_t cursor, ib_tpl_t tuple, Table* table, bool has_hidden_primary_key, uint64_t *hidden_pkey);
 
108
int read_row_from_innodb(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);
108
109
static void fill_ib_search_tpl_from_drizzle_key(ib_tpl_t search_tuple,
109
110
                                                const drizzled::KeyInfo *key_info,
110
111
                                                const unsigned char *key_ptr,
590
591
EmbeddedInnoDBCursor::EmbeddedInnoDBCursor(drizzled::plugin::StorageEngine &engine_arg,
591
592
                           TableShare &table_arg)
592
593
  :Cursor(engine_arg, table_arg),
593
 
   write_can_replace(false)
 
594
   write_can_replace(false),
 
595
   blobroot(NULL)
594
596
{ }
595
597
 
596
598
int EmbeddedInnoDBCursor::open(const char *name, int, uint32_t)
618
620
    ref_length= 0; // FIXME: this is a bug. we need to work out what index it is.
619
621
  }
620
622
 
 
623
  in_table_scan= false;
 
624
 
621
625
  return(0);
622
626
}
623
627
 
629
633
 
630
634
  free_share();
631
635
 
 
636
  delete blobroot;
 
637
  blobroot= NULL;
 
638
 
632
639
  return 0;
633
640
}
634
641
 
683
690
    *err= ib_table_schema_add_col(schema, field.name().c_str(), IB_INT,
684
691
                                  column_attr, 0, 4);
685
692
    break;
686
 
 
 
693
  case message::Table::Field::BLOB:
 
694
    *err= ib_table_schema_add_col(schema, field.name().c_str(), IB_BLOB,
 
695
                                  column_attr, 0, 0);
 
696
    break;
687
697
  default:
688
698
    my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "Column Type");
689
699
    return(HA_ERR_UNSUPPORTED);
1449
1459
      (**field).setReadSet();
1450
1460
      err= ib_tuple_write_u32(tuple, colnr, (*field)->val_int());
1451
1461
    }
 
1462
    else if ((**field).type() == DRIZZLE_TYPE_BLOB)
 
1463
    {
 
1464
      Field_blob *blob= reinterpret_cast<Field_blob*>(*field);
 
1465
      unsigned char* blob_ptr;
 
1466
      uint32_t blob_length= blob->get_length();
 
1467
      blob->get_ptr(&blob_ptr);
 
1468
      err= ib_col_set_value(tuple, colnr, blob_ptr, blob_length);
 
1469
    }
1452
1470
    else
1453
1471
    {
1454
1472
      err= ib_col_set_value(tuple, colnr, (*field)->ptr, (*field)->data_length());
1623
1641
  ib_tpl_t update_tuple;
1624
1642
  ib_err_t err;
1625
1643
 
1626
 
  err= ib_cursor_prev(cursor);
1627
 
  assert (err == DB_SUCCESS);
1628
 
 
1629
1644
  update_tuple= ib_clust_read_tuple_create(cursor);
1630
1645
 
1631
1646
  err= ib_tuple_copy(update_tuple, tuple);
1639
1654
  err= ib_cursor_update_row(cursor, tuple, update_tuple);
1640
1655
 
1641
1656
  ib_tuple_delete(update_tuple);
1642
 
  ib_err_t err2= ib_cursor_next(cursor);
1643
 
  (void)err2;
 
1657
 
 
1658
  advance_cursor= true;
1644
1659
 
1645
1660
  if (err == DB_SUCCESS)
1646
1661
    return 0;
1654
1669
{
1655
1670
  ib_err_t err;
1656
1671
 
1657
 
  err= ib_cursor_prev(cursor);
1658
 
  assert (err == DB_SUCCESS);
1659
 
 
1660
1672
  err= ib_cursor_delete_row(cursor);
1661
1673
  if (err != DB_SUCCESS)
1662
1674
    return -1; // FIXME
1663
1675
 
1664
 
  err= ib_cursor_next(cursor);
1665
 
  if (err != DB_SUCCESS && err != DB_END_OF_INDEX)
1666
 
    return -1; // FIXME
 
1676
  advance_cursor= true;
1667
1677
  return 0;
1668
1678
}
1669
1679
 
1724
1734
{
1725
1735
  ib_trx_t transaction;
1726
1736
 
 
1737
  if (in_table_scan)
 
1738
    doEndTableScan();
 
1739
  in_table_scan= true;
 
1740
 
1727
1741
  if(*get_trx(current_session) == NULL)
1728
1742
  {
1729
1743
    EmbeddedInnoDBEngine *innodb_engine= static_cast<EmbeddedInnoDBEngine*>(engine);
1740
1754
  if (err != DB_SUCCESS && err != DB_END_OF_INDEX)
1741
1755
    return -1; // FIXME
1742
1756
 
 
1757
  advance_cursor= false;
 
1758
 
1743
1759
  return(0);
1744
1760
}
1745
1761
 
1746
 
int read_row_from_innodb(unsigned char* buf, ib_crsr_t cursor, ib_tpl_t tuple, Table* table, bool has_hidden_primary_key, uint64_t *hidden_pkey)
 
1762
int read_row_from_innodb(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)
1747
1763
{
1748
1764
  ib_err_t err;
1749
1765
  ptrdiff_t row_offset= buf - table->record[0];
1755
1771
 
1756
1772
  int colnr= 0;
1757
1773
 
 
1774
  /* We need the primary key for ::position() to work */
 
1775
  if (table->s->primary_key != MAX_KEY)
 
1776
    table->mark_columns_used_by_index_no_reset(table->s->primary_key);
 
1777
 
1758
1778
  for (Field **field=table->field ; *field ; field++, colnr++)
1759
1779
  {
1760
1780
    if (! (**field).isReadSet())
1785
1805
      err= ib_tuple_read_u32(tuple, colnr, &date_read);
1786
1806
      (*field)->store(date_read);
1787
1807
    }
 
1808
    else if ((**field).type() == DRIZZLE_TYPE_BLOB)
 
1809
    {
 
1810
      if (blobroot == NULL)
 
1811
        (reinterpret_cast<Field_blob*>(*field))->set_ptr(length,
 
1812
                                      (unsigned char*)ib_col_get_value(tuple,
 
1813
                                                                       colnr));
 
1814
      else
 
1815
      {
 
1816
        if (*blobroot == NULL)
 
1817
        {
 
1818
          *blobroot= new drizzled::memory::Root();
 
1819
          (**blobroot).init_alloc_root();
 
1820
        }
 
1821
 
 
1822
        unsigned char *blob_ptr= (unsigned char*)(**blobroot).alloc_root(length);
 
1823
        memcpy(blob_ptr, ib_col_get_value(tuple, colnr), length);
 
1824
        (reinterpret_cast<Field_blob*>(*field))->set_ptr(length, blob_ptr);
 
1825
      }
 
1826
    }
1788
1827
    else
1789
1828
    {
1790
1829
      ib_col_copy_value(tuple, colnr, (*field)->ptr, (*field)->data_length());
1807
1846
  ib_err_t err;
1808
1847
  int ret;
1809
1848
 
 
1849
  if (advance_cursor)
 
1850
    err= ib_cursor_next(cursor);
 
1851
 
1810
1852
  tuple= ib_tuple_clear(tuple);
1811
1853
  ret= read_row_from_innodb(buf, cursor, tuple, table,
1812
1854
                            share->has_hidden_primary_key,
1813
1855
                            &hidden_autoinc_pkey_position);
1814
1856
 
1815
 
  err= ib_cursor_next(cursor);
1816
 
 
 
1857
  advance_cursor= true;
1817
1858
  return ret;
1818
1859
}
1819
1860
 
1824
1865
  ib_tuple_delete(tuple);
1825
1866
  err= ib_cursor_reset(cursor);
1826
1867
  assert(err == DB_SUCCESS);
1827
 
 
 
1868
  in_table_scan= false;
1828
1869
  return 0;
1829
1870
}
1830
1871
 
1832
1873
{
1833
1874
  ib_err_t err;
1834
1875
  int res;
1835
 
  int ret;
 
1876
  int ret= 0;
1836
1877
  ib_tpl_t search_tuple= ib_clust_search_tuple_create(cursor);
1837
1878
 
1838
1879
  if (share->has_hidden_primary_key)
1839
1880
  {
1840
 
    err= ib_col_set_value(search_tuple, 0, ((uint64_t*)(ref)), sizeof(uint64_t));
 
1881
    err= ib_col_set_value(search_tuple, 0,
 
1882
                          ((uint64_t*)(pos)), sizeof(uint64_t));
1841
1883
  }
1842
1884
  else
1843
1885
  {
1848
1890
 
1849
1891
  err= ib_cursor_moveto(cursor, search_tuple, IB_CUR_GE, &res);
1850
1892
  assert(err == DB_SUCCESS);
 
1893
 
 
1894
  assert(res==0);
 
1895
  if (res != 0)
 
1896
    ret= -1;
 
1897
 
1851
1898
  ib_tuple_delete(search_tuple);
1852
1899
 
1853
1900
  tuple= ib_tuple_clear(tuple);
1854
 
  ret= read_row_from_innodb(buf, cursor, tuple, table,
1855
 
                            share->has_hidden_primary_key,
1856
 
                            &hidden_autoinc_pkey_position);
1857
 
 
1858
 
  err= ib_cursor_next(cursor);
1859
 
 
1860
 
  return(0);
 
1901
 
 
1902
  if (ret == 0)
 
1903
    ret= read_row_from_innodb(buf, cursor, tuple, table,
 
1904
                              share->has_hidden_primary_key,
 
1905
                              &hidden_autoinc_pkey_position);
 
1906
 
 
1907
  advance_cursor= true;
 
1908
 
 
1909
  return(ret);
1861
1910
}
1862
1911
 
1863
1912
static void store_key_value_from_innodb(KeyInfo *key_info, unsigned char* ref, int ref_len, const unsigned char *record)
1944
1993
  ib_trx_t transaction= *get_trx(ha_session());
1945
1994
 
1946
1995
  active_index= keynr;
1947
 
  next_innodb_error= DB_SUCCESS;
1948
1996
 
1949
1997
  ib_cursor_attach_trx(cursor, transaction);
1950
1998
 
1972
2020
    ib_cursor_set_cluster_access(cursor);
1973
2021
  }
1974
2022
 
 
2023
  advance_cursor= false;
1975
2024
  return 0;
1976
2025
}
1977
2026
 
2079
2128
  assert(buff == key_ptr + key_len);
2080
2129
}
2081
2130
 
2082
 
int EmbeddedInnoDBCursor::index_read(unsigned char *buf,
2083
 
                                     const unsigned char *key_ptr,
2084
 
                                     uint32_t key_len,
2085
 
                                     drizzled::ha_rkey_function find_flag)
 
2131
int EmbeddedInnoDBCursor::innodb_index_read(unsigned char *buf,
 
2132
                                            const unsigned char *key_ptr,
 
2133
                                            uint32_t key_len,
 
2134
                                            drizzled::ha_rkey_function find_flag,
 
2135
                                            bool allocate_blobs)
2086
2136
{
2087
2137
  ib_tpl_t search_tuple;
2088
2138
  int res;
2104
2154
  err= ib_cursor_moveto(cursor, search_tuple, search_mode, &res);
2105
2155
  ib_tuple_delete(search_tuple);
2106
2156
 
2107
 
  if (err == DB_RECORD_NOT_FOUND)
2108
 
    return HA_ERR_END_OF_FILE;
 
2157
  if ((err == DB_RECORD_NOT_FOUND || err == DB_END_OF_INDEX))
 
2158
  {
 
2159
    table->status= STATUS_NOT_FOUND;
 
2160
    return HA_ERR_KEY_NOT_FOUND;
 
2161
  }
 
2162
 
 
2163
  assert(err==DB_SUCCESS);
2109
2164
 
2110
2165
  tuple= ib_tuple_clear(tuple);
2111
2166
  ret= read_row_from_innodb(buf, cursor, tuple, table,
2112
2167
                            share->has_hidden_primary_key,
2113
 
                            &hidden_autoinc_pkey_position);
2114
 
  err= ib_cursor_next(cursor);
 
2168
                            &hidden_autoinc_pkey_position,
 
2169
                            (allocate_blobs)? &blobroot : NULL);
 
2170
  if (ret == 0)
 
2171
    table->status= 0;
 
2172
  else
 
2173
    table->status= STATUS_NOT_FOUND;
 
2174
 
 
2175
  advance_cursor= true;
 
2176
 
 
2177
  return ret;
 
2178
}
 
2179
 
 
2180
int EmbeddedInnoDBCursor::index_read(unsigned char *buf,
 
2181
                                     const unsigned char *key_ptr,
 
2182
                                     uint32_t key_len,
 
2183
                                     drizzled::ha_rkey_function find_flag)
 
2184
{
 
2185
  return innodb_index_read(buf, key_ptr, key_len, find_flag, false);
 
2186
}
 
2187
 
 
2188
/* This is straight from cursor.cc, but it's private there :( */
 
2189
uint32_t EmbeddedInnoDBCursor::calculate_key_len(uint32_t key_position,
 
2190
                                                 key_part_map keypart_map_arg)
 
2191
{
 
2192
  /* works only with key prefixes */
 
2193
  assert(((keypart_map_arg + 1) & keypart_map_arg) == 0);
 
2194
 
 
2195
  KeyInfo *key_info_found= table->s->key_info + key_position;
 
2196
  KeyPartInfo *key_part_found= key_info_found->key_part;
 
2197
  KeyPartInfo *end_key_part_found= key_part_found + key_info_found->key_parts;
 
2198
  uint32_t length= 0;
 
2199
 
 
2200
  while (key_part_found < end_key_part_found && keypart_map_arg)
 
2201
  {
 
2202
    length+= key_part_found->store_length;
 
2203
    keypart_map_arg >>= 1;
 
2204
    key_part_found++;
 
2205
  }
 
2206
  return length;
 
2207
}
 
2208
 
 
2209
 
 
2210
int EmbeddedInnoDBCursor::innodb_index_read_map(unsigned char * buf,
 
2211
                                                const unsigned char *key,
 
2212
                                                key_part_map keypart_map,
 
2213
                                                enum ha_rkey_function find_flag,
 
2214
                                                bool allocate_blobs)
 
2215
{
 
2216
  uint32_t key_len= calculate_key_len(active_index, keypart_map);
 
2217
  return  innodb_index_read(buf, key, key_len, find_flag, allocate_blobs);
 
2218
}
 
2219
 
 
2220
int EmbeddedInnoDBCursor::index_read_idx_map(unsigned char * buf,
 
2221
                                             uint32_t index,
 
2222
                                             const unsigned char * key,
 
2223
                                             key_part_map keypart_map,
 
2224
                                             enum ha_rkey_function find_flag)
 
2225
{
 
2226
  int error, error1;
 
2227
  error= doStartIndexScan(index, 0);
 
2228
  if (!error)
 
2229
  {
 
2230
    error= innodb_index_read_map(buf, key, keypart_map, find_flag, true);
 
2231
    error1= doEndIndexScan();
 
2232
  }
 
2233
  return error ?  error : error1;
 
2234
}
 
2235
 
 
2236
int EmbeddedInnoDBCursor::reset()
 
2237
{
 
2238
  if (blobroot)
 
2239
    blobroot->free_root(MYF(0));
2115
2240
 
2116
2241
  return 0;
2117
2242
}
2120
2245
{
2121
2246
  int ret= HA_ERR_END_OF_FILE;
2122
2247
 
2123
 
  if (next_innodb_error == DB_END_OF_INDEX)
2124
 
    return HA_ERR_END_OF_FILE;
 
2248
  if (advance_cursor)
 
2249
  {
 
2250
    ib_err_t err= ib_cursor_next(cursor);
 
2251
    if (err == DB_END_OF_INDEX)
 
2252
      return HA_ERR_END_OF_FILE;
 
2253
  }
2125
2254
 
2126
2255
  tuple= ib_tuple_clear(tuple);
2127
2256
  ret= read_row_from_innodb(buf, cursor, tuple, table,
2128
2257
                            share->has_hidden_primary_key,
2129
2258
                            &hidden_autoinc_pkey_position);
2130
 
  next_innodb_error= ib_cursor_next(cursor);
2131
2259
 
 
2260
  advance_cursor= true;
2132
2261
  return ret;
2133
2262
}
2134
2263
 
2144
2273
  int ret= HA_ERR_END_OF_FILE;
2145
2274
  ib_err_t err;
2146
2275
 
 
2276
  if (advance_cursor)
 
2277
    err= ib_cursor_prev(cursor);
 
2278
 
2147
2279
  if (active_index == 0)
2148
2280
  {
2149
2281
    tuple= ib_tuple_clear(tuple);
2150
2282
    ret= read_row_from_innodb(buf, cursor, tuple, table,
2151
2283
                              share->has_hidden_primary_key,
2152
2284
                              &hidden_autoinc_pkey_position);
2153
 
    err= ib_cursor_prev(cursor);
2154
2285
  }
2155
2286
 
 
2287
  advance_cursor= true;
 
2288
 
2156
2289
  return ret;
2157
2290
}
2158
2291
 
2175
2308
  ret= read_row_from_innodb(buf, cursor, tuple, table,
2176
2309
                            share->has_hidden_primary_key,
2177
2310
                            &hidden_autoinc_pkey_position);
2178
 
  next_innodb_error= ib_cursor_next(cursor);
 
2311
 
 
2312
  advance_cursor= true;
2179
2313
 
2180
2314
  return ret;
2181
2315
}
2201
2335
    ret= read_row_from_innodb(buf, cursor, tuple, table,
2202
2336
                              share->has_hidden_primary_key,
2203
2337
                              &hidden_autoinc_pkey_position);
2204
 
    err= ib_cursor_prev(cursor);
 
2338
    advance_cursor= true;
2205
2339
  }
2206
2340
 
2207
2341
  return ret;
2211
2345
{
2212
2346
  switch (operation)
2213
2347
  {
 
2348
  case HA_EXTRA_FLUSH:
 
2349
    if (blobroot)
 
2350
      blobroot->free_root(MYF(0));
 
2351
    break;
2214
2352
  case HA_EXTRA_WRITE_CAN_REPLACE:
2215
2353
    write_can_replace= true;
2216
2354
    break;