File: sequel_pg.rb

package info (click to toggle)
ruby-sequel-pg 1.14.0-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye, sid, trixie
  • size: 176 kB
  • sloc: ansic: 1,693; ruby: 210; makefile: 2
file content (131 lines) | stat: -rw-r--r-- 4,234 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
# 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

  # In the case where an argument is given, use an optimized version.
  def map(sym=nil)
    if sym
      if block_given?
        super
      else
        rows = []
        clone(:_sequel_pg_type=>:map, :_sequel_pg_value=>sym).fetch_rows(sql){|s| rows << s}
        rows
      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]
      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

  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

  # 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]
      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

  if defined?(Sequel::Model::ClassMethods)
    # If model loads are being optimized and this is a model load, use the optimized
    # version.
    def each(&block)
      if optimize_model_load?
        clone(:_sequel_pg_type=>:model, :_sequel_pg_value=>row_proc).fetch_rows(sql, &block)
      else
        super
      end
    end
  end
    
  protected

  # Always use optimized version
  def _select_map_multiple(ret_cols)
    rows = []
    clone(:_sequel_pg_type=>:array).fetch_rows(sql){|s| rows << s}
    rows
  end

  # Always use optimized version
  def _select_map_single
    rows = []
    clone(:_sequel_pg_type=>:first).fetch_rows(sql){|s| rows << s}
    rows
  end

  private

  if defined?(Sequel::Model::ClassMethods)
    # The model load can only be optimized if it's for a model and it's not a graphed dataset
    # or using a cursor.
    def optimize_model_load?
      (rp = row_proc) &&
        rp.is_a?(Class) &&
        rp < Sequel::Model &&
        rp.method(:call).owner == Sequel::Model::ClassMethods &&
        opts[:optimize_model_load] != false &&
        !opts[:use_cursor] &&
        !opts[:graph]
    end
  end
end

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

  class Sequel::Postgres::PGArray::Creator
    # 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