flounder 0.14.0 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY +3 -0
- data/flounder.gemspec +1 -1
- data/lib/flounder/domain.rb +5 -2
- data/lib/flounder/entity.rb +9 -0
- data/lib/flounder/expression.rb +61 -3
- data/lib/flounder/query/base.rb +8 -8
- data/qed/expressions.md +9 -3
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9f4ec6bd3fa4f14eccf7efa8d3aed4e81a3d8e08
|
4
|
+
data.tar.gz: cba009f5dc2b519b4636b643b7ac1d02bd9a493c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 81a859be8701dc7aa497f17949ed8bb8db93cb22daaba9c24796d5d225ef4cfd936174f132648bde9755d67b4aa15c92db2c09e404fec28280e4db62d3fa302b
|
7
|
+
data.tar.gz: 85f24647fe87ddd7a788df1f0722811fd828d4e0c5c570c6ac295e40d9ef6d4e5fb3ead5526a20bf35566f2132638c7b355ba0e1291697e79c20f8c63a6d9c38
|
data/HISTORY
CHANGED
data/flounder.gemspec
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "flounder"
|
5
|
-
s.version = '0.
|
5
|
+
s.version = '0.15.0'
|
6
6
|
s.summary = "Flounder is a way to write SQL simply in Ruby. It deals with everything BUT object relational mapping. "
|
7
7
|
s.email = "kaspar.schiess@technologyastronauts.ch"
|
8
8
|
s.homepage = "https://bitbucket.org/technologyastronauts/oss_flounder"
|
data/lib/flounder/domain.rb
CHANGED
@@ -50,9 +50,12 @@ module Flounder
|
|
50
50
|
end
|
51
51
|
|
52
52
|
# Builds an SQL expression.
|
53
|
+
#
|
54
|
+
# domain.expr { concat('1', '2') }
|
53
55
|
#
|
54
|
-
def expr
|
55
|
-
Expression::Builder.new(self
|
56
|
+
def expr &block
|
57
|
+
builder = Expression::Builder.new(self)
|
58
|
+
builder.call(&block)
|
56
59
|
end
|
57
60
|
|
58
61
|
# Returns an aggregate of all query wall clock times. Please see
|
data/lib/flounder/entity.rb
CHANGED
@@ -66,6 +66,15 @@ module Flounder
|
|
66
66
|
end
|
67
67
|
alias to_s inspect
|
68
68
|
|
69
|
+
# Builds a condition part or a general SQL expression.
|
70
|
+
#
|
71
|
+
# entity.cond(a: 1)
|
72
|
+
#
|
73
|
+
def cond *conditions
|
74
|
+
builder = Expression::Builder.new(domain)
|
75
|
+
builder.interpret_conditions(self, conditions)
|
76
|
+
end
|
77
|
+
|
69
78
|
# Starts a new select query and yields it to the block. Note that you don't
|
70
79
|
# need to call this method to obtain a select query - any of the methods
|
71
80
|
# on Query::Select should work on the entity and return a new query object.
|
data/lib/flounder/expression.rb
CHANGED
@@ -11,6 +11,12 @@ module Flounder::Expression
|
|
11
11
|
def cast type
|
12
12
|
Cast.new(@domain, type, self)
|
13
13
|
end
|
14
|
+
def | expr
|
15
|
+
BinaryOp.new(@domain, 'OR', self, expr)
|
16
|
+
end
|
17
|
+
def & expr
|
18
|
+
BinaryOp.new(@domain, 'AND', self, expr)
|
19
|
+
end
|
14
20
|
|
15
21
|
def eval argument
|
16
22
|
case argument
|
@@ -83,18 +89,70 @@ module Flounder::Expression
|
|
83
89
|
end
|
84
90
|
end
|
85
91
|
|
92
|
+
class ConditionBit < Expr
|
93
|
+
def initialize domain, engine, bit
|
94
|
+
super(domain)
|
95
|
+
@engine = engine
|
96
|
+
@bit = bit
|
97
|
+
end
|
98
|
+
|
99
|
+
attr_accessor :bit, :engine
|
100
|
+
|
101
|
+
def to_sql
|
102
|
+
bit.to_sql(engine)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
class BinaryOp < Expr
|
107
|
+
def initialize domain, op_string, *terms
|
108
|
+
super(domain)
|
109
|
+
|
110
|
+
@op_string = op_string
|
111
|
+
@terms = terms
|
112
|
+
end
|
113
|
+
|
114
|
+
attr_accessor :op_string
|
115
|
+
|
116
|
+
def concat term
|
117
|
+
@terms << term
|
118
|
+
end
|
119
|
+
|
120
|
+
def to_sql
|
121
|
+
"(" +
|
122
|
+
@terms.
|
123
|
+
map { |t| eval(t) }.
|
124
|
+
join(" #{op_string} ") +
|
125
|
+
")"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
86
129
|
class Builder
|
87
|
-
def initialize domain
|
130
|
+
def initialize domain
|
88
131
|
@domain = domain
|
89
|
-
@context = context
|
90
132
|
end
|
91
133
|
|
92
|
-
attr_accessor :domain
|
134
|
+
attr_accessor :domain
|
93
135
|
|
94
136
|
def call &block
|
95
137
|
instance_eval(&block)
|
96
138
|
end
|
97
139
|
|
140
|
+
# Conditions are interpreted relative to an entity.
|
141
|
+
def interpret_conditions entity, conditions
|
142
|
+
# The method we need is in there...
|
143
|
+
query = Flounder::Query::Select.new(domain, entity)
|
144
|
+
engine = Flounder::Engine.new(domain.connection_pool)
|
145
|
+
|
146
|
+
and_expr = BinaryOp.new(domain, 'AND')
|
147
|
+
|
148
|
+
# TODO parse_conditions and its call tree is not really something that
|
149
|
+
# belongs into the query object - we should create a new abstraction here.
|
150
|
+
query.parse_conditions(*conditions) { |bit|
|
151
|
+
and_expr.concat(ConditionBit.new(domain, engine, bit)) }
|
152
|
+
|
153
|
+
and_expr
|
154
|
+
end
|
155
|
+
|
98
156
|
def respond_to? sym, include_all=false
|
99
157
|
true
|
100
158
|
end
|
data/lib/flounder/query/base.rb
CHANGED
@@ -81,14 +81,6 @@ module Flounder::Query
|
|
81
81
|
domain.log_bm measure
|
82
82
|
end
|
83
83
|
|
84
|
-
private
|
85
|
-
# Prepares a kick - meaning an execution on the database or a transform
|
86
|
-
# to an sql string. Ready Set...
|
87
|
-
#
|
88
|
-
def prepare_kick
|
89
|
-
# should be overridden
|
90
|
-
end
|
91
|
-
|
92
84
|
# Parses a conditions array like it is found with #where and #having and
|
93
85
|
# calls the block for each condition bit. Returns self.
|
94
86
|
#
|
@@ -126,6 +118,14 @@ module Flounder::Query
|
|
126
118
|
end
|
127
119
|
return self
|
128
120
|
end
|
121
|
+
|
122
|
+
private
|
123
|
+
# Prepares a kick - meaning an execution on the database or a transform
|
124
|
+
# to an sql string. Ready Set...
|
125
|
+
#
|
126
|
+
def prepare_kick
|
127
|
+
# should be overridden
|
128
|
+
end
|
129
129
|
|
130
130
|
# Rewrites a statement that contains bind placeholders like '$1' to
|
131
131
|
# contain placeholders starting at offset+1. Also checks that no
|
data/qed/expressions.md
CHANGED
@@ -4,8 +4,14 @@
|
|
4
4
|
Flounder also helps with the writing of complex SQL expressions.
|
5
5
|
|
6
6
|
~~~ruby
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
users = domain[:users]
|
8
|
+
domain.expr { a(b(c(1, ' ', users[:id]))) }.cast('int').as(:foo).
|
9
|
+
assert generates_sql("a(b(c(1, ' ', \"users\".\"id\")))::int AS foo")
|
10
10
|
~~~
|
11
11
|
|
12
|
+
You can also pass a condition-like hash to expr directly, it will return a Ruby object that allows for chaining.
|
13
|
+
|
14
|
+
~~~ruby
|
15
|
+
(users.cond(:posts, a: 1) | users.cond(a: 2)).
|
16
|
+
assert generates_sql("((\"posts\".\"a\" = 1) OR (\"users\".\"a\" = 2))")
|
17
|
+
~~~
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flounder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.15.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kaspar Schiess
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-10-
|
12
|
+
date: 2014-10-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: arel
|