occams-record 1.0.0.rc10 → 1.0.0.rc11
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.
- checksums.yaml +4 -4
- data/README.md +9 -1
- data/lib/occams-record.rb +1 -0
- data/lib/occams-record/eager_loaders/ad_hoc_base.rb +2 -2
- data/lib/occams-record/eager_loaders/base.rb +2 -2
- data/lib/occams-record/eager_loaders/context.rb +2 -2
- data/lib/occams-record/eager_loaders/polymorphic_belongs_to.rb +2 -2
- data/lib/occams-record/eager_loaders/through.rb +2 -2
- data/lib/occams-record/measureable.rb +63 -0
- data/lib/occams-record/query.rb +14 -4
- data/lib/occams-record/raw_query.rb +19 -4
- data/lib/occams-record/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a507ce21c11a7303250948fdcb29fdf9e6422968609b4915bfcd6800dfe7789c
|
4
|
+
data.tar.gz: b4fab3a88d28a742fed134800dde46c2919e400f04e93d427871dff349e36e76
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: df7f2eb7c4f0181c8ad6d0f6b8a9d9c40bc23132578768dece1cd13fbc064b42db32678908a5701eb5493955035fb7bef9fae0cabc236e041dde4213f9594191
|
7
|
+
data.tar.gz: ac478403eb241853853465c1002f3ba804cbe0bb942f3379a42c0df5252852f1f959f3a9d7082d110536d92171d853656c8c273a724ff33f0274960d78d107c3
|
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# Occams Record [](https://travis-ci.org/jhollinger/occams-record)
|
2
2
|
|
3
3
|
> Do not multiply entities beyond necessity. -- Occam's Razor
|
4
4
|
|
@@ -259,3 +259,11 @@ bundle exec rake test
|
|
259
259
|
```
|
260
260
|
|
261
261
|
Look inside `Gemfile` to see all testable versions.
|
262
|
+
|
263
|
+
# License
|
264
|
+
|
265
|
+
MIT License. See LICENSE for details.
|
266
|
+
|
267
|
+
# Copyright
|
268
|
+
|
269
|
+
Copywrite (c) 2019 Jordan Hollinger.
|
data/lib/occams-record.rb
CHANGED
@@ -35,11 +35,11 @@ module OccamsRecord
|
|
35
35
|
# @param rows [Array<OccamsRecord::Results::Row>] Array of rows used to calculate the query.
|
36
36
|
# @param query_logger [Array<String>]
|
37
37
|
#
|
38
|
-
def run(rows, query_logger: nil)
|
38
|
+
def run(rows, query_logger: nil, measurements: nil)
|
39
39
|
fkey_binds = calc_fkey_binds rows
|
40
40
|
assoc = if fkey_binds.any? { |_, vals| vals.any? }
|
41
41
|
binds = @binds.merge(fkey_binds)
|
42
|
-
RawQuery.new(@sql, binds, use: @use, eager_loaders: @eager_loaders, query_logger: query_logger).run
|
42
|
+
RawQuery.new(@sql, binds, use: @use, eager_loaders: @eager_loaders, query_logger: query_logger, measurements: measurements).run
|
43
43
|
else
|
44
44
|
[]
|
45
45
|
end
|
@@ -33,9 +33,9 @@ module OccamsRecord
|
|
33
33
|
# @param rows [Array<OccamsRecord::Results::Row>] Array of rows used to calculate the query.
|
34
34
|
# @param query_logger [Array<String>]
|
35
35
|
#
|
36
|
-
def run(rows, query_logger: nil)
|
36
|
+
def run(rows, query_logger: nil, measurements: nil)
|
37
37
|
query(rows) { |*args|
|
38
|
-
assoc_rows = args[0] ? Query.new(args[0], use: @use, eager_loaders: @eager_loaders, query_logger: query_logger).run : []
|
38
|
+
assoc_rows = args[0] ? Query.new(args[0], use: @use, eager_loaders: @eager_loaders, query_logger: query_logger, measurements: measurements).run : []
|
39
39
|
merge! assoc_rows, rows, *args[1..-1]
|
40
40
|
}
|
41
41
|
nil
|
@@ -103,10 +103,10 @@ module OccamsRecord
|
|
103
103
|
# @param rows [Array<ActiveRecord::Base>] the parent rows to load child rows into
|
104
104
|
# @param query_logger [Array] optional query logger
|
105
105
|
#
|
106
|
-
def run!(rows, query_logger: nil)
|
106
|
+
def run!(rows, query_logger: nil, measurements: nil)
|
107
107
|
raise "Cannot run eager loaders when @model has not been set!" if @dynamic_loaders.any? and @model.nil?
|
108
108
|
@loaders.each { |loader|
|
109
|
-
loader.run(rows, query_logger: query_logger)
|
109
|
+
loader.run(rows, query_logger: query_logger, measurements: measurements)
|
110
110
|
}
|
111
111
|
nil
|
112
112
|
end
|
@@ -31,11 +31,11 @@ module OccamsRecord
|
|
31
31
|
# @param rows [Array<OccamsRecord::Results::Row>] Array of rows used to calculate the query.
|
32
32
|
# @param query_logger [Array<String>]
|
33
33
|
#
|
34
|
-
def run(rows, query_logger: nil)
|
34
|
+
def run(rows, query_logger: nil, measurements: nil)
|
35
35
|
query(rows) { |scope|
|
36
36
|
eager_loaders = @eager_loaders.dup
|
37
37
|
eager_loaders.model = scope.klass
|
38
|
-
assoc_rows = Query.new(scope, use: @use, eager_loaders: eager_loaders, query_logger: query_logger).run
|
38
|
+
assoc_rows = Query.new(scope, use: @use, eager_loaders: eager_loaders, query_logger: query_logger, measurements: measurements).run
|
39
39
|
merge! assoc_rows, rows
|
40
40
|
}
|
41
41
|
nil
|
@@ -36,8 +36,8 @@ module OccamsRecord
|
|
36
36
|
@loader.name
|
37
37
|
end
|
38
38
|
|
39
|
-
def run(rows, query_logger: nil)
|
40
|
-
@loader.run(rows, query_logger: query_logger)
|
39
|
+
def run(rows, query_logger: nil, measurements: nil)
|
40
|
+
@loader.run(rows, query_logger: query_logger, measurements: measurements)
|
41
41
|
attr_set = "#{name}="
|
42
42
|
rows.each do |row|
|
43
43
|
row.send(attr_set, reduce(row))
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module OccamsRecord
|
2
|
+
Measurements = Struct.new(:total_time, :queries)
|
3
|
+
Measurement = Struct.new(:table_name, :sql, :time)
|
4
|
+
|
5
|
+
#
|
6
|
+
# Measure the time each query takes. Useful for figuring out which query is the slow one when you're doing a bunch of eager loads.
|
7
|
+
#
|
8
|
+
# orders = OccamsRecord.
|
9
|
+
# query(Order.all).
|
10
|
+
# eager_load(:customer).
|
11
|
+
# ...
|
12
|
+
# measure { |x|
|
13
|
+
# puts "Total time: #{x.total_time} sec"
|
14
|
+
# x.queries.each { |q|
|
15
|
+
# puts "Table: #{q.table_name} (#{q.time} sec)"
|
16
|
+
# puts q.sql
|
17
|
+
# }
|
18
|
+
# }.
|
19
|
+
# run
|
20
|
+
#
|
21
|
+
module Measureable
|
22
|
+
#
|
23
|
+
# Track the run time of each query, and the total run time of everything combined.
|
24
|
+
#
|
25
|
+
# @yield [OccamsRecord::Measurements]
|
26
|
+
# @return self
|
27
|
+
#
|
28
|
+
def measure(&block)
|
29
|
+
@measurements ||= []
|
30
|
+
@measurement_results_block = block
|
31
|
+
self
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def measure?
|
37
|
+
!@measurements.nil?
|
38
|
+
end
|
39
|
+
|
40
|
+
def measure!(table_name, sql)
|
41
|
+
result = nil
|
42
|
+
time = Benchmark.realtime { result = yield }
|
43
|
+
@measurements << Measurement.new(table_name, sql, time)
|
44
|
+
result
|
45
|
+
end
|
46
|
+
|
47
|
+
def record_start_time!
|
48
|
+
@start_time = Time.now if top_level_measurer?
|
49
|
+
end
|
50
|
+
|
51
|
+
def yield_measurements!
|
52
|
+
if top_level_measurer?
|
53
|
+
total_time = Time.now - @start_time
|
54
|
+
measurements = Measurements.new(total_time, @measurements.sort_by(&:time))
|
55
|
+
@measurement_results_block.call(measurements)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def top_level_measurer?
|
60
|
+
defined?(@measurement_results_block) && !@measurement_results_block.nil?
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/lib/occams-record/query.rb
CHANGED
@@ -39,6 +39,7 @@ module OccamsRecord
|
|
39
39
|
include Batches
|
40
40
|
include EagerLoaders::Builder
|
41
41
|
include Enumerable
|
42
|
+
include Measureable
|
42
43
|
|
43
44
|
#
|
44
45
|
# Initialize a new query.
|
@@ -47,13 +48,14 @@ module OccamsRecord
|
|
47
48
|
# @param use [Array<Module>] optional Module to include in the result class (single or array)
|
48
49
|
# @param query_logger [Array] (optional) an array into which all queries will be inserted for logging/debug purposes
|
49
50
|
# @param eager_loaders [OccamsRecord::EagerLoaders::Context]
|
51
|
+
# @param measurements [Array]
|
50
52
|
#
|
51
|
-
def initialize(scope, use: nil, eager_loaders: nil, query_logger: nil)
|
53
|
+
def initialize(scope, use: nil, eager_loaders: nil, query_logger: nil, measurements: nil)
|
52
54
|
@model = scope.klass
|
53
55
|
@scope = scope
|
54
56
|
@eager_loaders = eager_loaders || EagerLoaders::Context.new(@model)
|
55
57
|
@use = use
|
56
|
-
@query_logger = query_logger
|
58
|
+
@query_logger, @measurements = query_logger, measurements
|
57
59
|
end
|
58
60
|
|
59
61
|
#
|
@@ -93,10 +95,18 @@ module OccamsRecord
|
|
93
95
|
def run
|
94
96
|
sql = block_given? ? yield(scope).to_sql : scope.to_sql
|
95
97
|
@query_logger << sql if @query_logger
|
96
|
-
result =
|
98
|
+
result = if measure?
|
99
|
+
record_start_time!
|
100
|
+
measure!(model.table_name, sql) {
|
101
|
+
model.connection.exec_query sql
|
102
|
+
}
|
103
|
+
else
|
104
|
+
model.connection.exec_query sql
|
105
|
+
end
|
97
106
|
row_class = OccamsRecord::Results.klass(result.columns, result.column_types, @eager_loaders.names, model: model, modules: @use)
|
98
107
|
rows = result.rows.map { |row| row_class.new row }
|
99
|
-
@eager_loaders.run!(rows, query_logger: @query_logger)
|
108
|
+
@eager_loaders.run!(rows, query_logger: @query_logger, measurements: @measurements)
|
109
|
+
yield_measurements!
|
100
110
|
rows
|
101
111
|
end
|
102
112
|
|
@@ -53,6 +53,7 @@ module OccamsRecord
|
|
53
53
|
include Batches
|
54
54
|
include EagerLoaders::Builder
|
55
55
|
include Enumerable
|
56
|
+
include Measureable
|
56
57
|
|
57
58
|
#
|
58
59
|
# Initialize a new query.
|
@@ -62,13 +63,14 @@ module OccamsRecord
|
|
62
63
|
# @param use [Array<Module>] optional Module to include in the result class (single or array)
|
63
64
|
# @param eager_loaders [OccamsRecord::EagerLoaders::Context]
|
64
65
|
# @param query_logger [Array] (optional) an array into which all queries will be inserted for logging/debug purposes
|
66
|
+
# @param measurements [Array]
|
65
67
|
#
|
66
|
-
def initialize(sql, binds, use: nil, eager_loaders: nil, query_logger: nil)
|
68
|
+
def initialize(sql, binds, use: nil, eager_loaders: nil, query_logger: nil, measurements: nil)
|
67
69
|
@sql = sql
|
68
70
|
@binds = binds
|
69
71
|
@use = use
|
70
72
|
@eager_loaders = eager_loaders || EagerLoaders::Context.new
|
71
|
-
@query_logger = query_logger
|
73
|
+
@query_logger, @measurements = query_logger, measurements
|
72
74
|
@conn = @eager_loaders.model&.connection || ActiveRecord::Base.connection
|
73
75
|
end
|
74
76
|
|
@@ -95,10 +97,18 @@ module OccamsRecord
|
|
95
97
|
def run
|
96
98
|
_escaped_sql = escaped_sql
|
97
99
|
@query_logger << _escaped_sql if @query_logger
|
98
|
-
result =
|
100
|
+
result = if measure?
|
101
|
+
record_start_time!
|
102
|
+
measure!(table_name, _escaped_sql) {
|
103
|
+
@conn.exec_query _escaped_sql
|
104
|
+
}
|
105
|
+
else
|
106
|
+
@conn.exec_query _escaped_sql
|
107
|
+
end
|
99
108
|
row_class = OccamsRecord::Results.klass(result.columns, result.column_types, @eager_loaders.names, model: @eager_loaders.model, modules: @use)
|
100
109
|
rows = result.rows.map { |row| row_class.new row }
|
101
|
-
@eager_loaders.run!(rows, query_logger: @query_logger)
|
110
|
+
@eager_loaders.run!(rows, query_logger: @query_logger, measurements: @measurements)
|
111
|
+
yield_measurements!
|
102
112
|
rows
|
103
113
|
end
|
104
114
|
|
@@ -123,6 +133,7 @@ module OccamsRecord
|
|
123
133
|
|
124
134
|
# Returns the SQL as a String with all variables escaped
|
125
135
|
def escaped_sql
|
136
|
+
return sql if binds.empty?
|
126
137
|
sql % binds.reduce({}) { |a, (col, val)|
|
127
138
|
a[col.to_sym] = if val.is_a? Array
|
128
139
|
val.map { |x| @conn.quote x }.join(', ')
|
@@ -133,6 +144,10 @@ module OccamsRecord
|
|
133
144
|
}
|
134
145
|
end
|
135
146
|
|
147
|
+
def table_name
|
148
|
+
@sql.match(/\s+FROM\s+"?(\w+)"?/i)&.captures&.first
|
149
|
+
end
|
150
|
+
|
136
151
|
#
|
137
152
|
# Returns an Enumerator that yields batches of records, of size "of".
|
138
153
|
# The SQL string must include 'LIMIT %{batch_limit} OFFSET %{batch_offset}'.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: occams-record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.rc11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jordan Hollinger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -54,6 +54,7 @@ files:
|
|
54
54
|
- lib/occams-record/eager_loaders/polymorphic_belongs_to.rb
|
55
55
|
- lib/occams-record/eager_loaders/through.rb
|
56
56
|
- lib/occams-record/errors.rb
|
57
|
+
- lib/occams-record/measureable.rb
|
57
58
|
- lib/occams-record/merge.rb
|
58
59
|
- lib/occams-record/query.rb
|
59
60
|
- lib/occams-record/raw_query.rb
|