dbldots_oedipus 0.0.16

Sign up to get free protection for your applications and to get access to all the features.
Files changed (54) hide show
  1. data/.gitignore +10 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE +20 -0
  5. data/README.md +435 -0
  6. data/Rakefile +26 -0
  7. data/ext/oedipus/extconf.rb +72 -0
  8. data/ext/oedipus/lexing.c +96 -0
  9. data/ext/oedipus/lexing.h +20 -0
  10. data/ext/oedipus/oedipus.c +339 -0
  11. data/ext/oedipus/oedipus.h +58 -0
  12. data/lib/oedipus.rb +40 -0
  13. data/lib/oedipus/comparison.rb +88 -0
  14. data/lib/oedipus/comparison/between.rb +21 -0
  15. data/lib/oedipus/comparison/equal.rb +21 -0
  16. data/lib/oedipus/comparison/gt.rb +21 -0
  17. data/lib/oedipus/comparison/gte.rb +21 -0
  18. data/lib/oedipus/comparison/in.rb +21 -0
  19. data/lib/oedipus/comparison/lt.rb +21 -0
  20. data/lib/oedipus/comparison/lte.rb +21 -0
  21. data/lib/oedipus/comparison/not.rb +25 -0
  22. data/lib/oedipus/comparison/not_equal.rb +21 -0
  23. data/lib/oedipus/comparison/not_in.rb +21 -0
  24. data/lib/oedipus/comparison/outside.rb +21 -0
  25. data/lib/oedipus/comparison/shortcuts.rb +144 -0
  26. data/lib/oedipus/connection.rb +124 -0
  27. data/lib/oedipus/connection/pool.rb +133 -0
  28. data/lib/oedipus/connection/registry.rb +56 -0
  29. data/lib/oedipus/connection_error.rb +14 -0
  30. data/lib/oedipus/index.rb +320 -0
  31. data/lib/oedipus/query_builder.rb +185 -0
  32. data/lib/oedipus/rspec/test_rig.rb +132 -0
  33. data/lib/oedipus/version.rb +12 -0
  34. data/oedipus.gemspec +42 -0
  35. data/spec/data/.gitkeep +0 -0
  36. data/spec/integration/connection/registry_spec.rb +50 -0
  37. data/spec/integration/connection_spec.rb +156 -0
  38. data/spec/integration/index_spec.rb +442 -0
  39. data/spec/spec_helper.rb +16 -0
  40. data/spec/unit/comparison/between_spec.rb +36 -0
  41. data/spec/unit/comparison/equal_spec.rb +22 -0
  42. data/spec/unit/comparison/gt_spec.rb +22 -0
  43. data/spec/unit/comparison/gte_spec.rb +22 -0
  44. data/spec/unit/comparison/in_spec.rb +22 -0
  45. data/spec/unit/comparison/lt_spec.rb +22 -0
  46. data/spec/unit/comparison/lte_spec.rb +22 -0
  47. data/spec/unit/comparison/not_equal_spec.rb +22 -0
  48. data/spec/unit/comparison/not_in_spec.rb +22 -0
  49. data/spec/unit/comparison/not_spec.rb +37 -0
  50. data/spec/unit/comparison/outside_spec.rb +36 -0
  51. data/spec/unit/comparison/shortcuts_spec.rb +125 -0
  52. data/spec/unit/comparison_spec.rb +109 -0
  53. data/spec/unit/query_builder_spec.rb +205 -0
  54. metadata +164 -0
@@ -0,0 +1,58 @@
1
+ /*-- encoding: utf-8 --*/
2
+
3
+ /*
4
+ * Oedipus Sphinx 2 Search.
5
+ * Copyright © 2012 Chris Corbyn.
6
+ *
7
+ * See LICENSE file for details.
8
+ */
9
+
10
+ #include <ruby.h>
11
+ #include <mysql.h>
12
+
13
+ // Macros for lazy fingers
14
+ #define ODP_TO_S(v) rb_funcall(v, rb_intern("to_s"), 0)
15
+ #define ODP_TO_F(n) rb_funcall(n, rb_intern("to_f"), 0)
16
+ #define ODP_KIND_OF_P(v, type) (rb_funcall(v, rb_intern("kind_of?"), 1, type) == Qtrue)
17
+
18
+ /*! Internal struct used to reference a mysql connection */
19
+ typedef struct {
20
+ /*! Boolean representing the connected state */
21
+ int connected;
22
+ /*! The actual pointer allocated by mysql_init() */
23
+ MYSQL * ptr;
24
+ } OdpMysql;
25
+
26
+ /* -- Public methods -- */
27
+
28
+ /*! Allocate and initialize a new mysql client */
29
+ static VALUE odp_new(VALUE klass, VALUE host, VALUE port);
30
+
31
+ /*! Initialize a new mysql client */
32
+ static VALUE odp_initialize(VALUE self, VALUE host, VALUE port);
33
+
34
+ /*! Connect, or reconnect to mysql */
35
+ static VALUE odp_open(VALUE self);
36
+
37
+ /*! Disconnect from mysql */
38
+ static VALUE odp_close(VALUE self);
39
+
40
+ /*! Execute an SQL non-read query and return the number of rows affected */
41
+ static VALUE odp_execute(int argc, VALUE * args, VALUE self);
42
+
43
+ /*! Execute several SQL read queries and return the result sets */
44
+ static VALUE odp_query(int argc, VALUE * args, VALUE self);
45
+
46
+ /* -- Internal methods -- */
47
+
48
+ /*! Generic method to raise a connection error */
49
+ static void odp_raise(VALUE self, const char *msg);
50
+
51
+ /*! Free memory allocated to mysql */
52
+ static void odp_free(OdpMysql * conn);
53
+
54
+ /*! Substitute all ? markers with the values in bind_values */
55
+ static VALUE odp_replace_bind_values(OdpMysql * conn, VALUE sql, VALUE * bind_values, int num_values);
56
+
57
+ /*! Cast the given field to a ruby data type */
58
+ static VALUE odp_cast_value(MYSQL_FIELD f, char * v, unsigned long len);
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ require "oedipus/version"
11
+
12
+ require "oedipus/oedipus"
13
+
14
+ require "oedipus/comparison"
15
+ require "oedipus/comparison/equal"
16
+ require "oedipus/comparison/not_equal"
17
+ require "oedipus/comparison/between"
18
+ require "oedipus/comparison/outside"
19
+ require "oedipus/comparison/in"
20
+ require "oedipus/comparison/not_in"
21
+ require "oedipus/comparison/gte"
22
+ require "oedipus/comparison/gt"
23
+ require "oedipus/comparison/lte"
24
+ require "oedipus/comparison/lt"
25
+ require "oedipus/comparison/not"
26
+ require "oedipus/comparison/shortcuts"
27
+
28
+ require "oedipus/query_builder"
29
+
30
+ require "oedipus/connection_error"
31
+ require "oedipus/connection"
32
+ require "oedipus/connection/pool"
33
+ require "oedipus/connection/registry"
34
+
35
+ require "oedipus/index"
36
+
37
+ module Oedipus
38
+ extend Comparison::Shortcuts
39
+ extend Connection::Registry
40
+ end
@@ -0,0 +1,88 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ module Oedipus
11
+ # Represents a comparison operator and value.
12
+ class Comparison
13
+ class << self
14
+ # Return a suitable comparison object for +v+.
15
+ #
16
+ # The conversions are:
17
+ #
18
+ # - leave Comparison objects unchanged
19
+ # - convert real ranges to Between comparisons
20
+ # - convert Infinity-bounded exclusive ranges to GT/LT comparisons
21
+ # - convert Infinity-bounded inclusive ranges to GTE/LTE comparisons.
22
+ # - convert everything else to an Equal comparison
23
+ #
24
+ # @param [Object] v
25
+ # a ruby object to be compared
26
+ #
27
+ # @param [Comparison]
28
+ # a comparison suitable for comparing the input
29
+ def of(v)
30
+ case v
31
+ when Comparison
32
+ v
33
+ when Range
34
+ if v.end == Float::INFINITY
35
+ v.exclude_end? ? Shortcuts.gt(v.first) : Shortcuts.gte(v.first)
36
+ elsif v.first == -Float::INFINITY
37
+ v.exclude_end? ? Shortcuts.lt(v.end) : Shortcuts.lte(v.end)
38
+ else
39
+ Shortcuts.between(v)
40
+ end
41
+ when Enumerable
42
+ Shortcuts.in(v)
43
+ else
44
+ Shortcuts.eq(v)
45
+ end
46
+ end
47
+ end
48
+
49
+ attr_reader :v
50
+
51
+ # Initialize a new Comparison for +v+.
52
+ #
53
+ # @param [Object] v
54
+ # any ruby object to compare
55
+ def initialize(v)
56
+ @v = v
57
+ end
58
+
59
+ # Compare two comparisons for equality.
60
+ #
61
+ # @param [Comparison] other
62
+ # another comparison to check
63
+ #
64
+ # @return [Boolean]
65
+ # true if the comparisons are the same
66
+ def ==(other)
67
+ other.class == self.class && other.v == v
68
+ end
69
+
70
+ alias_method :eql?, :==
71
+
72
+ # Return the exact inverse of this comparison.
73
+ #
74
+ # @return [Comparison]
75
+ # the inverse of the current comparison
76
+ def inverse
77
+ raise NotImplementedError, "Comparison#inverse must be defined by subclasses"
78
+ end
79
+
80
+ # Represent the comparison as SQL arguments.
81
+ #
82
+ # @return [Array]
83
+ # an SQL expression to compare a LHS against v
84
+ def to_sql
85
+ raise NotImplementedError, "Comparison#to_sql must be defined by subclasses"
86
+ end
87
+ end
88
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ module Oedipus
11
+ # Between comparison of range.
12
+ class Comparison::Between < Comparison
13
+ def to_sql
14
+ ["BETWEEN ? AND ?", v.first, v.exclude_end? ? v.end - 1 : v.end]
15
+ end
16
+
17
+ def inverse
18
+ Comparison::Outside.new(v)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ module Oedipus
11
+ # Equality comparison of value.
12
+ class Comparison::Equal < Comparison
13
+ def to_sql
14
+ ["= ?", v]
15
+ end
16
+
17
+ def inverse
18
+ Comparison::NotEqual.new(v)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ module Oedipus
11
+ # Greater than comparison of +v+.
12
+ class Comparison::GT < Comparison
13
+ def to_sql
14
+ ["> ?", v]
15
+ end
16
+
17
+ def inverse
18
+ Comparison::LTE.new(v)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ module Oedipus
11
+ # Greater than or equal comparison of +v+.
12
+ class Comparison::GTE < Comparison
13
+ def to_sql
14
+ [">= ?", v]
15
+ end
16
+
17
+ def inverse
18
+ Comparison::LT.new(v)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ module Oedipus
11
+ # IN comparison of +v+.
12
+ class Comparison::In < Comparison
13
+ def to_sql
14
+ ["IN (#{v.map{'?'}.join(', ')})", *v]
15
+ end
16
+
17
+ def inverse
18
+ Comparison::NotIn.new(v)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ module Oedipus
11
+ # Less than comparison of +v+.
12
+ class Comparison::LT < Comparison
13
+ def to_sql
14
+ ["< ?", v]
15
+ end
16
+
17
+ def inverse
18
+ Comparison::GTE.new(v)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ module Oedipus
11
+ # Less than or equal comparison of +v+.
12
+ class Comparison::LTE < Comparison
13
+ def to_sql
14
+ ["<= ?", v]
15
+ end
16
+
17
+ def inverse
18
+ Comparison::GT.new(v)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ module Oedipus
11
+ # Negation comparison of value.
12
+ class Comparison::Not < Comparison
13
+ def initialize(v)
14
+ super(Comparison.of(v))
15
+ end
16
+
17
+ def to_sql
18
+ v.inverse.to_sql
19
+ end
20
+
21
+ def inverse
22
+ v
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ module Oedipus
11
+ # Negation comparison of value.
12
+ class Comparison::NotEqual < Comparison
13
+ def to_sql
14
+ ["!= ?", v]
15
+ end
16
+
17
+ def inverse
18
+ Comparison::Equal.new(v)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ module Oedipus
11
+ # NOT IN comparison of +v+.
12
+ class Comparison::NotIn < Comparison
13
+ def to_sql
14
+ ["NOT IN (#{v.map{'?'}.join(', ')})", *v]
15
+ end
16
+
17
+ def inverse
18
+ Comparison::In.new(v)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ module Oedipus
11
+ # Outside comparison of range.
12
+ class Comparison::Outside < Comparison
13
+ def to_sql
14
+ ["NOT BETWEEN ? AND ?", v.first, v.exclude_end? ? v.end - 1 : v.end]
15
+ end
16
+
17
+ def inverse
18
+ Comparison::Between.new(v)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,144 @@
1
+ # encoding: utf-8
2
+
3
+ ##
4
+ # Oedipus Sphinx 2 Search.
5
+ # Copyright © 2012 Chris Corbyn.
6
+ #
7
+ # See LICENSE file for details.
8
+ ##
9
+
10
+ module Oedipus
11
+ class Comparison
12
+ # Provides short methods for casting values to Comparisons.
13
+ module Shortcuts
14
+ extend self
15
+
16
+ # Return the Comparison for equality of +v+.
17
+ #
18
+ # @param [Object] v
19
+ # any ruby object to compare in a query
20
+ #
21
+ # @return [Comparison::Equal]
22
+ # an equality comparison of v
23
+ def eq(v)
24
+ Equal.new(v)
25
+ end
26
+
27
+ # Return the Comparison for inequality of +v+.
28
+ #
29
+ # @param [Object] v
30
+ # any ruby object to compare in a query
31
+ #
32
+ # @return [Comparison::Equal]
33
+ # an inequality comparison of v
34
+ def neq(v)
35
+ NotEqual.new(v)
36
+ end
37
+
38
+ # Return the Comparison for negation of +v+.
39
+ #
40
+ # @param [Object] v
41
+ # any ruby object to compare in a query
42
+ #
43
+ # @return [Comparison::Not]
44
+ # an negated comparison of v
45
+ def not(v)
46
+ Not.new(v)
47
+ end
48
+
49
+ # Return the Comparison for the range a..b.
50
+ #
51
+ # @param [Object] v
52
+ # either a Range, or a number
53
+ #
54
+ # @param [Fixnum] b
55
+ # if the first argument was a number, the other bound
56
+ #
57
+ # @return [Comparison::Between]
58
+ # an between comparison of a..b
59
+ def between(a, b = nil)
60
+ Between.new(a.kind_of?(Range) ? a : a..b)
61
+ end
62
+
63
+ # Return the Comparison to exclude the range a..b.
64
+ #
65
+ # @param [Object] v
66
+ # either a Range, or a number
67
+ #
68
+ # @param [Fixnum] b
69
+ # if the first argument was a number, the other bound
70
+ #
71
+ # @return [Comparison::Outside]
72
+ # an outside comparison of a..b
73
+ def outside(a, b = nil)
74
+ Outside.new(a.kind_of?(Range) ? a : a..b)
75
+ end
76
+
77
+ # Return the Comparison for any value in the set +v+.
78
+ #
79
+ # @param [Object] v
80
+ # any ruby object to compare
81
+ #
82
+ # @return [Comparison::In]
83
+ # the IN comparison for the values in v
84
+ def in(*v)
85
+ In.new(v.map { |el| el.respond_to?(:to_a) ? el.to_a : el }.flatten)
86
+ end
87
+
88
+ # Return the Comparison for any value NOT in the set +v+.
89
+ #
90
+ # @param [Object] v
91
+ # any ruby object to compare
92
+ #
93
+ # @return [Comparison::NotIn]
94
+ # the NOT IN comparison for the values in v
95
+ def not_in(*v)
96
+ NotIn.new(v.map { |el| el.respond_to?(:to_a) ? el.to_a : el }.flatten)
97
+ end
98
+
99
+ # Return the Comparison for >= +v+.
100
+ #
101
+ # @param [Object] v
102
+ # a number to compare
103
+ #
104
+ # @return [Comparison::GTE]
105
+ # a greater than or equal comparison for v
106
+ def gte(v)
107
+ GTE.new(v)
108
+ end
109
+
110
+ # Return the Comparison for > +v+.
111
+ #
112
+ # @param [Object] v
113
+ # a number to compare
114
+ #
115
+ # @return [Comparison::GT]
116
+ # a greater than comparison for v
117
+ def gt(v)
118
+ GT.new(v)
119
+ end
120
+
121
+ # Return the Comparison for <= +v+.
122
+ #
123
+ # @param [Object] v
124
+ # a number to compare
125
+ #
126
+ # @return [Comparison::LTE]
127
+ # a less than or equal comparison for v
128
+ def lte(v)
129
+ LTE.new(v)
130
+ end
131
+
132
+ # Return the Comparison for < +v+.
133
+ #
134
+ # @param [Object] v
135
+ # a number to compare
136
+ #
137
+ # @return [Comparison::LT]
138
+ # a less than comparison for v
139
+ def lt(v)
140
+ LT.new(v)
141
+ end
142
+ end
143
+ end
144
+ end