File: sequel_pg.rb

package info (click to toggle)
ruby-sequel-pg 1.18.2-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 204 kB
  • sloc: ansic: 1,938; ruby: 348; makefile: 2
file content (205 lines) | stat: -rw-r--r-- 6,291 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
# Add speedup for model class creation from dataset
class Sequel::Postgres::Database
  def optimize_model_load=(v)
    Sequel::Deprecation.deprecate("Database#optimize_model_load= is deprecated.  Optimized model loading is now enabled by default, and can only be disabled on a per-Dataset basis.")
    v
  end
  def optimize_model_load
    Sequel::Deprecation.deprecate("Database#optimize_model_load is deprecated.  Optimized model loading is now enabled by default, and can only be disabled on a per-Dataset basis.")
    true
  end
end

# Add faster versions of Dataset#map, #as_hash, #to_hash_groups, #select_map, #select_order_map, and #select_hash
class Sequel::Postgres::Dataset
  def optimize_model_load=(v)
    Sequel::Deprecation.deprecate("Dataset#optimize_model_load= mutation method is deprecated.  Switch to using Dataset#with_optimize_model_load, which returns a modified dataset")
    opts[:optimize_model_load] = v
  end
  def optimize_model_load
    Sequel::Deprecation.deprecate("Dataset#optimize_model_load method is deprecated.  Optimized model loading is enabled by default.")
    opts.has_key?(:optimize_model_load) ?  opts[:optimize_model_load] : true
  end

  # :nocov:
  if method_defined?(:as_set)
  # :nocov:
    if RUBY_VERSION > '4'
      def as_set(column)
        return super unless allow_sequel_pg_optimization?
        clone(:_sequel_pg_type=>:map_set, :_sequel_pg_value=>column).fetch_rows(sql){|s| return s}
        Set.new
      end
    # :nocov:
    else
      def as_set(column)
        return super unless allow_sequel_pg_optimization?
        rows = Set.new
        clone(:_sequel_pg_type=>:map, :_sequel_pg_value=>column).fetch_rows(sql){|s| rows.add(s)}
        rows
      end
    end
    # :nocov:
  end

  # In the case where an argument is given, use an optimized version.
  def map(sym=nil)
    if sym
      if block_given?
        super
      else
        return super unless allow_sequel_pg_optimization?
        clone(:_sequel_pg_type=>:map_array, :_sequel_pg_value=>sym).fetch_rows(sql){|a| return a}
        []
      end
    else
      super
    end
  end

  # Return a modified copy with the optimize_model_load setting changed.
  def with_optimize_model_load(v)
    clone(:optimize_model_load=>v)
  end

  # In the case where both arguments given, use an optimized version.
  def as_hash(key_column, value_column = nil, opts = Sequel::OPTS)
    if value_column && !opts[:hash]
      return super unless allow_sequel_pg_optimization?
      clone(:_sequel_pg_type=>:hash, :_sequel_pg_value=>[key_column, value_column]).fetch_rows(sql){|s| return s}
      {}
    elsif opts.empty?
      super(key_column, value_column)
    else
      super
    end
  end

  # :nocov:
  unless Sequel::Dataset.method_defined?(:as_hash)
    # Handle previous versions of Sequel that use to_hash instead of as_hash
    alias to_hash as_hash
    remove_method :as_hash
  end
  # :nocov:

  # In the case where both arguments given, use an optimized version.
  def to_hash_groups(key_column, value_column = nil, opts = Sequel::OPTS)
    if value_column && !opts[:hash]
      return super unless allow_sequel_pg_optimization?
      clone(:_sequel_pg_type=>:hash_groups, :_sequel_pg_value=>[key_column, value_column]).fetch_rows(sql){|s| return s}
      {}
    elsif opts.empty?
      super(key_column, value_column)
    else
      super
    end
  end

  # Delegate to with_sql_all using the default SQL
  def all(&block)
    with_sql_all(sql, &block)
  end

  # :nocov:
  # Generally overridden by the model support, only used if the model
  # support is not used.
  def with_sql_all(sql, &block)
    return super unless allow_sequel_pg_optimization?

    clone(:_sequel_pg_type=>:all).fetch_rows(sql) do |array|
      if rp = row_proc
        array.map!{|h| rp.call(h)}
      end
      post_load(array)
      array.each(&block) if block
      return array
    end
    []
  end
  # :nocov:
    
  protected

  # Always use optimized version
  def _select_map_multiple(ret_cols)
    return super unless allow_sequel_pg_optimization?
    clone(:_sequel_pg_type=>:array_array).fetch_rows(sql){|a| return a}
    []
  end

  # Always use optimized version
  def _select_map_single
    return super unless allow_sequel_pg_optimization?
    clone(:_sequel_pg_type=>:first_array).fetch_rows(sql){|a| return a}
    []
  end

  # :nocov:
  if method_defined?(:_select_set_multiple)
  # :nocov:
    if RUBY_VERSION > '4'
      # Always use optimized version
      def _select_set_multiple(ret_cols)
        return super unless allow_sequel_pg_optimization?
        clone(:_sequel_pg_type=>:array_set).fetch_rows(sql){|s| return s}
        Set.new
      end

      # Always use optimized version
      def _select_set_single
        return super unless allow_sequel_pg_optimization?
        clone(:_sequel_pg_type=>:first_set).fetch_rows(sql){|s| return s}
        Set.new
      end
    # :nocov:
    else
      # Always use optimized version
      def _select_set_multiple(ret_cols)
        return super unless allow_sequel_pg_optimization?
        set = Set.new
        clone(:_sequel_pg_type=>:array).fetch_rows(sql){|s| set.add s}
        set
      end

      # Always use optimized version
      def _select_set_single
        return super unless allow_sequel_pg_optimization?
        set = Set.new
        clone(:_sequel_pg_type=>:first).fetch_rows(sql){|s| set.add s}
        set
      end
    end
    # :nocov:
  end

  if defined?(Sequel::Model::ClassMethods)
    require_relative 'model'
  end

  private

  # Whether to allow sequel_pg to optimize the each/all/with_sql_all call.
  def allow_sequel_pg_optimization?
    (!opts[:graph] || opts[:eager_graph]) && !opts[:cursor]
  end
end

if defined?(Sequel::Postgres::PGArray)
  # pg_array extension previously loaded

  class Sequel::Postgres::PGArray::Creator
    # :nocov:
    # Avoid method redefined verbose warning
    alias call call if method_defined?(:call)
    # :nocov:

    # Override Creator to use sequel_pg's C-based parser instead of the pure ruby parser.
    def call(string)
      Sequel::Postgres::PGArray.new(Sequel::Postgres.parse_pg_array(string, @converter), @type)
    end
  end

  # Remove the pure-ruby parser, no longer needed.
  Sequel::Postgres::PGArray.send(:remove_const, :Parser)
end