Skip to content

Commit 1f96c39

Browse files
committed
feat: add source_conditions method
Adds ability to specify WHERE-clause for select query from source tmp-table
1 parent a1d6595 commit 1f96c39

File tree

3 files changed

+78
-0
lines changed

3 files changed

+78
-0
lines changed

lib/redis_counters/dumpers/destination.rb

+15
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,18 @@ class Destination
5858
# Условия соеденяются через AND.
5959
attr_accessor :conditions
6060

61+
# Список дополнительных условий, которые применяются для выборки из source-таблицы для обновления
62+
# target, Array of String.
63+
# Каждое условие представляет собой строку - часть SQL выражения, которое может включать именованные
64+
# параметры из числа доступных в хеше общих параметров дампера: engine.common_params.
65+
# Условия соединяются через AND.
66+
attr_accessor :source_conditions
67+
6168
def initialize(engine)
6269
@engine = engine
6370
@fields_map = HashWithIndifferentAccess.new
6471
@conditions = []
72+
@source_conditions = []
6573
end
6674

6775
def merge
@@ -73,6 +81,7 @@ def merge
7381
(
7482
SELECT #{selected_fields_expression}
7583
FROM #{source_table}
84+
#{source_conditions_expression}
7685
#{group_by_expression}
7786
),
7887
updated AS
@@ -133,6 +142,12 @@ def extra_conditions
133142
result = conditions.map { |condition| "(#{condition})" }.join(' AND ')
134143
result.present? ? "AND #{result}" : result
135144
end
145+
146+
def source_conditions_expression
147+
return if source_conditions.blank?
148+
149+
"WHERE #{source_conditions.map { |source_condition| "(#{source_condition})" }.join(' AND ')}"
150+
end
136151
end
137152
end
138153
end

lib/redis_counters/dumpers/dsl/destination.rb

+4
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ def map(field, target_field)
2828
def condition(value)
2929
destination.conditions << value
3030
end
31+
32+
def source_condition(value)
33+
destination.source_conditions << value
34+
end
3135
end
3236

3337
module ClassMethods

spec/lib/redis_counters/dumpers/engine_spec.rb

+59
Original file line numberDiff line numberDiff line change
@@ -93,5 +93,64 @@
9393
And { expect(StatsAggTotal.count).to eq 2 }
9494
And { expect(StatsAggTotal.where(record_id: 1).first.hits).to eq 6 }
9595
And { expect(StatsAggTotal.where(record_id: 2).first.hits).to eq 2 }
96+
97+
context 'with source conditions' do
98+
let(:dumper) do
99+
RedisCounters::Dumpers::Engine.build do
100+
name :stats_totals
101+
fields record_id: :integer,
102+
column_id: :integer,
103+
value: :integer,
104+
date: :date
105+
106+
destination do
107+
model StatsByDay
108+
take :record_id, :column_id, :hits, :date
109+
key_fields :record_id, :column_id, :date
110+
increment_fields :hits
111+
map :hits, to: :value
112+
condition 'target.date = :date'
113+
source_condition 'column_id = 100'
114+
end
115+
116+
destination do
117+
model StatsTotal
118+
take :record_id, :column_id, :hits
119+
key_fields :record_id, :column_id
120+
increment_fields :hits
121+
map :hits, to: :value
122+
source_condition 'column_id = 100'
123+
end
124+
125+
destination do
126+
model StatsAggTotal
127+
take :record_id, :hits
128+
key_fields :record_id
129+
increment_fields :hits
130+
map :hits, to: 'sum(value)'
131+
group_by :record_id
132+
source_condition 'column_id = 100'
133+
end
134+
135+
on_before_merge do |dumper, _connection|
136+
dumper.common_params = {date: dumper.date.strftime('%Y-%m-%d')}
137+
end
138+
end
139+
end
140+
141+
Then { expect(StatsByDay.count).to eq 4 }
142+
And { expect(StatsByDay.where(record_id: 1, column_id: 100, date: prev_date).first.hits).to eq 1 }
143+
And { expect(StatsByDay.where(record_id: 2, column_id: 100, date: prev_date).first.hits).to eq 1 }
144+
And { expect(StatsByDay.where(record_id: 1, column_id: 100, date: date).first.hits).to eq 1 }
145+
And { expect(StatsByDay.where(record_id: 2, column_id: 100, date: date).first.hits).to eq 1 }
146+
147+
And { expect(StatsTotal.count).to eq 2 }
148+
And { expect(StatsTotal.where(record_id: 1, column_id: 100).first.hits).to eq 2 }
149+
And { expect(StatsTotal.where(record_id: 2, column_id: 100).first.hits).to eq 2 }
150+
151+
And { expect(StatsAggTotal.count).to eq 2 }
152+
And { expect(StatsAggTotal.where(record_id: 1).first.hits).to eq 2 }
153+
And { expect(StatsAggTotal.where(record_id: 2).first.hits).to eq 2 }
154+
end
96155
end
97156
end

0 commit comments

Comments
 (0)