Compare commits

...

8 Commits

Author SHA1 Message Date
Denis Knauf a4ce8a1e6b v0.0.7 2012-07-03 16:28:46 +02:00
Denis Knauf 7f43e9fb86 not compatible to ruby1.8 now! new: ActiveRecordExtensions 2012-07-03 16:28:27 +02:00
Denis Knauf 3d922c5e47 v0.0.6 2012-02-09 14:10:58 +01:00
Denis Knauf 7229fd185c overlaps: key-pairs will be ored 2012-02-09 13:31:24 +01:00
Denis Knauf 08d1610987 optimizer optimized (AND[Or["abc"]] -> "abc"). ()-bugfix in where-clause. 2012-01-18 13:34:26 +01:00
Denis Knauf ce81d21bd8 v0.0.5.2. build-methods renamed to an underscored class-name with suffix _build and aliases build to these methods created. equal_join_build fixed; it never use col.joins.each. #foreigh_key 2012-01-17 10:52:31 +01:00
Denis Knauf fbf5a7019c v0.0.5.1 2012-01-16 12:52:28 +01:00
Denis Knauf 27639e24b7 #join: ",".to_alias OPS! 2012-01-16 12:52:01 +01:00
4 changed files with 79 additions and 46 deletions

View File

@ -1 +1 @@
0.0.5
0.0.7

View File

@ -43,9 +43,9 @@ class SmqlToAR
# Die eigentliche Exception wird in @data[:exception] hinterlegt.
class SubSMQLError < SMQLError
def initialize query, model, exception
ex = {:class => exception.class, :message => exception.message}
ex = {class: exception.class, message: exception.message}
ex[:data] = exception.data if exception.respond_to? :data
super :query => query, :model => model.to_s, :exception => ex
super query: query, model: model.to_s, exception: ex
set_backtrace exception.backtrace
end
end
@ -55,49 +55,49 @@ class SmqlToAR
# Malformed ColOp
class UnexpectedColOpError < ParseError
def initialize model, colop, val
super :got => colop, :val => val, :model => model.to_s
super got: colop, val: val, model: model.to_s
end
end
class UnexpectedError < ParseError
def initialize model, colop, val
super :got => {colop => val}, :model => model.to_s
super got: {colop => val}, model: model.to_s
end
end
class NonExistingSelectableError < SMQLError
def initialize got
super :got => got
super got: got
end
end
class NonExistingColumnError < SMQLError
def initialize expected, got
super :expected => expected, :got => got
super expected: expected, got: got
end
end
class NonExistingRelationError < SMQLError
def initialize expected, got
super :expected => expected, :got => got
super expected: expected, got: got
end
end
class ProtectedColumnError < SMQLError
def initialize protected_column
super :protected_column => protected_column
super protected_column: protected_column
end
end
class RootOnlyFunctionError < SMQLError
def initialize path
super :path => path
super path: path
end
end
class ConColumnError < SMQLError
def initialize expected, got
super :expected => expected, :got => got
super expected: expected, got: got
end
end
@ -243,8 +243,8 @@ class SmqlToAR
refls = model.respond_to?( :reflections) && model.reflections
refls && refls.each do |name, refl|
r[model.name][name] = case refl
when ActiveRecord::Reflection::ThroughReflection then {:macro => refl.macro, :model => refl.klass.name, :through => refl.through_reflection.name}
when ActiveRecord::Reflection::AssociationReflection then {:macro => refl.macro, :model => refl.klass.name}
when ActiveRecord::Reflection::ThroughReflection then {macro: refl.macro, model: refl.klass.name, through: refl.through_reflection.name}
when ActiveRecord::Reflection::AssociationReflection then {macro: refl.macro, model: refl.klass.name}
else raise "Ups: #{refl.class}"
end
models.push refl.klass unless r.keys.include? refl.klass.name
@ -293,8 +293,26 @@ class SmqlToAR
lib_dir = File.dirname __FILE__
fj = lambda {|*a| File.join lib_dir, *a }
Object.send :remove_const, :SmqlToAR
load fj.call( 'smql_to_ar.rb')
load fj.call( 'smql_to_ar', 'condition_types.rb')
load fj.call( 'smql_to_ar', 'query_builder.rb')
load fj[ 'smql_to_ar.rb']
load fj[ 'smql_to_ar', 'condition_types.rb']
load fj[ 'smql_to_ar', 'query_builder.rb']
end
module ActiveRecordExtensions
def self.included base
base.extend ClassMethods
end
module ClassMethods
def smql *params
SmqlToAR.to_ar self, *params
end
def smql_protected
[]
end
end
end
end
ActiveRecord::Base.send :include, SmqlToAR::ActiveRecordExtensions

View File

@ -153,7 +153,7 @@ class SmqlToAR
# 2) {"givenname=", ["Peter", "Hans"]} #=> ( givenname = 'Peter' OR givenname = 'Hans' )
# 3) {"givenname|surname=", ["Peter", "Mueller"]}
# #=> ( givenname = 'Peter' OR surname = 'Peter' ) AND ( givenname = 'Mueller' OR surname = 'Mueller' )
def build builder, table
def condition_build builder, table
values = Hash[ @value.collect {|value| [ builder.vid, value ] } ]
values.each {|k, v| builder.wobs k.to_sym => v }
if 1 == @cols.length
@ -174,6 +174,7 @@ class SmqlToAR
end
self
end
alias build condition_build
end
class NotInRange < Condition
@ -190,7 +191,7 @@ class SmqlToAR
super model, cols, val
end
def build builder, table
def not_in_range_build builder, table
builder.wobs (v1 = builder.vid).to_sym => @value.begin, (v2 = builder.vid).to_sym => @value.end
@cols.each do |col|
col.joins builder, table
@ -198,11 +199,13 @@ class SmqlToAR
end
self
end
alias build not_in_range_build
end
InRange = simple_condition NotInRange, '..', '%s BETWEEN %s AND %s'
class NotOverlaps < Condition
Operator, Where = '<!>', 'NOT (%s, %s) OVERLAPS (%s, %s)'
# Every key-pair will be ORed. No multiple values possible.
class Overlaps < Condition
Operator, Where = '<=>', '(%s, %s) OVERLAPS (%s, %s)'
Expected = [Range, lambda {|val|
Array === val && 2 == val.length &&
[Time, Date, String].any? {|v|v===val[0]} &&
@ -225,7 +228,8 @@ class SmqlToAR
super model, cols, val
end
def build builder, table
def overlaps_build builder, table
builder = Or.new builder
builder.wobs (v1 = builder.vid).to_sym => @value.begin, (v2 = builder.vid).to_sym => @value.end
v1 = "TIMESTAMP #{v1}"
v2 = "TIMESTAMP #{v2}"
@ -236,15 +240,16 @@ class SmqlToAR
builder.column( table+f.path, f.col), builder.column( table+s.path, s.col), v1, v2]
end
end
alias build overlaps_build
end
Overlaps = simple_condition NotOverlaps, '<=>', '(%s, %s) OVERLAPS (%s, %s)'
NotOverlaps = simple_condition Overlaps, '<=>', 'NOT (%s, %s) OVERLAPS (%s, %s)'
class NotIn < Condition
Operator = '!|='
Where = "%s NOT IN (%s)"
Expected = [Array]
def build builder, table
def not_in_build builder, table
builder.wobs (v = builder.vid).to_sym => @value
@cols.each do |col|
col.joins builder, table
@ -252,6 +257,7 @@ class SmqlToAR
end
self
end
alias build not_in_build
end
In = simple_condition NotIn, '|=', '%s IN (%s)', [Array]
@ -290,7 +296,7 @@ class SmqlToAR
raise_unless col.relation, NonExistingRelationError.new( %w[Relation], col)
end
def build builder, table
def equal_join_build builder, table
if 2 < @cols.first.second.length
b2, b3 = And, Or
else
@ -300,7 +306,7 @@ class SmqlToAR
@cols.each do |col, sub|
model, *sub = sub
t = table + col.path + [col.col]
col.joins.each {|j, m| builder.joins table+j, m }
col.joins builder, table
builder.joins t, model
b4 = b3.new( b2)
sub.each do |i|
@ -310,6 +316,7 @@ class SmqlToAR
end
self
end
alias build equal_join_build
end
# Takes to Queries.
@ -339,7 +346,7 @@ class SmqlToAR
raise_unless col.child?, ConColumnError.new( [:Column], col)
end
def build builder, table
def sub_equal_join_build builder, table
@cols.each do |col, sub|
t = table+col.to_a
builder.sub_joins t, col, *sub[0..1]
@ -348,6 +355,7 @@ class SmqlToAR
end
self
end
alias build sub_equal_join_build
end
=end
@ -372,7 +380,7 @@ class SmqlToAR
raise_unless col.exist_in? || SmqlToAR.model_of( col.last_model, col.col), NonExistingSelectableError.new( col)
end
def build builder, table
def select_build builder, table
@cols.each do |col|
if col.exist_in?
col.joins builder, table
@ -384,6 +392,7 @@ class SmqlToAR
end
self
end
alias build select_build
end
class Functions < Condition
@ -432,7 +441,7 @@ class SmqlToAR
super model, func, args
end
def build builder, table
def order_build builder, table
return if @args.blank?
@args.each do |o|
col, o = o
@ -442,26 +451,29 @@ class SmqlToAR
builder.order t, col.col, o
end
end
alias build order_build
end
class Limit < Function
Name = :limit
Expected = [Fixnum]
def build builder, table
def limit_build builder, table
raise_unless 1 == table.length, RootOnlyFunctionError.new( table)
builder.limit = Array.wrap(@args).first.to_i
end
alias build limit_build
end
class Offset < Function
Name = :offset
Expected = [Fixnum]
def build builder, table
def offset_build builder, table
raise_unless 1 == table.length, RootOnlyFunctionError.new( table)
builder.offset = Array.wrap(@args).first.to_i
end
alias build offset_build
end
def self.new model, col, val

View File

@ -135,25 +135,25 @@ class SmqlToAR
case refl
when ActiveRecord::Reflection::ThroughReflection
through = refl.through_reflection
throughtable = table[0...-1]+[Column::Col.new( through.name, table.last.as)]
srctable = throughtable+[Column::Col.new( refl.source_reflection.name, table.last.as)]
through_table = table[0...-1]+[Column::Col.new( through.name, table.last.as)]
srctable = through_table+[Column::Col.new( refl.source_reflection.name, table.last.as)]
@table_model[ srctable] = model
@table_alias[ table] = @table_alias[ srctable]
join_ throughtable, through.klass, quote_table_name( through.table_name)
join_ srctable, refl.klass, query, throughtable
join_ through_table, through.klass, quote_table_name( through.table_name)
join_ srctable, refl.klass, query, through_table
when ActiveRecord::Reflection::AssociationReflection
case refl.macro
when :has_many, :has_one
@_joins += build_join query, pretable, t, premodel.primary_key, refl.primary_key_name
@_joins += build_join query, pretable, t, premodel.primary_key, refl.foreign_key
when :belongs_to
@_joins += build_join query, pretable, t, refl.primary_key_name, premodel.primary_key
@_joins += build_join query, pretable, t, refl.foreign_key, premodel.primary_key
when :has_and_belongs_to_many
jointable = [','] + table
@_joins += build_join refl.options[:join_table], pretable, @table_alias[jointable], premodel.primary_key, refl.primary_key_name
jointable = [Column::Col.new(',')] + table
@_joins += build_join refl.options[:join_table], pretable, @table_alias[ jointable], premodel.primary_key, refl.foreign_key
@_joins += build_join query, jointable, t, refl.association_foreign_key, refl.association_primary_key
else raise BuilderError, "Unkown reflection macro: #{refl.macro.inspect}"
end
else raise BuilderError, "Unkown reflection type: #{refl.class.name}"
else raise BuilderError, "Unkown reflection type: #{refl.class.name} #{refl.macro.inspect}"
end
self
end
@ -248,12 +248,14 @@ class SmqlToAR
def optimize!
ext = []
collect! do |sub|
sub = sub.optimize! if sub.kind_of? Array
sub = sub.optimize! if sub.kind_of? SubBuilder
if self.class == sub.class
ext.push *sub
nil
elsif sub.blank?
nil
elsif 1 == sub.size
sub.first
else
sub
end
@ -267,21 +269,22 @@ class SmqlToAR
end
def default() SmqlToAR::And end
def default_new( parent) default.new self, parent, false end
def collect_build_where
collect {|x| x.respond_to?( :build_where) ? x.build_where : x.to_s }
def collect_build_where indent = nil
indent = (indent||0) + 1
collect {|x| "(#{x.respond_to?( :build_where) ? x.build_where( indent) : x.to_s})" }
end
end
class And < SubBuilder
def default; SmqlToAR::Or; end
def build_where
collect_build_where.join ' AND '
def build_where indent = nil
collect_build_where( indent).join " AND\n"+"\t"*(indent||0)
end
end
class Or < SubBuilder
def build_where
collect_build_where.join ' OR '
def build_where indent = nil
collect_build_where( indent).join " OR\n"+"\t"*(indent||0)
end
end
end