smql 0.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/lib/smql_to_ar.rb ADDED
@@ -0,0 +1,213 @@
1
+ # SmqlToAR - Base library: Converts SMQL to ActiveRecord
2
+ # Copyright (C) 2011 Denis Knauf
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ class SmqlToAR
18
+ include ActiveSupport::Benchmarkable
19
+ ############################################################################r
20
+ # Exceptions
21
+
22
+ class SMQLError < Exception
23
+ attr_reader :data
24
+ def initialize data
25
+ @data = data
26
+ super data.inspect
27
+ end
28
+ end
29
+
30
+ # Ein Fehler ist in einem Subquery aufgetreten.
31
+ # Die eigentliche Exception wird in @data[:exception] hinterlegt.
32
+ class SubSMQLError < SMQLError
33
+ def initialize query, model, exception
34
+ ex = {:class => exception.class, :message => exception.message}
35
+ ex[:data] = exception.data if exception.respond_to? :data
36
+ super :query => query, :model => model.to_s, :exception => ex
37
+ set_backtrace exception.backtrace
38
+ end
39
+ end
40
+
41
+ class ParseError < SMQLError; end
42
+
43
+ # Malformed ColOp
44
+ class UnexpectedColOpError < ParseError
45
+ def initialize model, colop, val
46
+ super :got => colop, :val => val, :model => model.to_s
47
+ end
48
+ end
49
+
50
+ class UnexpectedError < ParseError
51
+ def initialize model, colop, val
52
+ super :got => {colop => val}, :model => model.to_s
53
+ end
54
+ end
55
+
56
+ class NonExistingSelectableError < SMQLError
57
+ def initialize got
58
+ super :got => got
59
+ end
60
+ end
61
+
62
+ class NonExistingColumnError < SMQLError
63
+ def initialize expected, got
64
+ super :expected => expected, :got => got
65
+ end
66
+ end
67
+
68
+ class NonExistingRelationError < SMQLError
69
+ def initialize expected, got
70
+ super :expected => expected, :got => got
71
+ end
72
+ end
73
+
74
+ class ProtectedColumnError < SMQLError
75
+ def initialize protected_column
76
+ super :protected_column => protected_column
77
+ end
78
+ end
79
+
80
+ class OnlyOrderOnBaseError < SMQLError
81
+ def initialize path
82
+ super :path => path
83
+ end
84
+ end
85
+
86
+ class BuilderError < Exception; end
87
+
88
+ #############################################################################
89
+
90
+ # Model der Relation `rel` von `model`
91
+ def self.model_of model, rel
92
+ model.reflections[ rel.to_sym].andand.klass
93
+ end
94
+
95
+ # Eine Spalte in einer Tabelle, relativ zu `Column#model`.
96
+ # Kann auch einen Pfad `Column#path` haben, wobei `Column#col` dann
97
+ # eine Relation von dem Model der letzten Relation von `Column#path` ist.
98
+ class Column
99
+ include Enumerable
100
+ attr_reader :path, :col
101
+ attr_accessor :model
102
+
103
+ def initialize model, *col
104
+ @model = model
105
+ @last_model = nil
106
+ *@path, @col = Array.wrap( col).collect {|s| s.to_s.split /[.\/]/ }.flatten.collect &:to_sym
107
+ end
108
+
109
+ def last_model
110
+ @last_model ||= each{}
111
+ end
112
+
113
+ def each
114
+ model = @model
115
+ @path.each do |rel|
116
+ model = SmqlToAR.model_of model, rel
117
+ return false unless model
118
+ yield rel, model
119
+ end
120
+ model
121
+ end
122
+
123
+ def exist_in?
124
+ model = last_model
125
+ return false unless model
126
+ model.column_names.include? @col.to_s
127
+ end
128
+
129
+ def protected?
130
+ model = @model
131
+ each do |rel, _model|
132
+ pr = Array.wrap model.respond_to?( :smql_protected) ? model.smql_protected : nil
133
+ pr.include? rel.to_s
134
+ model = _model
135
+ end
136
+ pr = Array.wrap model.respond_to?( :smql_protected) ? model.smql_protected : nil
137
+ pr.include? @col.to_s
138
+ end
139
+
140
+ def joins builder = nil, table = nil, &exe
141
+ pp = []
142
+ table = Array.wrap table
143
+ exe ||= builder ? lambda {|j, m| builder.join table+j, m} : Array.method( :[])
144
+ collect do |rel, model|
145
+ pp.push rel
146
+ exe.call pp, model
147
+ end
148
+ end
149
+ def to_a() @path+[@col] end
150
+ def to_s() to_a.join '.' end
151
+ def to_sym() to_s.to_sym end
152
+ def to_json() to_s end
153
+ def inspect() "#<Column: #{model} #{to_s}>" end
154
+ def relation() SmqlToAR.model_of last_model, @col end
155
+ def allowed?() ! self.protected? end
156
+ end
157
+
158
+ attr_reader :model, :query, :conditions, :builder, :order
159
+ attr_accessor :logger
160
+ @@logger = if Object.const_defined?( :Rails)
161
+ Rails.logger
162
+ else
163
+ require 'logger'
164
+ Logger.new $stdout
165
+ end
166
+
167
+ class <<self
168
+ def logger=(logger) @@logger = logger end
169
+ def logger() @@logger end
170
+ end
171
+
172
+ def initialize model, query, order = nil
173
+ query = JSON.parse query if query.kind_of? String
174
+ @model, @query, @logger, @order = model, query, @@logger, order
175
+ #p model: @model, query: @query
176
+ end
177
+
178
+ def parse
179
+ benchmark 'SMQL parse' do
180
+ @conditions = ConditionTypes.try_parse @model, @query
181
+ end
182
+ #p conditions: @conditions
183
+ self
184
+ end
185
+
186
+ def build
187
+ benchmark 'SMQL build query' do
188
+ @builder = QueryBuilder.new @model
189
+ table = @builder.base_table
190
+ @conditions.each {|condition| condition.build builder, table }
191
+ end
192
+ #p builder: @builder
193
+ self
194
+ end
195
+
196
+ def ar
197
+ @ar ||= benchmark 'SMQL ar' do
198
+ @builder.to_ar
199
+ end
200
+ end
201
+
202
+ def to_ar
203
+ benchmark 'SMQL' do
204
+ parse
205
+ build
206
+ ar.tap {|ar| logger.info ar.to_sql }
207
+ end
208
+ end
209
+
210
+ def self.to_ar *params
211
+ new( *params).to_ar
212
+ end
213
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: smql
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 0
9
+ version: 0.0.0
10
+ platform: ruby
11
+ authors:
12
+ - Denis Knauf
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2011-09-08 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activerecord
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ segments:
29
+ - 0
30
+ version: "0"
31
+ type: :runtime
32
+ version_requirements: *id001
33
+ - !ruby/object:Gem::Dependency
34
+ name: activesupport
35
+ prerelease: false
36
+ requirement: &id002 !ruby/object:Gem::Requirement
37
+ none: false
38
+ requirements:
39
+ - - ">="
40
+ - !ruby/object:Gem::Version
41
+ segments:
42
+ - 0
43
+ version: "0"
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: json
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ segments:
55
+ - 0
56
+ version: "0"
57
+ type: :runtime
58
+ version_requirements: *id003
59
+ description: SMQL is a JSON-based query langauage similar to MQL. This gem convertes these querys to ActiveRecord.
60
+ email:
61
+ - Denis.Knauf@gmail.com
62
+ executables: []
63
+
64
+ extensions: []
65
+
66
+ extra_rdoc_files:
67
+ - LICENSE
68
+ - README.md
69
+ - TODO
70
+ files:
71
+ - AUTHORS
72
+ - LICENSE
73
+ - README.md
74
+ - VERSION
75
+ - lib/smql.rb
76
+ - lib/smql_to_ar.rb
77
+ - lib/smql_to_ar/condition_types.rb
78
+ - lib/smql_to_ar/query_builder.rb
79
+ - TODO
80
+ has_rdoc: true
81
+ homepage: http://github.com/DenisKnauf/smql
82
+ licenses: []
83
+
84
+ post_install_message:
85
+ rdoc_options: []
86
+
87
+ require_paths:
88
+ - lib
89
+ required_ruby_version: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ segments:
95
+ - 0
96
+ version: "0"
97
+ required_rubygems_version: !ruby/object:Gem::Requirement
98
+ none: false
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ segments:
103
+ - 0
104
+ version: "0"
105
+ requirements: []
106
+
107
+ rubyforge_project:
108
+ rubygems_version: 1.3.7
109
+ signing_key:
110
+ specification_version: 3
111
+ summary: JSON-based query language "SMQL" to ActiveRecord converter
112
+ test_files: []
113
+