aliased tables. firm: { "people[users]": {type: "User"}, "people[old]": {"age>:": 50 } # Every ToDo which has a User as Person or people older than 50. It is not an OR, it is an AND, but {people:{type:"User","age>":50}} or {"people":{type:"User"},"people":{"age>:":50} means every User older than 50. "users" and "old" are independet questions and both must be present, if firm should be true.
This commit is contained in:
parent
8eebb3ac1f
commit
69aceef180
|
@ -107,9 +107,9 @@ class SmqlToAR
|
|||
|
||||
# Model der Relation `rel` von `model`
|
||||
def self.model_of model, rel
|
||||
rel = rel.to_sym
|
||||
r = model.reflections[ rel].andand.klass
|
||||
r.nil? && :self == rel ? model : r
|
||||
p model_of: rel.to_sym, model: model
|
||||
r = model.reflections[ rel.to_sym].andand.klass
|
||||
r.nil? && rel === :self ? model : r
|
||||
end
|
||||
|
||||
# Eine Spalte in einer Tabelle, relativ zu `Column#model`.
|
||||
|
@ -120,10 +120,43 @@ class SmqlToAR
|
|||
attr_reader :path, :col
|
||||
attr_accessor :model
|
||||
|
||||
class Col
|
||||
attr_accessor :col, :as
|
||||
def initialize col, as = nil
|
||||
if col.kind_of? Col
|
||||
@col, @as = col.col, col.as
|
||||
elsif /^(.*?)\[(.*)\]$/ =~ col.to_s
|
||||
@col, @as = $1, $2
|
||||
else
|
||||
@col, @as = col.to_s, as.to_s
|
||||
@as = nil if @as.blank?
|
||||
end
|
||||
end
|
||||
|
||||
def to_s() @col end
|
||||
def to_sym() to_s.to_sym end
|
||||
def inspect() "#{@col}[@#{@as}]" end
|
||||
def to_alias() "#{@col}[#{@as}]" end
|
||||
|
||||
def == other
|
||||
other = Col.new other
|
||||
@col = other.col && @as == other.col
|
||||
end
|
||||
|
||||
def === other
|
||||
other = Col.new other
|
||||
@col == other.col
|
||||
end
|
||||
end
|
||||
|
||||
def initialize model, *col
|
||||
@model = model
|
||||
@last_model = nil
|
||||
*@path, @col = *Array.wrap( col).collect( &it.to_s.split( /[.\/]/)).flatten.collect( &:to_sym).reject( &it==:self)
|
||||
*@path, @col = *Array.wrap( col).
|
||||
collect( &it.to_s.split( /[.\/]/)).
|
||||
flatten.
|
||||
collect( &Col.method( :new)).
|
||||
reject( &it===:self)
|
||||
end
|
||||
|
||||
def last_model
|
||||
|
@ -132,9 +165,10 @@ class SmqlToAR
|
|||
|
||||
def each
|
||||
model = @model
|
||||
p each: self, path: @path
|
||||
@path.each do |rel|
|
||||
rel = rel.to_sym
|
||||
unless :self == rel
|
||||
p rel: rel
|
||||
unless rel === :self
|
||||
model = SmqlToAR.model_of model, rel
|
||||
return false unless model
|
||||
yield rel, model
|
||||
|
@ -169,6 +203,7 @@ class SmqlToAR
|
|||
exe.call pp, model
|
||||
end
|
||||
end
|
||||
|
||||
def self?() !@col end
|
||||
def length() @path.length+(self.self? ? 0 : 1) end
|
||||
def size() @path.size+(self.self? ? 0 : 1) end
|
||||
|
|
|
@ -56,9 +56,11 @@ class SmqlToAR
|
|||
r = nil
|
||||
#p :try_parse => { :model => model, :colop => colop, :value => val }
|
||||
conditions.each do |c|
|
||||
raise_unless colop =~ /^(?:\d*:)?(.*?)(\W*)$/, UnexpectedColOpError.new( model, colop, val)
|
||||
raise_unless colop =~ /^(?:\d*:)?(.*?)((?:\W*(?!\])\W)?)$/, UnexpectedColOpError.new( model, colop, val)
|
||||
col, op = $1, $2
|
||||
p col: col, op: op
|
||||
col = split_keys( col).collect {|c| Column.new model, c }
|
||||
p col: col
|
||||
r = c.try_parse model, col, op, val
|
||||
break if r
|
||||
end
|
||||
|
@ -246,6 +248,7 @@ class SmqlToAR
|
|||
model, *sub = sub
|
||||
t = table + col.path + [col.col]
|
||||
col.joins.each {|j, m| builder.joins table+j, m }
|
||||
p build_t: t
|
||||
builder.joins t, model
|
||||
b2 = 1 == sub.length ? builder : Or.new( builder)
|
||||
sub.each {|i| i.collect( &it.build( And.new( b2), t)); p 'or' => b2 }
|
||||
|
|
|
@ -28,20 +28,27 @@ class SmqlToAR
|
|||
def to_i() @vid end
|
||||
end
|
||||
|
||||
class Aliases < Hash
|
||||
def self.new prefix, *a, &e
|
||||
e ||= lambda do |h, k|
|
||||
j = Array.wrap( k).compact
|
||||
h[k] = h.key?(j) ? h[j] : "#{prefix},#{j.collect( &:to_alias).join( ',')}"
|
||||
end
|
||||
super *a, &e
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :table_alias, :model, :table_model, :base_table, :_where, :_select, :_wobs, :_joins, :prefix, :_vid
|
||||
attr_accessor :logger, :limit, :offset
|
||||
|
||||
def initialize model, prefix = nil
|
||||
@prefix = "smql"
|
||||
@logger = SmqlToAR.logger
|
||||
@table_alias = Hash.new do |h, k|
|
||||
j = Array.wrap( k).compact
|
||||
h[k] = h.key?(j) ? h[j] : "#{@prefix},#{j.join(',')}"
|
||||
end
|
||||
@table_alias = Aliases.new @prefix
|
||||
@_vid, @_where, @_wobs, @model, @quoter = 0, SmqlToAR::And[], {}, model, model.connection
|
||||
@base_table = [model.table_name.to_sym]
|
||||
@base_table = [Column::Col.new( model.table_name)]
|
||||
@table_alias[ @base_table] = @base_table.first
|
||||
t = quote_table_name @table_alias[ @base_table]
|
||||
t = quote_table_name @base_table.first.col
|
||||
@_select, @_joins, @_joined, @_includes, @_order = ["DISTINCT #{t}.*"], "", [@base_table], [], []
|
||||
@table_model = {@base_table => @model}
|
||||
end
|
||||
|
@ -49,7 +56,7 @@ class SmqlToAR
|
|||
def vid() Vid.new( @_vid+=1) end
|
||||
|
||||
def inspect
|
||||
"#<#{self.class.name}:#{"0x%x"% (self.object_id<<1)}|#{@prefix}:#{@base_table}:#{@model} vid=#{@_vid} where=#{@_where} wobs=#{@_wobs} select=#{@_select} aliases=#{@_table_alias}>"
|
||||
"#<#{self.class.name}:#{"0x%x"% (self.object_id<<1)}|#{@prefix}:#{@base_table}:#{@model} vid=#{@_vid} where=#{@_where} wobs=#{@_wobs} select=#{@_select} aliases=#{@table_alias}>"
|
||||
end
|
||||
|
||||
# Jede via where uebergebene Condition wird geodert und alle zusammen werden geundet.
|
||||
|
@ -71,14 +78,19 @@ class SmqlToAR
|
|||
end
|
||||
|
||||
def quote_table_name name
|
||||
name = case name
|
||||
when Array, Column::Col then @table_alias[Array.wrap name]
|
||||
else name.to_s
|
||||
end
|
||||
@quoter.quote_table_name( name).gsub /"\."/, ','
|
||||
end
|
||||
|
||||
def column table, name
|
||||
"#{quote_table_name table.kind_of?(String) ? table : @table_alias[table]}.#{quote_column_name name}"
|
||||
"#{quote_table_name table}.#{quote_column_name name}"
|
||||
end
|
||||
|
||||
def build_join orig, pretable, table, prekey, key
|
||||
p build_join: {orig: orig, pretable: pretable, table: table, prekey: prekey, key: key}, alias: @table_alias
|
||||
" LEFT JOIN #{orig} AS #{quote_table_name table} ON #{column pretable, prekey} = #{column table, key} "
|
||||
end
|
||||
|
||||
|
@ -92,13 +104,14 @@ class SmqlToAR
|
|||
@table_model[ table] = model
|
||||
premodel = @table_model[ pretable]
|
||||
t = @table_alias[ table]
|
||||
pt = quote_table_name @table_alias[ table[ 0...-1]]
|
||||
refl = premodel.reflections[table.last]
|
||||
pt = quote_table_name table[ 0...-1]
|
||||
p table: table
|
||||
refl = premodel.reflections[table.last.to_sym]
|
||||
case refl
|
||||
when ActiveRecord::Reflection::ThroughReflection
|
||||
through = refl.through_reflection
|
||||
throughtable = table[0...-1]+[through.name.to_sym]
|
||||
srctable = throughtable+[refl.source_reflection.name]
|
||||
throughtable = table[0...-1]+[Column::Col.new( through.name, table.last.as)]
|
||||
srctable = throughtable+[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)
|
||||
|
|
Loading…
Reference in a new issue