oinky 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/LICENSE +22 -0
  2. data/README.md +141 -0
  3. data/ext/extconf.rb +79 -0
  4. data/ext/include/oinky.h +424 -0
  5. data/ext/include/oinky.hpp +63 -0
  6. data/ext/include/oinky/nky_base.hpp +1116 -0
  7. data/ext/include/oinky/nky_core.hpp +1603 -0
  8. data/ext/include/oinky/nky_cursor.hpp +665 -0
  9. data/ext/include/oinky/nky_dialect.hpp +107 -0
  10. data/ext/include/oinky/nky_error.hpp +164 -0
  11. data/ext/include/oinky/nky_fixed_table.hpp +710 -0
  12. data/ext/include/oinky/nky_handle.hpp +334 -0
  13. data/ext/include/oinky/nky_index.hpp +1038 -0
  14. data/ext/include/oinky/nky_log.hpp +15 -0
  15. data/ext/include/oinky/nky_merge_itr.hpp +403 -0
  16. data/ext/include/oinky/nky_model.hpp +110 -0
  17. data/ext/include/oinky/nky_pool.hpp +760 -0
  18. data/ext/include/oinky/nky_public.hpp +808 -0
  19. data/ext/include/oinky/nky_serializer.hpp +1625 -0
  20. data/ext/include/oinky/nky_strtable.hpp +504 -0
  21. data/ext/include/oinky/nky_table.hpp +1996 -0
  22. data/ext/nky_lib.cpp +390 -0
  23. data/ext/nky_lib_core.hpp +212 -0
  24. data/ext/nky_lib_index.cpp +158 -0
  25. data/ext/nky_lib_table.cpp +224 -0
  26. data/lib/oinky.rb +1284 -0
  27. data/lib/oinky/compiler.rb +106 -0
  28. data/lib/oinky/cpp_emitter.rb +311 -0
  29. data/lib/oinky/dsl.rb +167 -0
  30. data/lib/oinky/error.rb +19 -0
  31. data/lib/oinky/modelbase.rb +12 -0
  32. data/lib/oinky/nbuffer.rb +152 -0
  33. data/lib/oinky/normalize.rb +132 -0
  34. data/lib/oinky/oc_builder.rb +44 -0
  35. data/lib/oinky/query.rb +193 -0
  36. data/lib/oinky/rb_emitter.rb +147 -0
  37. data/lib/oinky/shard.rb +40 -0
  38. data/lib/oinky/testsup.rb +104 -0
  39. data/lib/oinky/version.rb +9 -0
  40. data/oinky.gemspec +36 -0
  41. metadata +120 -0
@@ -0,0 +1,15 @@
1
+ // This source is distributed under the terms of the MIT License. Refer
2
+ // to the 'LICENSE' file for details.
3
+ //
4
+ // Copyright (c) Jacob Lacouture, 2012
5
+
6
+ namespace Oinky
7
+ {
8
+ namespace Internal
9
+ {
10
+ using namespace Oinky::Errors;
11
+ using namespace Oinky::Utils;
12
+
13
+
14
+ } //namespace Internal
15
+ } //namespace Oinky
@@ -0,0 +1,403 @@
1
+ // This source is distributed under the terms of the MIT License. Refer
2
+ // to the 'LICENSE' file for details.
3
+ //
4
+ // Copyright (c) Jacob Lacouture, 2012
5
+
6
+ namespace Oinky
7
+ {
8
+ namespace Utils
9
+ {
10
+ using namespace Oinky::Errors;
11
+
12
+ //
13
+ // The merge iterator is bidirectional. We need a concept of a range, where
14
+ // the iterator can be valid, or at end(), or additionally, before the
15
+ // beginning of the sequence. In general, we cannot safely decrement an
16
+ // iterator from begin().
17
+ //
18
+
19
+ template<typename ITR>
20
+ class symmetric_iterator
21
+ {
22
+ typedef ITR iterator;
23
+
24
+ iterator _i;
25
+ iterator _begin;
26
+ iterator _end;
27
+ bool _sub_begin;
28
+
29
+ iterator begin() const { return _begin; }
30
+ iterator end() const { return _end; }
31
+
32
+ public:
33
+ symmetric_iterator(
34
+ const iterator &__i,
35
+ const iterator &__begin,
36
+ const iterator &__end) :
37
+ _i(__i),
38
+ _begin(__begin),
39
+ _end(__end),
40
+ _sub_begin(false)
41
+ {}
42
+
43
+ symmetric_iterator() : _sub_begin(false) {}
44
+
45
+ // This need not return iterator &. It merely must return whatever
46
+ // the comparer expects.
47
+ const iterator &i() const { return _i; }
48
+
49
+ bool before_begin() const { return _sub_begin; }
50
+ bool at_end() const { return _i == _end; }
51
+ bool is_valid() const { return !before_begin() && !at_end(); }
52
+
53
+ void increment() {
54
+ OINKY_ASSERT( _sub_begin || (_i != _end) );
55
+ if (_sub_begin) {
56
+ _sub_begin = false;
57
+ } else {
58
+ ++_i;
59
+ }
60
+ }
61
+ void decrement() {
62
+ OINKY_ASSERT( !_sub_begin );
63
+ if (_i == _begin) {
64
+ _sub_begin = true;
65
+ } else {
66
+ --_i;
67
+ }
68
+ }
69
+ };
70
+
71
+ template<typename DERIVED, typename VALUE_TYPE, typename RANGE1, typename RANGE2, typename COMPARE>
72
+ class merge_iterator_template : public
73
+ boost::iterator_facade<
74
+ DERIVED,
75
+ VALUE_TYPE,
76
+ boost::bidirectional_traversal_tag,
77
+ VALUE_TYPE
78
+ >
79
+ {
80
+ typedef merge_iterator_template<DERIVED,VALUE_TYPE,RANGE1,RANGE2,COMPARE> this_t;
81
+ typedef boost::iterator_facade<
82
+ DERIVED,
83
+ VALUE_TYPE,
84
+ boost::bidirectional_traversal_tag,
85
+ VALUE_TYPE
86
+ > base_t;
87
+
88
+ friend class boost::iterator_core_access;
89
+
90
+ public:
91
+ // base iterators should all have good defaults.
92
+ merge_iterator_template() {}
93
+
94
+ merge_iterator_template(
95
+ const RANGE1 &_l,
96
+ const RANGE2 &_r) :
97
+ l(_l),
98
+ r(_r)
99
+ {
100
+ set_fwd_state();
101
+ }
102
+
103
+ private:
104
+ RANGE1 l;
105
+ RANGE2 r;
106
+
107
+ // -1: *this == *l
108
+ // 0: *this == *l, *this == *r
109
+ // 1: *this == *r
110
+ int active;
111
+ // -1: *l < *r
112
+ // 0: *l == *r
113
+ // 1: *l > r
114
+ int lsubr;
115
+
116
+ void set_fwd_state()
117
+ {
118
+ lsubr = 0;
119
+ bool compare = true;
120
+ if (l.before_begin()) {
121
+ lsubr -= 1;
122
+ compare = false;
123
+ } else if (l.at_end()) {
124
+ lsubr += 1;
125
+ compare = false;
126
+ }
127
+ if (r.before_begin()) {
128
+ lsubr += 1;
129
+ compare = false;
130
+ } else if (r.at_end()) {
131
+ lsubr -= 1;
132
+ compare = false;
133
+ }
134
+ if (compare) {
135
+ // Compute l-r
136
+ COMPARE c;
137
+ lsubr = c(l.i(), r.i());
138
+ }
139
+ // current position is the smaller of the two. -1 if left
140
+ // is smaller, 1 if right is smaller, 0 if equal.
141
+ active = lsubr;
142
+ }
143
+ void set_reverse_state()
144
+ {
145
+ set_fwd_state();
146
+ active = -active;
147
+ }
148
+ protected:
149
+ void increment()
150
+ {
151
+ // Advance the iterator.
152
+ COMPARE c;
153
+ (void) c;
154
+
155
+ // Left is active.
156
+ if (active < 0) {
157
+ // If right < left, then this is a change of direction.
158
+ if (lsubr > 0) {
159
+ // Grow right.
160
+ r.increment();
161
+ // The invariant is that left and right are always less than
162
+ // one step apart. Stepping either toward the other changes
163
+ // sign of lsubr, or makes it nonzero.
164
+ OINKY_ASSERT((r.at_end()) || (c(l.i(),r.i()) < 0));
165
+ }
166
+ l.increment();
167
+ } else if (active > 0) {
168
+ // If right > left, then this is a change of direction.
169
+ if (lsubr < 0) {
170
+ // Grow left to beyond right.
171
+ l.increment();
172
+ OINKY_ASSERT((l.at_end()) || (c(l.i(),r.i()) > 0));
173
+ }
174
+ r.increment();
175
+ } else {
176
+ // Increment both.
177
+ l.increment();
178
+ r.increment();
179
+ }
180
+ // Make the smallest iterator active.
181
+ set_fwd_state();
182
+ }
183
+ void advance(int n) {
184
+ while (n>0) {
185
+ increment();
186
+ --n;
187
+ }
188
+ while (n<0) {
189
+ decrement();
190
+ ++n;
191
+ }
192
+ }
193
+
194
+ void decrement()
195
+ {
196
+ COMPARE c;
197
+ (void) c;
198
+
199
+ // Left is active.
200
+ if (active < 0) {
201
+ // If right > left, then this is a change of direction.
202
+ if (lsubr < 0) {
203
+ // Decrement right until it's less than left;
204
+ r.decrement();
205
+ // Having decremented, we know r.i != r.end or r.sub_begin.
206
+ // Also, if the iterators were separated by less than one
207
+ // position, then right should now be < left.
208
+ OINKY_ASSERT(r.before_begin() || (c(l.i(),r.i()) > 0));
209
+ }
210
+ // Now decrement left.
211
+ l.decrement();
212
+ } else if (active > 0) {
213
+ // If right < left, then this is a change of direction.
214
+ if (lsubr > 0) {
215
+ // Decrement left until it's less than right.
216
+ l.decrement();
217
+ OINKY_ASSERT(l.before_begin() || (c(l.i(),r.i()) < 0));
218
+ }
219
+ // Now decrement right.
220
+ r.decrement();
221
+ } else {
222
+ // Decrement both.
223
+ l.decrement();
224
+ r.decrement();
225
+ }
226
+ // Make the largest iterator active.
227
+ set_reverse_state();
228
+ }
229
+
230
+ // This is nontrivial, since the iterators may be traveling different
231
+ // directions. They may thus be equal (referring to the same element)
232
+ // but have one of the the component iterators being different.
233
+ bool equal(const this_t &other) const { return compare_to(_equal(), other); }
234
+
235
+ public:
236
+ const RANGE1 &left() const { return l; }
237
+ const RANGE2 &right() const { return r; }
238
+
239
+ // Remember, it's possible that BOTH left and right will be simultaneously active.
240
+ bool left_active() const { return (active <= 0) && l.is_valid(); }
241
+ bool right_active() const { return (active >= 0) && r.is_valid(); }
242
+
243
+ bool at_end() const { return l.at_end() && r.at_end(); }
244
+ bool before_begin() const { return l.before_begin() && r.before_begin(); }
245
+
246
+ template<typename FN>
247
+ bool compare_to(const FN &fn, const this_t &other) const {
248
+ int x = compare_to(other);
249
+ return fn(x,0);
250
+ }
251
+
252
+ int compare_to(const this_t &other) const {
253
+ COMPARE c;
254
+
255
+ int stat =
256
+ (left_active() ? 8 : 0) |
257
+ (right_active() ? 4 : 0) |
258
+ (other.left_active() ? 2 : 0) |
259
+ (other.right_active() ? 1 : 0);
260
+ switch (stat) {
261
+ case 0x0 + 0x0 :
262
+ // Both at end.
263
+ return 0;
264
+ case 0x8 + 0x0:
265
+ case 0x4 + 0x0:
266
+ case 0xc + 0x0:
267
+ // other at end. This not.
268
+ return -1;
269
+ case 0x0 + 0x2:
270
+ case 0x0 + 0x1:
271
+ case 0x0 + 0x3:
272
+ // this at end. Other not.
273
+ return 1;
274
+ case 0x8 + 0x2:
275
+ case 0xc + 0x2:
276
+ case 0x8 + 0x3:
277
+ case 0xc + 0x3:
278
+ // Left active on both.
279
+ return c(l.i(), other.l.i());
280
+ case 0x4 + 0x1:
281
+ case 0xc + 0x1:
282
+ case 0x4 + 0x3:
283
+ //case 0xc + 0x3: dup
284
+ // Right active on both.
285
+ return c(r.i(), other.r.i());
286
+ case 0x8 + 0x1:
287
+ // This left. Other right.
288
+ return c(l.i(), other.r.i());
289
+ case 0x4 + 0x2:
290
+ // This right. Other left.
291
+ return c(r.i(), other.l.i());
292
+ }
293
+ OINKY_ASSERT(false);
294
+ throw_error(implementation_bug());
295
+ return 0;
296
+ }
297
+
298
+ /* This is slow, and not required of bidirectional iterators, so we don't
299
+ implement it.
300
+ int distance_to(const this_t &other) const {
301
+ // This works, but is not efficient, and should not be used.
302
+ OINKY_ASSERT(false);
303
+ throw_error(unsupported_operation());
304
+
305
+ if (other < *this) {
306
+ return -other.distance_to(*this);
307
+ }
308
+
309
+ this_t tmp = *this;
310
+ int count = 0;
311
+ while (tmp < other) {
312
+ ++tmp;
313
+ ++count;
314
+ }
315
+ return count;
316
+ }*/
317
+
318
+ private:
319
+ struct _equal {template<typename T> bool operator()(const T&l, const T&r) const {return l == r;}};
320
+
321
+ struct _less {template<typename T> bool operator()(const T&l, const T&r) const {return l < r;}};
322
+ struct _gt {template<typename T> bool operator()(const T&l, const T&r) const {return l > r;}};
323
+ struct _leq {template<typename T> bool operator()(const T&l, const T&r) const {return l <= r;}};
324
+ struct _geq {template<typename T> bool operator()(const T&l, const T&r) const {return l >= r;}};
325
+
326
+ public:
327
+ bool operator<(const this_t &other) const {
328
+ return compare_to(_less(), other);
329
+ }
330
+ bool operator>(const this_t &other) const {
331
+ return compare_to(_gt(), other);
332
+ }
333
+ bool operator<=(const this_t &other) const {
334
+ return compare_to(_leq(), other);
335
+ }
336
+ bool operator>=(const this_t &other) const {
337
+ return compare_to(_geq(), other);
338
+ }
339
+ };
340
+
341
+
342
+ template<typename ITR1, typename ITR2, typename COMPARE>
343
+ class merge_iterator : public merge_iterator_template<
344
+ merge_iterator<ITR1, ITR2, COMPARE>,
345
+ typename boost::iterator_value<ITR1>::type,
346
+ symmetric_iterator<ITR1>,
347
+ symmetric_iterator<ITR2>,
348
+ COMPARE
349
+ >
350
+ {
351
+ typedef symmetric_iterator<ITR1> range1_t;
352
+ typedef symmetric_iterator<ITR2> range2_t;
353
+
354
+ typedef merge_iterator_template<
355
+ merge_iterator<ITR1, ITR2, COMPARE>,
356
+ typename boost::iterator_value<ITR1>::type,
357
+ range1_t,
358
+ range2_t,
359
+ COMPARE
360
+ > base_t;
361
+ public:
362
+ merge_iterator() {}
363
+
364
+ merge_iterator(
365
+ const range1_t &_l,
366
+ const range2_t &_r) :
367
+ base_t(_l,_r)
368
+ {}
369
+
370
+ merge_iterator(
371
+ const ITR1 &_li, const ITR1 &_lb, const ITR1 &_le,
372
+ const ITR2 &_ri, const ITR2 &_rb, const ITR2 &_re) :
373
+ base_t(range1_t(_li, _lb, _le),range2_t(_ri, _rb, _re))
374
+ {}
375
+
376
+ BOOST_STATIC_ASSERT((boost::is_same<
377
+ typename boost::iterator_value<ITR1>::type,
378
+ typename boost::iterator_value<ITR2>::type>::value));
379
+
380
+ typedef typename boost::iterator_value<ITR1>::type value_type;
381
+
382
+ const ITR1 &left() const { return base_t::left().i(); }
383
+ const ITR2 &right() const { return base_t::right().i(); }
384
+
385
+ private:
386
+ value_type dereference() const {
387
+ if (base_t::left_active()) {
388
+ return *left();
389
+ } else if (base_t::right_active()) {
390
+ return *right();
391
+ }
392
+
393
+ // Dereferencing an iterator at the end.
394
+ OINKY_ASSERT(false);
395
+ return value_type();
396
+ }
397
+
398
+ friend class boost::iterator_core_access;
399
+ };
400
+
401
+ } //namespace Utils
402
+ } //namespace Oinky
403
+
@@ -0,0 +1,110 @@
1
+ // This source is distributed under the terms of the MIT License. Refer
2
+ // to the 'LICENSE' file for details.
3
+ //
4
+ // Copyright (c) Jacob Lacouture, 2012
5
+
6
+ // These are some support classes for the code generated by the model compiler,
7
+ // which is still experimental.
8
+ //
9
+ // Everything in this file is subject to change.
10
+
11
+ namespace Oinky
12
+ {
13
+ namespace Model
14
+ {
15
+ typedef db_t::column_selector_t column_selector_t;
16
+ typedef db_t::index_handle index_handle;
17
+ typedef db_t::table_handle table_handle;
18
+
19
+ class TableBase
20
+ {
21
+ public:
22
+ static void create_column_if(
23
+ table_handle &th,
24
+ const char *colname,
25
+ column_type_code_t coltype,
26
+ const variant_cv_t &default_value)
27
+ {
28
+ db_t::column_itr i = th.columns().find(colname);
29
+ if (i == th.columns().end()) {
30
+ i = th.columns().create(colname, coltype, default_value);
31
+ }
32
+ }
33
+
34
+ static void create_index_if(
35
+ table_handle &th,
36
+ const db_string &ixname,
37
+ bool is_unique,
38
+ const index_column_def *cols_begin,
39
+ const index_column_def *cols_end)
40
+ {
41
+ db_t::index_itr i = th.indices().find(ixname);
42
+ if (i == th.indices().end()) {
43
+ i = th.indices().create(ixname, is_unique ? Oinky::Unique : Oinky::NonUnique, cols_begin, cols_end);
44
+ }
45
+ }
46
+
47
+ static index_handle get_index_handle(table_handle &th, const char *indexname) {
48
+ return th.indices()[indexname];
49
+ }
50
+
51
+ protected:
52
+ table_handle th;
53
+ db_t &__db;
54
+
55
+ public:
56
+ db_t &db() const { return __db; }
57
+
58
+ void check_init_row_accessor(column_selector_t &cs, const char **cn_begin, const char **cn_end)
59
+ {
60
+ // Column count will be zero if we haven't initialized yet. But
61
+ // we must also account for the fact that selectors are invalidated
62
+ // by schema changes to the table.
63
+ if ((cs.column_count() == 0) ||
64
+ (th.last_colset_change() != cs.last_colset_change()))
65
+ {
66
+ // This will raise an exception if one of our columns has been
67
+ // deleted since we mounted.
68
+ cs = th.make_selector(cn_begin, cn_end);
69
+ }
70
+ }
71
+
72
+ TableBase(const table_handle &_th, db_t &_db) : th(_th), __db(_db)
73
+ {}
74
+ };
75
+
76
+ class SchemaBase
77
+ {
78
+ db_t &db;
79
+
80
+ public:
81
+ static table_handle get_table_handle(db_t &db, const char *tablename) {
82
+ return *db.tables().create_if(tablename).first;
83
+ }
84
+
85
+ // Variable part of table-schema update. We invoke the callback when we
86
+ // detect something wrong, which is a defensive tactic.
87
+ typedef void (*schema_cb_fn)(db_t &db);
88
+
89
+ protected:
90
+ void up_schema(schema_cb_fn schema_cb)
91
+ {
92
+ // Ensure the schema migration is atomic.
93
+ sp_marker_t lkg = db.new_sp();
94
+ try {
95
+ (*schema_cb)(db);
96
+ } catch (...) {
97
+ db.sp_rollback(lkg);
98
+ // Re-throw.
99
+ throw;
100
+ }
101
+ }
102
+
103
+ public:
104
+ SchemaBase(db_t &_db, schema_cb_fn update_schema) : db(_db) {
105
+ (*update_schema)(db);
106
+ }
107
+ };
108
+
109
+ } //namespace Model
110
+ } //namespace Oinky