sequel_pg_extended_columns 1.6.19
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 +7 -0
- data/CHANGELOG +149 -0
- data/MIT-LICENSE +47 -0
- data/README.rdoc +190 -0
- data/Rakefile +21 -0
- data/ext/sequel_pg/extconf.rb +21 -0
- data/ext/sequel_pg/sequel_pg.c +1129 -0
- data/lib/sequel/extensions/pg_streaming.rb +149 -0
- data/lib/sequel_pg/sequel_pg.rb +103 -0
- metadata +108 -0
@@ -0,0 +1,149 @@
|
|
1
|
+
unless Sequel::Postgres.respond_to?(:supports_streaming?)
|
2
|
+
raise LoadError, "either sequel_pg not loaded, or an old version of sequel_pg loaded"
|
3
|
+
end
|
4
|
+
unless Sequel::Postgres.supports_streaming?
|
5
|
+
raise LoadError, "streaming is not supported by the version of libpq in use"
|
6
|
+
end
|
7
|
+
|
8
|
+
# Database methods necessary to support streaming. You should load this extension
|
9
|
+
# into your database object:
|
10
|
+
#
|
11
|
+
# DB.extension(:pg_streaming)
|
12
|
+
#
|
13
|
+
# Then you can call #stream on your datasets to use the streaming support:
|
14
|
+
#
|
15
|
+
# DB[:table].stream.each{|row| ...}
|
16
|
+
#
|
17
|
+
# Or change a set so that all dataset calls use streaming:
|
18
|
+
#
|
19
|
+
# DB.stream_all_queries = true
|
20
|
+
module Sequel::Postgres::Streaming
|
21
|
+
attr_accessor :stream_all_queries
|
22
|
+
|
23
|
+
# Also extend the database's datasets to support streaming.
|
24
|
+
# This extension requires modifying connections, so disconnect
|
25
|
+
# so that new connections will get the methods.
|
26
|
+
def self.extended(db)
|
27
|
+
db.extend_datasets(DatasetMethods)
|
28
|
+
db.stream_all_queries = false
|
29
|
+
db.disconnect
|
30
|
+
end
|
31
|
+
|
32
|
+
# Make sure all new connections have the appropriate methods added.
|
33
|
+
def connect(server)
|
34
|
+
conn = super
|
35
|
+
conn.extend(AdapterMethods)
|
36
|
+
conn
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
# If streaming is requested, and a prepared statement is not
|
42
|
+
# used, tell the connection to use single row mode for the query.
|
43
|
+
def _execute(conn, sql, opts={}, &block)
|
44
|
+
if opts[:stream] && !sql.is_a?(Symbol)
|
45
|
+
conn.single_row_mode = true
|
46
|
+
end
|
47
|
+
super
|
48
|
+
end
|
49
|
+
|
50
|
+
# If streaming is requested, send the prepared statement instead
|
51
|
+
# of executing it and blocking.
|
52
|
+
def _execute_prepared_statement(conn, ps_name, args, opts)
|
53
|
+
if opts[:stream]
|
54
|
+
conn.send_prepared_statement(ps_name, args)
|
55
|
+
else
|
56
|
+
super
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
module AdapterMethods
|
61
|
+
# Whether the next query on this connection should use
|
62
|
+
# single_row_mode.
|
63
|
+
attr_accessor :single_row_mode
|
64
|
+
|
65
|
+
# Send the prepared statement on this connection using
|
66
|
+
# single row mode.
|
67
|
+
def send_prepared_statement(ps_name, args)
|
68
|
+
send_query_prepared(ps_name, args)
|
69
|
+
set_single_row_mode
|
70
|
+
block
|
71
|
+
self
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
if Sequel::Database.instance_methods.map(&:to_s).include?('log_connection_yield')
|
77
|
+
# If using single row mode, send the query instead of executing it.
|
78
|
+
def execute_query(sql, args)
|
79
|
+
if @single_row_mode
|
80
|
+
@single_row_mode = false
|
81
|
+
@db.log_connection_yield(sql, self, args){args ? send_query(sql, args) : send_query(sql)}
|
82
|
+
set_single_row_mode
|
83
|
+
block
|
84
|
+
self
|
85
|
+
else
|
86
|
+
super
|
87
|
+
end
|
88
|
+
end
|
89
|
+
else
|
90
|
+
def execute_query(sql, args)
|
91
|
+
if @single_row_mode
|
92
|
+
@single_row_mode = false
|
93
|
+
@db.log_yield(sql, args){args ? send_query(sql, args) : send_query(sql)}
|
94
|
+
set_single_row_mode
|
95
|
+
block
|
96
|
+
self
|
97
|
+
else
|
98
|
+
super
|
99
|
+
end
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
# Dataset methods used to implement streaming.
|
105
|
+
module DatasetMethods
|
106
|
+
# If streaming has been requested and the current dataset
|
107
|
+
# can be streamed, request the database use streaming when
|
108
|
+
# executing this query, and use yield_each_row to process
|
109
|
+
# the separate PGresult for each row in the connection.
|
110
|
+
def fetch_rows(sql)
|
111
|
+
if stream_results?
|
112
|
+
execute(sql, :stream=>true) do |conn|
|
113
|
+
yield_each_row(conn){|h| yield h}
|
114
|
+
end
|
115
|
+
else
|
116
|
+
super
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Use streaming to implement paging.
|
121
|
+
def paged_each(opts=Sequel::OPTS, &block)
|
122
|
+
stream.each(&block)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Return a clone of the dataset that will use streaming to load
|
126
|
+
# rows.
|
127
|
+
def stream
|
128
|
+
clone(:stream=>true)
|
129
|
+
end
|
130
|
+
|
131
|
+
private
|
132
|
+
|
133
|
+
# Only stream results if streaming has been specifically requested
|
134
|
+
# and the query is streamable.
|
135
|
+
def stream_results?
|
136
|
+
(@opts[:stream] || db.stream_all_queries) && streamable?
|
137
|
+
end
|
138
|
+
|
139
|
+
# Queries using cursors are not streamable, and queries that use
|
140
|
+
# the map/select_map/to_hash/to_hash_groups optimizations are not
|
141
|
+
# streamable, but other queries are streamable.
|
142
|
+
def streamable?
|
143
|
+
spgt = (o = @opts)[:_sequel_pg_type]
|
144
|
+
(spgt.nil? || spgt == :model) && !o[:cursor]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
Sequel::Database.register_extension(:pg_streaming, Sequel::Postgres::Streaming)
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# Add speedup for model class creation from dataset
|
2
|
+
class Sequel::Postgres::Database
|
3
|
+
# Whether to optimize loads for all model datasets created from this dataset.
|
4
|
+
# Has certain limitations, see the README for details.
|
5
|
+
attr_accessor :optimize_model_load
|
6
|
+
end
|
7
|
+
|
8
|
+
# Add faster versions of Dataset#map, #to_hash, #select_map, #select_order_map, and #select_hash
|
9
|
+
class Sequel::Postgres::Dataset
|
10
|
+
# Set whether to enable optimized model loading for this dataset.
|
11
|
+
attr_writer :optimize_model_load
|
12
|
+
|
13
|
+
# In the case where an argument is given, use an optimized version.
|
14
|
+
def map(sym=nil)
|
15
|
+
if sym
|
16
|
+
if block_given?
|
17
|
+
super
|
18
|
+
else
|
19
|
+
rows = []
|
20
|
+
clone(:_sequel_pg_type=>:map, :_sequel_pg_value=>sym).fetch_rows(sql){|s| rows << s}
|
21
|
+
rows
|
22
|
+
end
|
23
|
+
else
|
24
|
+
super
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# If this dataset has turned model loading on or off, use the default value from
|
29
|
+
# the Database object.
|
30
|
+
def optimize_model_load
|
31
|
+
defined?(@optimize_model_load) ? @optimize_model_load : db.optimize_model_load
|
32
|
+
end
|
33
|
+
|
34
|
+
# In the case where both arguments given, use an optimized version.
|
35
|
+
def to_hash(key_column, value_column = nil, opts = Sequel::OPTS)
|
36
|
+
if value_column && !opts[:hash]
|
37
|
+
clone(:_sequel_pg_type=>:hash, :_sequel_pg_value=>[key_column, value_column]).fetch_rows(sql){|s| return s}
|
38
|
+
elsif opts.empty?
|
39
|
+
super(key_column, value_column)
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# In the case where both arguments given, use an optimized version.
|
46
|
+
def to_hash_groups(key_column, value_column = nil, opts = Sequel::OPTS)
|
47
|
+
if value_column && !opts[:hash]
|
48
|
+
clone(:_sequel_pg_type=>:hash_groups, :_sequel_pg_value=>[key_column, value_column]).fetch_rows(sql){|s| return s}
|
49
|
+
elsif opts.empty?
|
50
|
+
super(key_column, value_column)
|
51
|
+
else
|
52
|
+
super
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# If model loads are being optimized and this is a model load, use the optimized
|
57
|
+
# version.
|
58
|
+
def each
|
59
|
+
if (rp = row_proc) && optimize_model_load?
|
60
|
+
clone(:_sequel_pg_type=>:model, :_sequel_pg_value=>rp).fetch_rows(sql, &Proc.new)
|
61
|
+
else
|
62
|
+
super
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
protected
|
67
|
+
|
68
|
+
# Always use optimized version
|
69
|
+
def _select_map_multiple(ret_cols)
|
70
|
+
rows = []
|
71
|
+
clone(:_sequel_pg_type=>:array).fetch_rows(sql){|s| rows << s}
|
72
|
+
rows
|
73
|
+
end
|
74
|
+
|
75
|
+
# Always use optimized version
|
76
|
+
def _select_map_single
|
77
|
+
rows = []
|
78
|
+
clone(:_sequel_pg_type=>:first).fetch_rows(sql){|s| rows << s}
|
79
|
+
rows
|
80
|
+
end
|
81
|
+
|
82
|
+
private
|
83
|
+
|
84
|
+
# The model load can only be optimized if it's for a model and it's not a graphed dataset
|
85
|
+
# or using a cursor.
|
86
|
+
def optimize_model_load?
|
87
|
+
(rp = row_proc).is_a?(Class) && (rp < Sequel::Model) && optimize_model_load && !opts[:use_cursor] && !opts[:graph]
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
if defined?(Sequel::Postgres::PGArray)
|
92
|
+
# pg_array extension previously loaded
|
93
|
+
|
94
|
+
class Sequel::Postgres::PGArray::Creator
|
95
|
+
# Override Creator to use sequel_pg's C-based parser instead of the pure ruby parser.
|
96
|
+
def call(string)
|
97
|
+
Sequel::Postgres::PGArray.new(Sequel::Postgres.parse_pg_array(string, @converter), @type)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Remove the pure-ruby parser, no longer needed.
|
102
|
+
Sequel::Postgres::PGArray.send(:remove_const, :Parser)
|
103
|
+
end
|
metadata
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sequel_pg_extended_columns
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.6.19
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mansoor Ali Khan
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2021-11-29 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: pg
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 0.18.0
|
20
|
+
- - "!="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 1.2.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 0.18.0
|
30
|
+
- - "!="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 1.2.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: sequel
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 4.38.0
|
40
|
+
type: :runtime
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - ">="
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: 4.38.0
|
47
|
+
description: |
|
48
|
+
sequel_pg overwrites the inner loop of the Sequel postgres
|
49
|
+
adapter row fetching code with a C version. The C version
|
50
|
+
is significantly faster than the pure ruby version
|
51
|
+
that Sequel uses by default.
|
52
|
+
|
53
|
+
sequel_pg also offers optimized versions of some dataset
|
54
|
+
methods, as well as adds support for using PostgreSQL
|
55
|
+
streaming.
|
56
|
+
email: mansoorkhan108@gmail.com
|
57
|
+
executables: []
|
58
|
+
extensions:
|
59
|
+
- ext/sequel_pg/extconf.rb
|
60
|
+
extra_rdoc_files:
|
61
|
+
- README.rdoc
|
62
|
+
- CHANGELOG
|
63
|
+
- MIT-LICENSE
|
64
|
+
files:
|
65
|
+
- CHANGELOG
|
66
|
+
- MIT-LICENSE
|
67
|
+
- README.rdoc
|
68
|
+
- Rakefile
|
69
|
+
- ext/sequel_pg/extconf.rb
|
70
|
+
- ext/sequel_pg/sequel_pg.c
|
71
|
+
- lib/sequel/extensions/pg_streaming.rb
|
72
|
+
- lib/sequel_pg/sequel_pg.rb
|
73
|
+
homepage: https://github.com/mansoorkhan108/sequel_pg
|
74
|
+
licenses:
|
75
|
+
- MIT
|
76
|
+
metadata:
|
77
|
+
bug_tracker_uri: https://github.com/jeremyevans/sequel_pg/issues
|
78
|
+
changelog_uri: https://github.com/jeremyevans/sequel_pg/blob/master/CHANGELOG
|
79
|
+
documentation_uri: https://github.com/jeremyevans/sequel_pg/blob/master/README.rdoc
|
80
|
+
mailing_list_uri: https://groups.google.com/forum/#!forum/sequel-talk
|
81
|
+
source_code_uri: https://github.com/jeremyevans/sequel_pg
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options:
|
84
|
+
- "--quiet"
|
85
|
+
- "--line-numbers"
|
86
|
+
- "--inline-source"
|
87
|
+
- "--title"
|
88
|
+
- 'sequel_pg: Faster SELECTs when using Sequel with pg'
|
89
|
+
- "--main"
|
90
|
+
- README.rdoc
|
91
|
+
require_paths:
|
92
|
+
- lib
|
93
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 1.9.3
|
98
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
requirements: []
|
104
|
+
rubygems_version: 3.0.8
|
105
|
+
signing_key:
|
106
|
+
specification_version: 4
|
107
|
+
summary: Faster SELECTs when using Sequel with pg
|
108
|
+
test_files: []
|