occams-record 1.0.0.rc10 → 1.0.0.rc11
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://travis-ci.org/jhollinger/occams-record.svg?branch=master)](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
|