Merge lp:~posulliv/drizzle/simple-tc-engine into lp:~drizzle-trunk/drizzle/development

Proposed by Padraig O'Sullivan
Status: Rejected
Rejected by: Padraig O'Sullivan
Proposed branch: lp:~posulliv/drizzle/simple-tc-engine
Merge into: lp:~drizzle-trunk/drizzle/development
Diff against target: 1515 lines
14 files modified
plugin/tokyo_cabinet_engine/open_tables.cc (+76/-0)
plugin/tokyo_cabinet_engine/open_tables.h (+92/-0)
plugin/tokyo_cabinet_engine/plugin.ac (+8/-0)
plugin/tokyo_cabinet_engine/plugin.ini (+12/-0)
plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.cc (+71/-0)
plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.h (+73/-0)
plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.cc (+221/-0)
plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.h (+140/-0)
plugin/tokyo_cabinet_engine/tokyo_cabinet_share.cc (+240/-0)
plugin/tokyo_cabinet_engine/tokyo_cabinet_share.h (+219/-0)
tests/suite/tc_engine/r/auto_increment.result (+32/-0)
tests/suite/tc_engine/r/basic.result (+138/-0)
tests/suite/tc_engine/t/auto_increment.test (+13/-0)
tests/suite/tc_engine/t/basic.test (+107/-0)
To merge this branch: bzr merge lp:~posulliv/drizzle/simple-tc-engine
Reviewer Review Type Date Requested Status
Stewart Smith (community) Needs Information
Review via email: mp+12323@code.launchpad.net
To post a comment you must log in.
Revision history for this message
Padraig O'Sullivan (posulliv) wrote :

This merge proposal consists of a simple in-memory storage engine that uses the Tokyo Cabinet in-memory hash API. It also includes a very lacking test suite with 2 small test files for the storage engine. Since this proposal is a little bit out of nowhere and you are probably wondering why the heck I did this, let me explain why I did it...

I'm taking a distributed systems class this semester for fun which will involve a project. I've managed to get a project involving Drizzle approved. What I plan on doing is investigating how to use cloud storage services (such as S3) as the storage backend for a SQL engine (which will be drizzle) and how to implement various consistency protocols over an eventually consistent data store such as S3. Since S3 is basically a key/value store (as described in the Dynamo paper), I wanted to get some practice creating a storage engine using a key/value store interface. Thus, I found Brian's posting on a Tokyo Cabinet based storage engine from a while back and went with that. I ported it to Drizzle and modified it to use the in-memory API calls from Tokyo Cabinet for the heck of it. This will help me in getting my basic S3 storage engine working in the next few weeks as I now have a good idea of how to create a storage engine using a key/value store interface.

I wasn't sure what to do with this engine, so I figured I'd propose it for merging. I also remember Brian's post about a new memory engine so I thought this might make a good start. I'm open to giving this over to someone. I was also under the impression this doesn't really conflict with BlitzDB. From what I understand about BlitzDB, its aimed at being a more general purpose storage engine but then again, maybe I should give this to Toru and he can do what he likes with it.

Anyway, any comments are more than welcome. If no-one is interested in this, or it doesn't prove very useful, well then this proposal can be ignored :) It was good practice for working with a key/value store for me! Alternatively, if there is interest, I can work on it more in my spare time to make it a better in-memory engine if that is desirable.

-Padraig

Revision history for this message
Brian Aker (brianaker) wrote :

Hi!

Yep, we need a new in-memory engine. I can't really judge whether TC would work well for in-memory or not (we need to study up the analytics around this... aka benchmark).

My personal thought? No harm in doing it, and I suspect it will be no worse then the current engine (might even be an improvement...). Is it the final engine? I have my doubts mainly because of concurrency issues. You can certainly learn the interface this way, and... most likely this would be useful for others.

Cheers,
   -Brian

Revision history for this message
Stewart Smith (stewart) wrote :

On Fri, Sep 25, 2009 at 04:45:48AM -0000, Brian Aker wrote:
> Hi!
>
> Yep, we need a new in-memory engine. I can't really judge whether TC
> would work well for in-memory or not (we need to study up the analytics
> around this... aka benchmark).
>
> My personal thought? No harm in doing it, and I suspect it will be no
> worse then the current engine (might even be an improvement...). Is it
> the final engine? I have my doubts mainly because of concurrency issues.
> You can certainly learn the interface this way, and... most likely this
> would be useful for others.

I also really like the idea of maintaining an engine with a clear
boundary between engine API and storage engine code as all of our
existing engines are a bit muddy there and/or rather complex.

--
Stewart Smith

Revision history for this message
Stewart Smith (stewart) wrote :

the delete table paths seem to be a bit strange. it looks like you're deleting it on the close of the last tableshare, although the proper way would be to do it when explicitly called to remove the table (and check exists/not exists).

If you wanted to be fancy and demo the data dictionary APIs, you could have a (on disk) tc db of table names with the data being the table proto.

review: Needs Information

Unmerged revisions

1155. By Padraig O'Sullivan

Merge from trunk.

1154. By Padraig O'Sullivan

Added some more doxygen comments.

1153. By Padraig O'Sullivan

Updated plugin main file to have the authors reflected accurately. Included
Brian and Stewart since I based this engine off the tokyo cabinet engine
they did.

1152. By Padraig O'Sullivan

Converted the engine to an in-memory engine. It would be quite trivial to
create an option which lets the engine operate in memory or on disk. We
could even support having tables of both types at the same time. However, I
don't see why you would need a disk-based storage engine when you have
InnoDB?

1151. By Padraig O'Sullivan

Added some doxygen comments and updated the plugin.ini file to indicate that
a test suite is available for this plugin. Thus, the test suite will get run
when 'make test' issued.

1150. By Padraig O'Sullivan

Tiny modification based on valgrind output.

1149. By Padraig O'Sullivan

Updating the flags based to the tokyo cabinet based storage engine so that
altering of tables is supported.

1148. By Padraig O'Sullivan

Corrected the way tables are updated. Update statements now work correctly.

1147. By Padraig O'Sullivan

Added support for deleting a row in the storage engine.

1146. By Padraig O'Sullivan

Added support for storing rows of non-fixed length to the storage engine.
Updates to rows which store blobs still don't work correctly but we are
making some progress.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== added directory 'plugin/tokyo_cabinet_engine'
2=== added file 'plugin/tokyo_cabinet_engine/open_tables.cc'
3--- plugin/tokyo_cabinet_engine/open_tables.cc 1970-01-01 00:00:00 +0000
4+++ plugin/tokyo_cabinet_engine/open_tables.cc 2009-09-24 03:50:23 +0000
5@@ -0,0 +1,76 @@
6+/*
7+ * Copyright (C) 2009 Sun Microsystems
8+ *
9+ * This program is free software; you can redistribute it and/or modify
10+ * it under the terms of the GNU General Public License as published by
11+ * the Free Software Foundation; either version 2 of the License, or
12+ * (at your option) any later version.
13+ *
14+ * This program is distributed in the hope that it will be useful,
15+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
16+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+ * GNU General Public License for more details.
18+ *
19+ * You should have received a copy of the GNU General Public License
20+ * along with this program; if not, write to the Free Software
21+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
22+ */
23+
24+#include <drizzled/server_includes.h>
25+#include "tokyo_cabinet_handler.h"
26+#include "open_tables.h"
27+
28+#include <string>
29+#include <map>
30+
31+using namespace std;
32+using namespace drizzled;
33+
34+TokyoCabinetShare *OpenTables::getShare(const string &name)
35+{
36+ map<const string, TokyoCabinetShare *>::iterator it;
37+ pthread_mutex_lock(&mutex);
38+
39+ it= open_tables.find(name);
40+ if (it != open_tables.end())
41+ {
42+ share= (*it).second;
43+ }
44+ else
45+ {
46+ share= NULL;
47+ }
48+
49+ if (! share)
50+ {
51+ share= new(std::nothrow) TokyoCabinetShare(name);
52+ if (! share)
53+ {
54+ pthread_mutex_unlock(&mutex);
55+ return NULL;
56+ }
57+ if (! share->openTable())
58+ {
59+ delete share;
60+ return NULL;
61+ }
62+ open_tables[name]= share;
63+ share->initThreadLock();
64+ }
65+ share->incUseCount();
66+ pthread_mutex_unlock(&mutex);
67+
68+ return share;
69+}
70+
71+void OpenTables::freeShare()
72+{
73+ pthread_mutex_lock(&mutex);
74+ share->decUseCount();
75+ if (share->getUseCount() == 0)
76+ {
77+ share->freeDatabaseHandler();
78+ open_tables.erase(share->getName());
79+ }
80+ pthread_mutex_unlock(&mutex);
81+}
82
83=== added file 'plugin/tokyo_cabinet_engine/open_tables.h'
84--- plugin/tokyo_cabinet_engine/open_tables.h 1970-01-01 00:00:00 +0000
85+++ plugin/tokyo_cabinet_engine/open_tables.h 2009-09-24 03:50:23 +0000
86@@ -0,0 +1,92 @@
87+/*
88+ * Copyright (C) 2009 Sun Microsystems
89+ *
90+ * This program is free software; you can redistribute it and/or modify
91+ * it under the terms of the GNU General Public License as published by
92+ * the Free Software Foundation; version 2 of the License.
93+ *
94+ * This program is distributed in the hope that it will be useful,
95+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
96+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
97+ * GNU General Public License for more details.
98+ *
99+ * You should have received a copy of the GNU General Public License
100+ * along with this program; if not, write to the Free Software
101+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
102+ */
103+
104+/**
105+ * @file
106+ *
107+ * Defines a class for how open tables will be tracked for this storage
108+ * engine.
109+ */
110+
111+#ifndef DRIZZLE_PLUGIN_TOKYO_ENGINE_OPEN_TABLES_H
112+#define DRIZZLE_PLUGIN_TOKYO_ENGINE_OPEN_TABLES_H
113+
114+#include "tokyo_cabinet_handler.h"
115+
116+#include <string>
117+#include <vector>
118+#include <map>
119+
120+/**
121+ * @class OpenTables
122+ *
123+ * Class which tracks all the open tables for the storage engine.
124+ * Encapsulating this functionality in a class will make it easier for us to
125+ * change things such as whether a std::map or HASH is used to lookup the
126+ * open tables.
127+ */
128+class OpenTables
129+{
130+public:
131+
132+ static OpenTables &singleton()
133+ {
134+ static OpenTables open_tabs;
135+ return open_tabs;
136+ }
137+
138+ /**
139+ * Retrieve a share from the structure used to main the list of open
140+ * shares. We do a lookup by name.
141+ *
142+ * @param[in] name name to lookup
143+ * @return pointer to the appropriate table share
144+ */
145+ TokyoCabinetShare *getShare(const std::string &name);
146+
147+ /**
148+ * Erase a share from the structure used to maintain the list of shares.
149+ */
150+ void freeShare();
151+
152+private:
153+
154+ pthread_mutex_t mutex;
155+
156+ std::map<const std::string, TokyoCabinetShare *>
157+ open_tables;
158+
159+ TokyoCabinetShare *share;
160+
161+ OpenTables()
162+ :
163+ mutex(),
164+ open_tables(),
165+ share(NULL)
166+ {
167+ pthread_mutex_init(&mutex, MY_MUTEX_INIT_FAST);
168+ }
169+
170+ ~OpenTables()
171+ {
172+ pthread_mutex_destroy(&mutex);
173+ }
174+
175+ OpenTables(const OpenTables&);
176+};
177+
178+#endif /* DRIZZLE_PLUGIN_TOKYO_ENGINE_OPEN_TABLES_H */
179
180=== added file 'plugin/tokyo_cabinet_engine/plugin.ac'
181--- plugin/tokyo_cabinet_engine/plugin.ac 1970-01-01 00:00:00 +0000
182+++ plugin/tokyo_cabinet_engine/plugin.ac 2009-09-24 03:50:23 +0000
183@@ -0,0 +1,8 @@
184+AC_LIB_HAVE_LINKFLAGS(tokyocabinet,,
185+ [#include <tchdb.h>],
186+ [
187+ TCHDB hdb;
188+ ])
189+ AS_IF([test "x$ac_cv_libtokyocabinet" = "xno"],
190+ AC_MSG_WARN([tokyocabinet not found: not building TokyoCabinet engine.]))
191+DRIZZLED_PLUGIN_DEP_LIBS="${DRIZZLED_PLUGIN_DEP_LIBS} ${LTLIBTOKYOCABINET}"
192
193=== added file 'plugin/tokyo_cabinet_engine/plugin.ini'
194--- plugin/tokyo_cabinet_engine/plugin.ini 1970-01-01 00:00:00 +0000
195+++ plugin/tokyo_cabinet_engine/plugin.ini 2009-09-24 03:50:23 +0000
196@@ -0,0 +1,12 @@
197+[plugin]
198+name=tokyo_cabinet_engine
199+title=Tokyo Cabinet Storage Engine
200+description=A Tokyo Cabinet Based Storage Engine
201+load_by_default= yes
202+sources=tokyo_cabinet_engine.cc tokyo_cabinet_handler.cc open_tables.cc
203+ tokyo_cabinet_share.cc
204+headers=tokyo_cabinet_engine.h tokyo_cabinet_handler.h open_tables.h
205+ tokyo_cabinet_share.h
206+build_conditional="${ac_cv_libtokyocabinet}" = "yes"
207+ldflags=${LTLIBTOKYOCABINET}
208+testsuite=tc_engine
209
210=== added file 'plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.cc'
211--- plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.cc 1970-01-01 00:00:00 +0000
212+++ plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.cc 2009-09-24 03:50:23 +0000
213@@ -0,0 +1,71 @@
214+/*
215+ * Copyright (C) 2009 Sun Microsystems
216+ *
217+ * This program is free software; you can redistribute it and/or modify
218+ * it under the terms of the GNU General Public License as published by
219+ * the Free Software Foundation; either version 2 of the License, or
220+ * (at your option) any later version.
221+ *
222+ * This program is distributed in the hope that it will be useful,
223+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
224+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
225+ * GNU General Public License for more details.
226+ *
227+ * You should have received a copy of the GNU General Public License
228+ * along with this program; if not, write to the Free Software
229+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
230+ */
231+
232+#include <drizzled/server_includes.h>
233+#include <drizzled/show.h>
234+#include "tokyo_cabinet_engine.h"
235+#include "tokyo_cabinet_handler.h"
236+#include "open_tables.h"
237+
238+#include <string>
239+#include <map>
240+
241+using namespace std;
242+using namespace drizzled;
243+
244+static const string engine_name("Tokyo");
245+static StorageEngine *tokyo_cabinet_engine= NULL;
246+
247+static int init(plugin::Registry &registry)
248+{
249+ tokyo_cabinet_engine= new(std::nothrow) TokyoCabinetEngine(engine_name);
250+ if (! tokyo_cabinet_engine)
251+ {
252+ return true;
253+ }
254+
255+ /* we are good to go */
256+ registry.add(tokyo_cabinet_engine);
257+
258+ return false;
259+}
260+
261+static int deinit(plugin::Registry &registry)
262+{
263+ if (tokyo_cabinet_engine)
264+ {
265+ registry.remove(tokyo_cabinet_engine);
266+ delete tokyo_cabinet_engine;
267+ }
268+ return false;
269+}
270+
271+drizzle_declare_plugin(tokyo_cabinet_engine)
272+{
273+ "tokyo_cabinet_engine",
274+ "0.1",
275+ "Padraig O'Sullivan, Brian Aker, Stewart Smith",
276+ "Simple In-Memory Tokyo Cabinet Storage Engine",
277+ PLUGIN_LICENSE_GPL,
278+ init, /* Plugin Init */
279+ deinit, /* Plugin Deinit */
280+ NULL, /* status variables */
281+ NULL, /* system variables */
282+ NULL /* config options */
283+}
284+drizzle_declare_plugin_end;
285
286=== added file 'plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.h'
287--- plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.h 1970-01-01 00:00:00 +0000
288+++ plugin/tokyo_cabinet_engine/tokyo_cabinet_engine.h 2009-09-24 03:50:23 +0000
289@@ -0,0 +1,73 @@
290+/*
291+ * Copyright (C) 2009 Sun Microsystems
292+ *
293+ * This program is free software; you can redistribute it and/or modify
294+ * it under the terms of the GNU General Public License as published by
295+ * the Free Software Foundation; either version 2 of the License, or
296+ * (at your option) any later version.
297+ *
298+ * This program is distributed in the hope that it will be useful,
299+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
300+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
301+ * GNU General Public License for more details.
302+ *
303+ * You should have received a copy of the GNU General Public License
304+ * along with this program; if not, write to the Free Software
305+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
306+ */
307+
308+/**
309+ * @file
310+ *
311+ * Declares the class that will represent this storage engine.
312+ */
313+
314+#ifndef DRIZZLE_PLUGIN_TOKYO_CABINET_ENGINE_H
315+#define DRIZZLE_PLUGIN_TOKYO_CABINET_ENGINE_H
316+
317+#include <drizzled/error.h>
318+#include "tokyo_cabinet_handler.h"
319+
320+#include <string>
321+
322+class TokyoCabinetEngine : public StorageEngine
323+{
324+public:
325+
326+ TokyoCabinetEngine(const std::string &in_name)
327+ :
328+ StorageEngine(in_name,
329+ HTON_CAN_RECREATE)
330+ {}
331+
332+ ~TokyoCabinetEngine() {}
333+
334+ virtual handler *create(TableShare *table,
335+ MEM_ROOT *mem_root)
336+ {
337+ return new(mem_root) TokyoCabinetHandler(this, table);
338+ }
339+
340+ const char **bas_ext() const
341+ {
342+ return NULL;
343+ }
344+
345+ int createTableImplementation(Session *,
346+ const char *,
347+ Table *,
348+ HA_CREATE_INFO *,
349+ drizzled::message::Table *)
350+ {
351+ return 0;
352+ }
353+
354+ int deleteTableImplementation(Session *,
355+ const string)
356+ {
357+ return 0;
358+ }
359+
360+};
361+
362+#endif /* DRIZZLE_PLUGIN_TOKYO_CABINET_ENGINE_H */
363
364=== added file 'plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.cc'
365--- plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.cc 1970-01-01 00:00:00 +0000
366+++ plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.cc 2009-09-24 03:50:23 +0000
367@@ -0,0 +1,221 @@
368+/*
369+ * Copyright (C) 2009 Sun Microsystems
370+ *
371+ * This program is free software; you can redistribute it and/or modify
372+ * it under the terms of the GNU General Public License as published by
373+ * the Free Software Foundation; either version 2 of the License, or
374+ * (at your option) any later version.
375+ *
376+ * This program is distributed in the hope that it will be useful,
377+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
378+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
379+ * GNU General Public License for more details.
380+ *
381+ * You should have received a copy of the GNU General Public License
382+ * along with this program; if not, write to the Free Software
383+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
384+ */
385+
386+#include "drizzled/server_includes.h"
387+#include "drizzled/join_table.h"
388+#include "drizzled/handler.h"
389+#include "drizzled/field/blob.h"
390+#include "drizzled/field/timestamp.h"
391+#include "drizzled/session.h"
392+
393+#include "tokyo_cabinet_handler.h"
394+#include "tokyo_cabinet_share.h"
395+#include "open_tables.h"
396+
397+#include <string>
398+#include <map>
399+
400+using namespace std;
401+using namespace drizzled;
402+
403+int TokyoCabinetHandler::open(const char *name, int, uint32_t)
404+{
405+ OpenTables &open_tables= OpenTables::singleton();
406+ if (! (share= open_tables.getShare(name)))
407+ {
408+ return HA_ERR_OUT_OF_MEM;
409+ }
410+
411+ assert(share);
412+
413+ thr_lock_data_init(share->getThreadLock(), &data_lock, NULL);
414+
415+ bool pack_table= ! (table->s->db_create_options &
416+ HA_OPTION_PACK_RECORD);
417+ share->setFixedLengthTable(pack_table);
418+ share->setRowLength(getMaxRowLength());
419+ share->setTableFields(table->field);
420+ share->setNullBytes(table->s->null_bytes);
421+ share->setTableRecord(table->record[0]);
422+
423+ return 0;
424+}
425+
426+int TokyoCabinetHandler::close()
427+{
428+ OpenTables &open_tables= OpenTables::singleton();
429+ open_tables.freeShare();
430+ return 0;
431+}
432+
433+int TokyoCabinetHandler::info(uint32_t flags)
434+{
435+ /*
436+ * If this flag is set, then we know that the time of the last
437+ * modification needs to be modified.
438+ */
439+ if (flags & HA_STATUS_TIME)
440+ {
441+ }
442+
443+ if (flags & HA_STATUS_VARIABLE)
444+ {
445+ stats.records= share->getNumOfRecords();
446+ }
447+
448+ /*
449+ * If this flag is set, then we know that the auto_increment value needs
450+ * to be updated.
451+ */
452+ if (flags & HA_STATUS_AUTO)
453+ {
454+ stats.auto_increment_value= 1;
455+ }
456+
457+ return 0;
458+}
459+
460+int TokyoCabinetHandler::rnd_init(bool)
461+{
462+ share->initIterators();
463+ return 0;
464+}
465+
466+int TokyoCabinetHandler::rnd_next(unsigned char *buf)
467+{
468+ return (share->retrieveRow(buf));
469+}
470+
471+int TokyoCabinetHandler::rnd_pos(unsigned char *buf, unsigned char *pos)
472+{
473+ Field *field_key= table->key_info[table->s->primary_key].key_part->field;
474+ uint16_t len;
475+ memcpy(&len, pos, sizeof(uint16_t));
476+ int ret= share->findRow(field_key, buf, pos + 2, len);
477+
478+ return ret;
479+}
480+
481+void TokyoCabinetHandler::position(const unsigned char *)
482+{
483+ return;
484+}
485+
486+THR_LOCK_DATA **TokyoCabinetHandler::store_lock(Session *session,
487+ THR_LOCK_DATA **to,
488+ enum thr_lock_type lock_type)
489+{
490+ /* borrowed from archive and BDB engines. TODO: understand this! */
491+ if (lock_type != TL_IGNORE && data_lock.type == TL_UNLOCK)
492+ {
493+ if ((lock_type >= TL_WRITE_CONCURRENT_INSERT && lock_type <= TL_WRITE) &&
494+ ! session_tablespace_op(session))
495+ {
496+ lock_type= TL_WRITE_ALLOW_WRITE;
497+ }
498+ if (lock_type == TL_READ_NO_INSERT)
499+ {
500+ lock_type= TL_READ;
501+ }
502+ data_lock.type= lock_type;
503+ }
504+ *to++= &data_lock;
505+ return to;
506+}
507+
508+uint32_t TokyoCabinetHandler::index_flags(uint32_t,
509+ uint32_t,
510+ bool) const
511+{
512+ return 0;
513+}
514+
515+int TokyoCabinetHandler::index_read(unsigned char *buf,
516+ const unsigned char *key,
517+ uint32_t key_len,
518+ enum ha_rkey_function)
519+{
520+ Field *key_field= table->key_info[active_index].key_part->field;
521+ ha_statistic_increment(&SSV::ha_read_key_count);
522+ int ret= share->findRow(key_field, buf, key, key_len);
523+ return ret;
524+}
525+
526+int TokyoCabinetHandler::index_next(unsigned char *)
527+{
528+ return HA_ERR_END_OF_FILE;
529+}
530+
531+int TokyoCabinetHandler::write_row(unsigned char *buf)
532+{
533+ Field *key_field= table->key_info[table->s->primary_key].key_part->field;
534+
535+ ha_statistic_increment(&SSV::ha_write_count);
536+
537+ if (table->next_number_field && buf == table->record[0])
538+ {
539+ update_auto_increment();
540+ }
541+
542+ /* push the data to the key/value store */
543+ return (share->storeRow(key_field, buf));
544+}
545+
546+int TokyoCabinetHandler::update_row(const unsigned char *,
547+ unsigned char *new_data)
548+{
549+ Field *key_field= table->key_info[table->s->primary_key].key_part->field;
550+
551+ ha_statistic_increment(&SSV::ha_update_count);
552+
553+ if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
554+ {
555+ table->timestamp_field->set_time();
556+ }
557+
558+ return (share->updateRow(key_field, new_data));
559+}
560+
561+int TokyoCabinetHandler::delete_row(const unsigned char *)
562+{
563+ Field *key_field= table->key_info[table->s->primary_key].key_part->field;
564+ ha_statistic_increment(&SSV::ha_delete_count);
565+ return (share->deleteRow(key_field));
566+}
567+
568+int TokyoCabinetHandler::delete_all_rows()
569+{
570+ share->deleteAllRows();
571+ return 0;
572+}
573+
574+uint32_t TokyoCabinetHandler::getMaxRowLength()
575+{
576+ uint32_t len= table->s->reclength + table->s->fields * 2;
577+ uint32_t *pos= table->getBlobField();
578+ uint32_t *end= pos + table->sizeBlobFields();
579+
580+ while (pos != end)
581+ {
582+ Field_blob *blob_field= static_cast<Field_blob *>(table->field[*pos]);
583+ len+= 2 + blob_field->get_length();
584+ pos++;
585+ }
586+
587+ return len;
588+}
589
590=== added file 'plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.h'
591--- plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.h 1970-01-01 00:00:00 +0000
592+++ plugin/tokyo_cabinet_engine/tokyo_cabinet_handler.h 2009-09-24 03:50:23 +0000
593@@ -0,0 +1,140 @@
594+/*
595+ * Copyright (C) 2009 Sun Microsystems
596+ *
597+ * This program is free software; you can redistribute it and/or modify
598+ * it under the terms of the GNU General Public License as published by
599+ * the Free Software Foundation; either version 2 of the License, or
600+ * (at your option) any later version.
601+ *
602+ * This program is distributed in the hope that it will be useful,
603+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
604+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
605+ * GNU General Public License for more details.
606+ *
607+ * You should have received a copy of the GNU General Public License
608+ * along with this program; if not, write to the Free Software
609+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
610+ */
611+
612+/**
613+ * @file
614+ *
615+ * Declares the handler for the Tokyo Cabinet storage engine.
616+ */
617+
618+#ifndef DRIZZLE_PLUGIN_TOKYO_CABINET_HANDLER_H
619+#define DRIZZLE_PLUGIN_TOKYO_CABINET_HANDLER_H
620+
621+#include <drizzled/handler.h>
622+#include <drizzled/show.h>
623+#include <mysys/thr_lock.h>
624+
625+#include "tokyo_cabinet_share.h"
626+
627+class TokyoCabinetHandler : public handler
628+{
629+public:
630+
631+ /* determines how many indexes are allowed per table */
632+ static const uint32_t MAX_KEYS= 1;
633+ static const uint32_t MAX_KEY_PARTS= 1;
634+ static const uint32_t MAX_KEY_LEN= 1024;
635+
636+ TokyoCabinetHandler(StorageEngine *engine_arg, TableShare *table_arg)
637+ :
638+ handler(engine_arg, table_arg)
639+ {}
640+
641+ ~TokyoCabinetHandler() {}
642+
643+ const char *table_type() const
644+ {
645+ return "TOKYO";
646+ }
647+
648+ /*
649+ The name of the index type that will be used for display
650+ don't implement this method unless you really have indexes
651+ */
652+ const char *index_type(uint32_t)
653+ {
654+ return "HASH";
655+ }
656+
657+ uint64_t table_flags() const
658+ {
659+ return (HA_NO_TRANSACTIONS |
660+ HA_REQUIRE_PRIMARY_KEY |
661+ HA_PRIMARY_KEY_REQUIRED_FOR_POSITION |
662+ HA_PRIMARY_KEY_REQUIRED_FOR_DELETE);
663+ }
664+
665+ /* open a table */
666+ int open(const char *name, int mode, uint32_t test_if_locked);
667+
668+ /* close a table */
669+ int close(void);
670+
671+ /* provide info to the optimizer */
672+ int info(uint32_t flag);
673+
674+ /* preparation for table scan (is this true?) */
675+ int rnd_init(bool scan);
676+
677+ /* get the next row and copy it into buf */
678+ int rnd_next(unsigned char *buf);
679+
680+ /* locate row pointed to by pos, copy it into buf */
681+ int rnd_pos(unsigned char *buf, unsigned char *pos);
682+
683+ /* record position of a record for reordering */
684+ void position(const unsigned char *record);
685+
686+ THR_LOCK_DATA **store_lock(Session *session,
687+ THR_LOCK_DATA **to,
688+ enum thr_lock_type lock_type);
689+
690+ uint32_t index_flags(uint32_t idx, uint32_t part, bool all_parts) const;
691+ int index_read(unsigned char *buf,
692+ const unsigned char *key,
693+ uint32_t key_len,
694+ enum ha_rkey_function find_flag);
695+ int index_next(unsigned char *buf);
696+
697+ int write_row(unsigned char *buf);
698+ int update_row(const unsigned char *,
699+ unsigned char *);
700+ int delete_row(const unsigned char *);
701+ int delete_all_rows();
702+
703+ uint32_t max_supported_keys() const
704+ {
705+ return MAX_KEYS;
706+ }
707+
708+ uint32_t max_supported_key_parts() const
709+ {
710+ return MAX_KEY_PARTS;
711+ }
712+
713+ uint32_t max_supported_key_length() const
714+ {
715+ return MAX_KEY_LEN;
716+ }
717+
718+private:
719+
720+ /**
721+ * Determine the maximum length of a row in the table we are working with.
722+ * This function is "borrowed" from the archive storage engine.
723+ *
724+ * @return the max row length for a table
725+ */
726+ uint32_t getMaxRowLength();
727+
728+ THR_LOCK_DATA data_lock;
729+ TokyoCabinetShare *share;
730+
731+};
732+
733+#endif /* DRIZZLE_PLUGIN_TOKYO_CABINET_HANDLER_H */
734
735=== added file 'plugin/tokyo_cabinet_engine/tokyo_cabinet_share.cc'
736--- plugin/tokyo_cabinet_engine/tokyo_cabinet_share.cc 1970-01-01 00:00:00 +0000
737+++ plugin/tokyo_cabinet_engine/tokyo_cabinet_share.cc 2009-09-24 03:50:23 +0000
738@@ -0,0 +1,240 @@
739+/*
740+ * Copyright (C) 2009 Sun Microsystems
741+ *
742+ * This program is free software; you can redistribute it and/or modify
743+ * it under the terms of the GNU General Public License as published by
744+ * the Free Software Foundation; either version 2 of the License, or
745+ * (at your option) any later version.
746+ *
747+ * This program is distributed in the hope that it will be useful,
748+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
749+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
750+ * GNU General Public License for more details.
751+ *
752+ * You should have received a copy of the GNU General Public License
753+ * along with this program; if not, write to the Free Software
754+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
755+ */
756+
757+#include "drizzled/server_includes.h"
758+#include "drizzled/handler.h"
759+#include "drizzled/show.h"
760+#include "mysys/thr_lock.h"
761+
762+#include <tcutil.h>
763+#include <tchdb.h>
764+#include <stdlib.h>
765+#include <stdbool.h>
766+#include <stdint.h>
767+
768+#include "tokyo_cabinet_share.h"
769+
770+using namespace std;
771+
772+bool TokyoCabinetShare::createDatabaseHandler()
773+{
774+ data_handler= tcmdbnew();
775+ if (! data_handler)
776+ {
777+ return false;
778+ }
779+ return true;
780+}
781+
782+bool TokyoCabinetShare::openTable()
783+{
784+ return true;
785+}
786+
787+void TokyoCabinetShare::freeDatabaseHandler()
788+{
789+ tcmdbdel(data_handler);
790+}
791+
792+int TokyoCabinetShare::storeRow(Field *key_field,
793+ unsigned char *row)
794+{
795+ createKey(key_field);
796+
797+ unsigned char *buf= new(std::nothrow) unsigned char[row_len];
798+ if (! buf)
799+ {
800+ return HA_ERR_OUT_OF_MEM;
801+ }
802+
803+ size_t len= packRow(buf, row);
804+
805+ bool ret= tcmdbputkeep(data_handler,
806+ primary_key,
807+ primary_key_len,
808+ buf,
809+ len);
810+ if (! ret)
811+ {
812+ delete buf;
813+ return HA_ERR_GENERIC;
814+ }
815+
816+ delete buf;
817+ return 0;
818+}
819+
820+int TokyoCabinetShare::updateRow(Field *key_field,
821+ unsigned char *row)
822+{
823+ createKey(key_field);
824+
825+ unsigned char *buf= new(std::nothrow) unsigned char[row_len];
826+ if (! buf)
827+ {
828+ return HA_ERR_OUT_OF_MEM;
829+ }
830+
831+ size_t len= packRow(buf, row);
832+
833+ /* TODO: somehow, check if this operation succeeded */
834+ tcmdbput(data_handler,
835+ primary_key,
836+ primary_key_len,
837+ buf,
838+ len);
839+
840+ delete buf;
841+ return 0;
842+}
843+
844+size_t TokyoCabinetShare::packRow(unsigned char *buf,
845+ unsigned char *row)
846+{
847+ size_t len= 0;
848+
849+ if (fixed_length_table)
850+ {
851+ memcpy(buf, row, row_len);
852+ len= row_len;
853+ }
854+ else
855+ {
856+ /* copy NULL bits */
857+ memcpy(buf, row, null_bytes);
858+ unsigned char *pos= buf + null_bytes;
859+
860+ for (Field **field= fields; *field; field++)
861+ {
862+ if (! ((*field)->is_null()))
863+ {
864+ pos= (*field)->pack(pos, row + (*field)->offset(row));
865+ }
866+ }
867+ len= (size_t) (pos - buf);
868+ }
869+ return len;
870+}
871+
872+void TokyoCabinetShare::unpackRow(unsigned char *buf,
873+ const char *row)
874+{
875+ if (fixed_length_table)
876+ {
877+ memcpy(buf, row, row_len);
878+ }
879+ else
880+ {
881+ const unsigned char *pos= (const unsigned char *) row;
882+ memcpy(buf, pos, null_bytes);
883+ pos+= null_bytes;
884+
885+ for (Field **field= fields; *field; field++)
886+ {
887+ if (! (*field)->is_null())
888+ {
889+ pos= (*field)->unpack(buf + (*field)->offset(table_record), pos);
890+ }
891+ }
892+ }
893+}
894+
895+void TokyoCabinetShare::createKey(Field *key)
896+{
897+ char *pos= primary_key_buff;
898+ char attr_buff[1024];
899+
900+ String attribute(attr_buff,
901+ sizeof(attr_buff),
902+ &my_charset_bin);
903+
904+ key->setReadSet();
905+ key->val_str(&attribute, &attribute);
906+
907+ size_t len= strlen(key->field_name);
908+ memcpy(pos, key->field_name, len);
909+ pos+= len;
910+
911+ memcpy(pos, attribute.ptr(), attribute.length());
912+ pos+= attribute.length();
913+
914+ primary_key_len= (size_t) (pos - primary_key_buff);
915+ primary_key= primary_key_buff;
916+}
917+
918+void TokyoCabinetShare::initIterators()
919+{
920+ tcmdbiterinit(data_handler);
921+}
922+
923+int TokyoCabinetShare::retrieveRow(unsigned char *buf)
924+{
925+ char *key= NULL;
926+
927+ while ((key= tcmdbiternext2(data_handler)) != NULL)
928+ {
929+ char *value= tcmdbget2(data_handler, key);
930+ free(key);
931+ if (value)
932+ {
933+ unpackRow(buf, value);
934+ free(value);
935+ return 0;
936+ }
937+ }
938+
939+ return HA_ERR_END_OF_FILE;
940+}
941+
942+int TokyoCabinetShare::deleteRow(Field *key_field)
943+{
944+ createKey(key_field);
945+
946+ bool ret= tcmdbout(data_handler,
947+ primary_key,
948+ primary_key_len);
949+ if (! ret)
950+ {
951+ return -1;
952+ }
953+ return 0;
954+}
955+
956+int TokyoCabinetShare::findRow(Field *key_field,
957+ unsigned char *buf,
958+ const unsigned char *key,
959+ size_t key_len)
960+{
961+ key_field->set_key_image(key, key_len);
962+ key_field->set_notnull();
963+ createKey(key_field);
964+
965+ int size;
966+ char *tc_row= (char *) tcmdbget(data_handler,
967+ primary_key,
968+ primary_key_len,
969+ &size);
970+ if (tc_row == NULL)
971+ {
972+ return HA_ERR_KEY_NOT_FOUND;
973+ }
974+
975+ unpackRow(buf, tc_row);
976+ free(tc_row);
977+ return 0;
978+}
979
980=== added file 'plugin/tokyo_cabinet_engine/tokyo_cabinet_share.h'
981--- plugin/tokyo_cabinet_engine/tokyo_cabinet_share.h 1970-01-01 00:00:00 +0000
982+++ plugin/tokyo_cabinet_engine/tokyo_cabinet_share.h 2009-09-24 03:50:23 +0000
983@@ -0,0 +1,219 @@
984+/*
985+ * Copyright (C) 2009 Sun Microsystems
986+ *
987+ * This program is free software; you can redistribute it and/or modify
988+ * it under the terms of the GNU General Public License as published by
989+ * the Free Software Foundation; either version 2 of the License, or
990+ * (at your option) any later version.
991+ *
992+ * This program is distributed in the hope that it will be useful,
993+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
994+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
995+ * GNU General Public License for more details.
996+ *
997+ * You should have received a copy of the GNU General Public License
998+ * along with this program; if not, write to the Free Software
999+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1000+ */
1001+
1002+/**
1003+ * @file
1004+ *
1005+ * Contains a declaration of the share class for the Tokyo Cabinet storage
1006+ * engine.
1007+ *
1008+ * @todo
1009+ * would it not be better to create a class that encapsulates all the calls
1010+ * to the Tokyo Cabinet API that we can just use from within the table
1011+ * share?
1012+ */
1013+
1014+#ifndef DRIZZLE_PLUGIN_TOKYO_CABINET_SHARE_H
1015+#define DRIZZLE_PLUGIN_TOKYO_CABINET_SHARE_H
1016+
1017+#include <drizzled/handler.h>
1018+#include <drizzled/show.h>
1019+#include <mysys/thr_lock.h>
1020+
1021+#include <tcutil.h>
1022+#include <tchdb.h>
1023+#include <stdlib.h>
1024+#include <stdbool.h>
1025+#include <stdint.h>
1026+
1027+class TokyoCabinetShare
1028+{
1029+public:
1030+
1031+ static const uint32_t MAX_KEY_LEN= 1024;
1032+
1033+ TokyoCabinetShare()
1034+ :
1035+ use_count(0),
1036+ lock(),
1037+ name(),
1038+ data_handler(NULL),
1039+ fixed_length_table(false),
1040+ row_len(0),
1041+ fields(NULL),
1042+ null_bytes(0),
1043+ table_record(NULL),
1044+ primary_key(NULL),
1045+ primary_key_len(0)
1046+ {
1047+ data_handler= tcmdbnew();
1048+ }
1049+
1050+ TokyoCabinetShare(const std::string &in_name)
1051+ :
1052+ use_count(0),
1053+ lock(),
1054+ name(in_name),
1055+ data_handler(NULL),
1056+ fixed_length_table(false),
1057+ row_len(0),
1058+ fields(NULL),
1059+ null_bytes(0),
1060+ table_record(NULL),
1061+ primary_key(NULL),
1062+ primary_key_len(0)
1063+ {
1064+ data_handler= tcmdbnew();
1065+ }
1066+
1067+ ~TokyoCabinetShare()
1068+ {
1069+ thr_lock_delete(&lock);
1070+ tcmdbdel(data_handler);
1071+ }
1072+
1073+ uint32_t getUseCount() const
1074+ {
1075+ return use_count;
1076+ }
1077+
1078+ void incUseCount()
1079+ {
1080+ use_count++;
1081+ }
1082+
1083+ void decUseCount()
1084+ {
1085+ use_count--;
1086+ }
1087+
1088+ const std::string &getName() const
1089+ {
1090+ return name;
1091+ }
1092+
1093+ void initThreadLock()
1094+ {
1095+ thr_lock_init(&lock);
1096+ }
1097+
1098+ THR_LOCK *getThreadLock()
1099+ {
1100+ return &lock;
1101+ }
1102+
1103+ void setFixedLengthTable(bool input)
1104+ {
1105+ fixed_length_table= input;
1106+ }
1107+
1108+ bool isFixedLengthTable() const
1109+ {
1110+ return fixed_length_table;
1111+ }
1112+
1113+ void setRowLength(uint32_t in_len)
1114+ {
1115+ row_len= in_len;
1116+ }
1117+
1118+ void setTableFields(Field **in_fields)
1119+ {
1120+ fields= in_fields;
1121+ }
1122+
1123+ void setNullBytes(size_t in_null_bytes)
1124+ {
1125+ null_bytes= in_null_bytes;
1126+ }
1127+
1128+ void setTableRecord(unsigned char *in_record)
1129+ {
1130+ table_record= in_record;
1131+ }
1132+
1133+ bool createDatabaseHandler();
1134+
1135+ bool openTable();
1136+
1137+ void freeDatabaseHandler();
1138+
1139+ uint64_t getNumOfRecords()
1140+ {
1141+ return tcmdbrnum(data_handler);
1142+ }
1143+
1144+ int storeRow(Field *key_field,
1145+ unsigned char *row);
1146+
1147+ int updateRow(Field *key_field,
1148+ unsigned char *row);
1149+
1150+ /**
1151+ * Create a key for this row to be stored in the Tokyo Cabinet store. The
1152+ * key is created based on the primary key value for the row.
1153+ *
1154+ * @param[in] the primary key field
1155+ */
1156+ void createKey(Field *key);
1157+
1158+ int deleteRow(Field *key_field);
1159+
1160+ void deleteAllRows()
1161+ {
1162+ tcmdbvanish(data_handler);
1163+ }
1164+
1165+ void initIterators();
1166+
1167+ int retrieveRow(unsigned char *buf);
1168+
1169+ int findRow(Field *key_field,
1170+ unsigned char *buf,
1171+ const unsigned char *key,
1172+ size_t key_len);
1173+
1174+private:
1175+
1176+ /**
1177+ * Store a variable sized row in Tokyo Cabinet.
1178+ */
1179+ size_t packRow(unsigned char *buf, unsigned char *row);
1180+
1181+ /**
1182+ * Retrieve a variable sized row from Tokyo Cabinet.
1183+ */
1184+ void unpackRow(unsigned char *buf, const char *row);
1185+
1186+ uint32_t use_count;
1187+ THR_LOCK lock;
1188+ std::string name;
1189+ TCMDB *data_handler;
1190+ bool fixed_length_table;
1191+ uint32_t row_len;
1192+ Field **fields;
1193+ size_t null_bytes;
1194+ unsigned char *table_record;
1195+
1196+ char primary_key_buff[MAX_KEY_LEN];
1197+ char *primary_key;
1198+ size_t primary_key_len;
1199+
1200+};
1201+
1202+#endif /* DRIZZLE_PLUGIN_TOKYO_CABINET_SHARE_H */
1203
1204=== added directory 'tests/suite/tc_engine'
1205=== added directory 'tests/suite/tc_engine/r'
1206=== added file 'tests/suite/tc_engine/r/auto_increment.result'
1207--- tests/suite/tc_engine/r/auto_increment.result 1970-01-01 00:00:00 +0000
1208+++ tests/suite/tc_engine/r/auto_increment.result 2009-09-24 03:50:24 +0000
1209@@ -0,0 +1,32 @@
1210+DROP TABLE IF EXISTS t2;
1211+Warnings:
1212+Note 1051 Unknown table 't2'
1213+CREATE TABLE t2 (a int primary key auto_increment, b bigint) ENGINE=TOKYO;
1214+insert into t2 (b) values (42),(74),(108),(256);
1215+SELECT * from t2 ORDER BY a;
1216+a b
1217+1 42
1218+2 74
1219+3 108
1220+4 256
1221+SELECT COUNT(*) from t2;
1222+COUNT(*)
1223+4
1224+EXPLAIN SELECT * FROM t2 WHERE a=1;
1225+id select_type table type possible_keys key key_len ref rows Extra
1226+1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1
1227+SELECT * FROM t2 WHERE a=1;
1228+a b
1229+1 42
1230+SELECT * FROM t2 WHERE a=2;
1231+a b
1232+2 74
1233+SELECT * FROM t2 WHERE a=3;
1234+a b
1235+3 108
1236+SELECT * FROM t2 WHERE a=4;
1237+a b
1238+4 256
1239+SELECT * FROM t2 WHERE a=5;
1240+a b
1241+DROP TABLE t2;
1242
1243=== added file 'tests/suite/tc_engine/r/basic.result'
1244--- tests/suite/tc_engine/r/basic.result 1970-01-01 00:00:00 +0000
1245+++ tests/suite/tc_engine/r/basic.result 2009-09-24 03:50:24 +0000
1246@@ -0,0 +1,138 @@
1247+DROP TABLE IF EXISTS t1;
1248+Warnings:
1249+Note 1051 Unknown table 't1'
1250+CREATE TABLE t1 (a int primary key, b varchar(200)) ENGINE=TOKYO;
1251+INSERT INTO t1 (a,b) VALUES (1, 'FOO');
1252+INSERT INTO t1 (a,b) VALUES (2, 'BAR');
1253+INSERT INTO t1 (a,b) VALUES (3, 'LCA ROCKS');
1254+INSERT INTO t1 (a,b) VALUES (4, 'freeze ray');
1255+INSERT INTO t1 (a,b) VALUES (5, 'this row appears because of the kind donations of....');
1256+SELECT COUNT(*) FROM t1;
1257+COUNT(*)
1258+5
1259+SELECT * from t1;
1260+a b
1261+4 freeze ray
1262+5 this row appears because of the kind donations of....
1263+1 FOO
1264+2 BAR
1265+3 LCA ROCKS
1266+DROP TABLE t1;
1267+CREATE TABLE t2 (a int primary key,b bigint) ENGINE=TOKYO;
1268+insert into t2 (a,b) values (1,42),(2,74),(3,108),(4,256);
1269+SELECT COUNT(*) FROM t2;
1270+COUNT(*)
1271+4
1272+SELECT * from t2;
1273+a b
1274+4 256
1275+1 42
1276+2 74
1277+3 108
1278+SELECT * FROM t2 WHERE a > 2;
1279+a b
1280+4 256
1281+3 108
1282+SELECT * FROM t2 WHERE a > 4;
1283+a b
1284+DROP TABLE t2;
1285+CREATE TABLE t3 (a int primary key, b int unique) ENGINE=TOKYO;
1286+ERROR 42000: Too many keys specified; max 1 keys allowed
1287+CREATE TABLE t4 (a int, b int, PRIMARY KEY (a,b)) ENGINE=TOKYO;
1288+ERROR 42000: Too many key parts specified; max 1 parts allowed
1289+CREATE TABLE t5 (a int, index(a)) ENGINE=TOKYO;
1290+ERROR 42000: Table handler doesn't support NULL in given index. Please change column 'a' to be NOT NULL or use another handler
1291+drop table if exists t1,t2;
1292+create table t1 (id int primary key, num int) engine=tokyo;
1293+insert into t1 values (1, 100);
1294+insert into t1 values (2, 101);
1295+insert into t1 values (3, 102);
1296+insert into t1 values (4, 103);
1297+insert into t1 values (5, 104);
1298+select * from t1;
1299+id num
1300+1 100
1301+2 101
1302+3 102
1303+4 103
1304+5 104
1305+select count(*) from t1;
1306+count(*)
1307+5
1308+select * from t1 where id = 1;
1309+id num
1310+1 100
1311+select * from t1 where id = 2;
1312+id num
1313+2 101
1314+select * from t1 where id = 3;
1315+id num
1316+3 102
1317+select * from t1 where id = 4;
1318+id num
1319+4 103
1320+select * from t1 where id = 5;
1321+id num
1322+5 104
1323+update t1 set num = 1111 where id = 1;
1324+update t1 set num = 2222 where id = 2;
1325+update t1 set num = 3333 where id = 3;
1326+select * from t1 where id < 4;
1327+id num
1328+1 1111
1329+2 2222
1330+3 3333
1331+delete from t1 where id = 1;
1332+delete from t1 where id = 2;
1333+delete from t1 where id = 3;
1334+delete from t1;
1335+drop table t1;
1336+create table t2 (id int primary key, b blob) engine=tokyo;
1337+insert into t2 values (1, "aaa");
1338+insert into t2 values (2, "bbb");
1339+insert into t2 values (3, "aaaaaa");
1340+insert into t2 values (4, "bbbbbb");
1341+select * from t2;
1342+id b
1343+1 aaa
1344+2 bbb
1345+3 aaaaaa
1346+4 bbbbbb
1347+update t2 set b = NULL where id = 1;
1348+update t2 set b = "updated" where id = 2;
1349+update t2 set b = NULL where id = 3;
1350+update t2 set b = "updated" where id = 4;
1351+select * from t2;
1352+id b
1353+1 NULL
1354+2 updated
1355+3 NULL
1356+4 updated
1357+drop table t2;
1358+create table t1(id int primary key, num1 int, num2 int) engine=tokyo;
1359+create table t2 like t1;
1360+insert into t2 values (1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5), (6,6,6);
1361+insert into t2 values (7,7,7), (8,8,8), (9,9,9), (10,10,10), (11,11,11);
1362+insert into t1 select * from t2;
1363+select * from t1;
1364+id num1 num2
1365+8 8 8
1366+1 1 1
1367+9 9 9
1368+10 10 10
1369+2 2 2
1370+11 11 11
1371+3 3 3
1372+4 4 4
1373+5 5 5
1374+6 6 6
1375+7 7 7
1376+delete from t1;
1377+insert into t1 select * from t2 where id < 5;
1378+select * from t1;
1379+id num1 num2
1380+1 1 1
1381+2 2 2
1382+3 3 3
1383+4 4 4
1384+drop table t1, t2;
1385
1386=== added directory 'tests/suite/tc_engine/t'
1387=== added file 'tests/suite/tc_engine/t/auto_increment.test'
1388--- tests/suite/tc_engine/t/auto_increment.test 1970-01-01 00:00:00 +0000
1389+++ tests/suite/tc_engine/t/auto_increment.test 2009-09-24 03:50:24 +0000
1390@@ -0,0 +1,13 @@
1391+DROP TABLE IF EXISTS t2;
1392+CREATE TABLE t2 (a int primary key auto_increment, b bigint) ENGINE=TOKYO;
1393+insert into t2 (b) values (42),(74),(108),(256);
1394+SELECT * from t2 ORDER BY a;
1395+SELECT COUNT(*) from t2;
1396+EXPLAIN SELECT * FROM t2 WHERE a=1;
1397+SELECT * FROM t2 WHERE a=1;
1398+SELECT * FROM t2 WHERE a=2;
1399+SELECT * FROM t2 WHERE a=3;
1400+SELECT * FROM t2 WHERE a=4;
1401+SELECT * FROM t2 WHERE a=5;
1402+DROP TABLE t2;
1403+
1404
1405=== added file 'tests/suite/tc_engine/t/basic.test'
1406--- tests/suite/tc_engine/t/basic.test 1970-01-01 00:00:00 +0000
1407+++ tests/suite/tc_engine/t/basic.test 2009-09-24 03:50:24 +0000
1408@@ -0,0 +1,107 @@
1409+--disable-warnings
1410+DROP TABLE IF EXISTS t1;
1411+--enable-warnings
1412+
1413+CREATE TABLE t1 (a int primary key, b varchar(200)) ENGINE=TOKYO;
1414+
1415+INSERT INTO t1 (a,b) VALUES (1, 'FOO');
1416+INSERT INTO t1 (a,b) VALUES (2, 'BAR');
1417+INSERT INTO t1 (a,b) VALUES (3, 'LCA ROCKS');
1418+INSERT INTO t1 (a,b) VALUES (4, 'freeze ray');
1419+INSERT INTO t1 (a,b) VALUES (5, 'this row appears because of the kind donations of....');
1420+SELECT COUNT(*) FROM t1;
1421+SELECT * from t1;
1422+
1423+DROP TABLE t1;
1424+
1425+CREATE TABLE t2 (a int primary key,b bigint) ENGINE=TOKYO;
1426+insert into t2 (a,b) values (1,42),(2,74),(3,108),(4,256);
1427+SELECT COUNT(*) FROM t2;
1428+SELECT * from t2;
1429+SELECT * FROM t2 WHERE a > 2;
1430+SELECT * FROM t2 WHERE a > 4;
1431+DROP TABLE t2;
1432+
1433+--error ER_TOO_MANY_KEYS
1434+CREATE TABLE t3 (a int primary key, b int unique) ENGINE=TOKYO;
1435+
1436+--error ER_TOO_MANY_KEY_PARTS
1437+CREATE TABLE t4 (a int, b int, PRIMARY KEY (a,b)) ENGINE=TOKYO;
1438+
1439+--error ER_NULL_COLUMN_IN_INDEX
1440+CREATE TABLE t5 (a int, index(a)) ENGINE=TOKYO;
1441+
1442+--disable_warnings
1443+drop table if exists t1,t2;
1444+--enable_warnings
1445+
1446+## Easy warm up test
1447+create table t1 (id int primary key, num int) engine=tokyo;
1448+
1449+insert into t1 values (1, 100);
1450+insert into t1 values (2, 101);
1451+insert into t1 values (3, 102);
1452+insert into t1 values (4, 103);
1453+insert into t1 values (5, 104);
1454+
1455+select * from t1;
1456+select count(*) from t1;
1457+
1458+# Test Primary Key
1459+select * from t1 where id = 1;
1460+select * from t1 where id = 2;
1461+select * from t1 where id = 3;
1462+select * from t1 where id = 4;
1463+select * from t1 where id = 5;
1464+
1465+# Update rows based on Primary Key
1466+update t1 set num = 1111 where id = 1;
1467+update t1 set num = 2222 where id = 2;
1468+update t1 set num = 3333 where id = 3;
1469+
1470+select * from t1 where id < 4;
1471+
1472+# Delete rows based on Primary Key
1473+delete from t1 where id = 1;
1474+delete from t1 where id = 2;
1475+delete from t1 where id = 3;
1476+
1477+# Delete remaining rows
1478+delete from t1;
1479+
1480+drop table t1;
1481+
1482+# Test BLOB type
1483+create table t2 (id int primary key, b blob) engine=tokyo;
1484+
1485+insert into t2 values (1, "aaa");
1486+insert into t2 values (2, "bbb");
1487+insert into t2 values (3, "aaaaaa");
1488+insert into t2 values (4, "bbbbbb");
1489+
1490+select * from t2;
1491+
1492+update t2 set b = NULL where id = 1;
1493+update t2 set b = "updated" where id = 2;
1494+update t2 set b = NULL where id = 3;
1495+update t2 set b = "updated" where id = 4;
1496+
1497+select * from t2;
1498+
1499+drop table t2;
1500+
1501+# Test INSERT-SELECT statements
1502+create table t1(id int primary key, num1 int, num2 int) engine=tokyo;
1503+create table t2 like t1;
1504+
1505+insert into t2 values (1,1,1), (2,2,2), (3,3,3), (4,4,4), (5,5,5), (6,6,6);
1506+insert into t2 values (7,7,7), (8,8,8), (9,9,9), (10,10,10), (11,11,11);
1507+
1508+insert into t1 select * from t2;
1509+select * from t1;
1510+delete from t1;
1511+
1512+insert into t1 select * from t2 where id < 5;
1513+select * from t1;
1514+
1515+drop table t1, t2;