sequel_core 1.5.1 → 2.0.0
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.
- data/CHANGELOG +116 -0
 - data/COPYING +19 -19
 - data/README +83 -32
 - data/Rakefile +9 -20
 - data/bin/sequel +43 -112
 - data/doc/cheat_sheet.rdoc +225 -0
 - data/doc/dataset_filtering.rdoc +257 -0
 - data/lib/sequel_core/adapters/adapter_skeleton.rb +4 -2
 - data/lib/sequel_core/adapters/ado.rb +3 -1
 - data/lib/sequel_core/adapters/db2.rb +4 -2
 - data/lib/sequel_core/adapters/dbi.rb +127 -113
 - data/lib/sequel_core/adapters/informix.rb +4 -2
 - data/lib/sequel_core/adapters/jdbc.rb +5 -3
 - data/lib/sequel_core/adapters/mysql.rb +112 -46
 - data/lib/sequel_core/adapters/odbc.rb +5 -7
 - data/lib/sequel_core/adapters/odbc_mssql.rb +12 -3
 - data/lib/sequel_core/adapters/openbase.rb +3 -1
 - data/lib/sequel_core/adapters/oracle.rb +11 -9
 - data/lib/sequel_core/adapters/postgres.rb +261 -262
 - data/lib/sequel_core/adapters/sqlite.rb +72 -22
 - data/lib/sequel_core/connection_pool.rb +140 -73
 - data/lib/sequel_core/core_ext.rb +201 -66
 - data/lib/sequel_core/core_sql.rb +123 -153
 - data/lib/sequel_core/database/schema.rb +156 -0
 - data/lib/sequel_core/database.rb +321 -338
 - data/lib/sequel_core/dataset/callback.rb +11 -12
 - data/lib/sequel_core/dataset/convenience.rb +213 -240
 - data/lib/sequel_core/dataset/pagination.rb +58 -43
 - data/lib/sequel_core/dataset/parse_tree_sequelizer.rb +331 -0
 - data/lib/sequel_core/dataset/query.rb +41 -0
 - data/lib/sequel_core/dataset/schema.rb +15 -0
 - data/lib/sequel_core/dataset/sequelizer.rb +41 -373
 - data/lib/sequel_core/dataset/sql.rb +741 -632
 - data/lib/sequel_core/dataset.rb +183 -168
 - data/lib/sequel_core/deprecated.rb +1 -169
 - data/lib/sequel_core/exceptions.rb +24 -19
 - data/lib/sequel_core/migration.rb +44 -52
 - data/lib/sequel_core/object_graph.rb +43 -42
 - data/lib/sequel_core/pretty_table.rb +71 -76
 - data/lib/sequel_core/schema/generator.rb +163 -105
 - data/lib/sequel_core/schema/sql.rb +250 -93
 - data/lib/sequel_core/schema.rb +2 -8
 - data/lib/sequel_core/sql.rb +394 -0
 - data/lib/sequel_core/worker.rb +37 -27
 - data/lib/sequel_core.rb +99 -45
 - data/spec/adapters/informix_spec.rb +0 -1
 - data/spec/adapters/mysql_spec.rb +177 -124
 - data/spec/adapters/oracle_spec.rb +0 -1
 - data/spec/adapters/postgres_spec.rb +98 -58
 - data/spec/adapters/sqlite_spec.rb +45 -4
 - data/spec/blockless_filters_spec.rb +269 -0
 - data/spec/connection_pool_spec.rb +21 -18
 - data/spec/core_ext_spec.rb +169 -19
 - data/spec/core_sql_spec.rb +56 -49
 - data/spec/database_spec.rb +78 -17
 - data/spec/dataset_spec.rb +300 -428
 - data/spec/migration_spec.rb +1 -1
 - data/spec/object_graph_spec.rb +5 -11
 - data/spec/rcov.opts +1 -1
 - data/spec/schema_generator_spec.rb +16 -4
 - data/spec/schema_spec.rb +89 -10
 - data/spec/sequelizer_spec.rb +56 -56
 - data/spec/spec.opts +0 -5
 - data/spec/spec_config.rb +7 -0
 - data/spec/spec_config.rb.example +5 -5
 - data/spec/spec_helper.rb +6 -0
 - data/spec/worker_spec.rb +1 -1
 - metadata +78 -63
 
| 
         @@ -10,9 +10,7 @@ module Sequel 
     | 
|
| 
       10 
10 
     | 
    
         
             
                  end
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                  def connect
         
     | 
| 
       13 
     | 
    
         
            -
                     
     | 
| 
       14 
     | 
    
         
            -
                      @opts[:database] = ':memory:'
         
     | 
| 
       15 
     | 
    
         
            -
                    end
         
     | 
| 
      
 13 
     | 
    
         
            +
                    @opts[:database] = ':memory:' if @opts[:database].blank?
         
     | 
| 
       16 
14 
     | 
    
         
             
                    db = ::SQLite3::Database.new(@opts[:database])
         
     | 
| 
       17 
15 
     | 
    
         
             
                    db.busy_timeout(@opts.fetch(:timeout, 5000))
         
     | 
| 
       18 
16 
     | 
    
         
             
                    db.type_translation = true
         
     | 
| 
         @@ -38,31 +36,39 @@ module Sequel 
     | 
|
| 
       38 
36 
     | 
    
         
             
                  end
         
     | 
| 
       39 
37 
     | 
    
         | 
| 
       40 
38 
     | 
    
         
             
                  def execute(sql)
         
     | 
| 
       41 
     | 
    
         
            -
                     
     | 
| 
       42 
     | 
    
         
            -
             
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
     | 
    
         
            -
                     
     | 
| 
      
 39 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 40 
     | 
    
         
            +
                      log_info(sql)
         
     | 
| 
      
 41 
     | 
    
         
            +
                      @pool.hold {|conn| conn.execute_batch(sql); conn.changes}
         
     | 
| 
      
 42 
     | 
    
         
            +
                    rescue SQLite3::Exception => e
         
     | 
| 
      
 43 
     | 
    
         
            +
                      raise Error::InvalidStatement, "#{sql}\r\n#{e.message}"
         
     | 
| 
      
 44 
     | 
    
         
            +
                    end
         
     | 
| 
       45 
45 
     | 
    
         
             
                  end
         
     | 
| 
       46 
46 
     | 
    
         | 
| 
       47 
47 
     | 
    
         
             
                  def execute_insert(sql)
         
     | 
| 
       48 
     | 
    
         
            -
                     
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
                     
     | 
| 
      
 48 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 49 
     | 
    
         
            +
                      log_info(sql)
         
     | 
| 
      
 50 
     | 
    
         
            +
                      @pool.hold {|conn| conn.execute(sql); conn.last_insert_row_id}
         
     | 
| 
      
 51 
     | 
    
         
            +
                    rescue SQLite3::Exception => e
         
     | 
| 
      
 52 
     | 
    
         
            +
                      raise Error::InvalidStatement, "#{sql}\r\n#{e.message}"
         
     | 
| 
      
 53 
     | 
    
         
            +
                    end
         
     | 
| 
       52 
54 
     | 
    
         
             
                  end
         
     | 
| 
       53 
55 
     | 
    
         | 
| 
       54 
56 
     | 
    
         
             
                  def single_value(sql)
         
     | 
| 
       55 
     | 
    
         
            -
                     
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
             
     | 
| 
       58 
     | 
    
         
            -
                     
     | 
| 
      
 57 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 58 
     | 
    
         
            +
                      log_info(sql)
         
     | 
| 
      
 59 
     | 
    
         
            +
                      @pool.hold {|conn| conn.get_first_value(sql)}
         
     | 
| 
      
 60 
     | 
    
         
            +
                    rescue SQLite3::Exception => e
         
     | 
| 
      
 61 
     | 
    
         
            +
                      raise Error::InvalidStatement, "#{sql}\r\n#{e.message}"
         
     | 
| 
      
 62 
     | 
    
         
            +
                    end
         
     | 
| 
       59 
63 
     | 
    
         
             
                  end
         
     | 
| 
       60 
64 
     | 
    
         | 
| 
       61 
65 
     | 
    
         
             
                  def execute_select(sql, &block)
         
     | 
| 
       62 
     | 
    
         
            -
                     
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
                     
     | 
| 
      
 66 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 67 
     | 
    
         
            +
                      log_info(sql)
         
     | 
| 
      
 68 
     | 
    
         
            +
                      @pool.hold {|conn| conn.query(sql, &block)}
         
     | 
| 
      
 69 
     | 
    
         
            +
                    rescue SQLite3::Exception => e
         
     | 
| 
      
 70 
     | 
    
         
            +
                      raise Error::InvalidStatement, "#{sql}\r\n#{e.message}"
         
     | 
| 
      
 71 
     | 
    
         
            +
                    end
         
     | 
| 
       66 
72 
     | 
    
         
             
                  end
         
     | 
| 
       67 
73 
     | 
    
         | 
| 
       68 
74 
     | 
    
         
             
                  def pragma_get(name)
         
     | 
| 
         @@ -124,20 +130,64 @@ module Sequel 
     | 
|
| 
       124 
130 
     | 
    
         
             
                        result = nil
         
     | 
| 
       125 
131 
     | 
    
         
             
                        conn.transaction {result = yield(conn)}
         
     | 
| 
       126 
132 
     | 
    
         
             
                        result
         
     | 
| 
       127 
     | 
    
         
            -
                      rescue => e
         
     | 
| 
       128 
     | 
    
         
            -
                        raise e unless Error::Rollback === e
         
     | 
| 
      
 133 
     | 
    
         
            +
                      rescue ::Exception => e
         
     | 
| 
      
 134 
     | 
    
         
            +
                        raise (SQLite3::Exception === e ? Error.new(e.message) : e) unless Error::Rollback === e
         
     | 
| 
      
 135 
     | 
    
         
            +
                      end
         
     | 
| 
      
 136 
     | 
    
         
            +
                    end
         
     | 
| 
      
 137 
     | 
    
         
            +
                  end
         
     | 
| 
      
 138 
     | 
    
         
            +
                  
         
     | 
| 
      
 139 
     | 
    
         
            +
                  private
         
     | 
| 
      
 140 
     | 
    
         
            +
                  def connection_pool_default_options
         
     | 
| 
      
 141 
     | 
    
         
            +
                    o = super.merge(:pool_reuse_connections=>:always, :pool_convert_exceptions=>false)
         
     | 
| 
      
 142 
     | 
    
         
            +
                    # Default to only a single connection if a memory database is used,
         
     | 
| 
      
 143 
     | 
    
         
            +
                    # because otherwise each connection will get a separate database
         
     | 
| 
      
 144 
     | 
    
         
            +
                    o[:max_connections] = 1 if @opts[:database] == ':memory:' || @opts[:database].blank?
         
     | 
| 
      
 145 
     | 
    
         
            +
                    o
         
     | 
| 
      
 146 
     | 
    
         
            +
                  end
         
     | 
| 
      
 147 
     | 
    
         
            +
             
     | 
| 
      
 148 
     | 
    
         
            +
                  SCHEMA_TYPE_RE = /\A(\w+)\((\d+)\)\z/
         
     | 
| 
      
 149 
     | 
    
         
            +
                  def schema_parse_table(table_name, opts)
         
     | 
| 
      
 150 
     | 
    
         
            +
                    rows = self["PRAGMA table_info('#{::SQLite3::Database.quote(table_name.to_s)}')"].collect do |row|
         
     | 
| 
      
 151 
     | 
    
         
            +
                      row.delete(:cid)
         
     | 
| 
      
 152 
     | 
    
         
            +
                      row[:column] = row.delete(:name)
         
     | 
| 
      
 153 
     | 
    
         
            +
                      row[:allow_null] = row.delete(:notnull).to_i == 0 ? 'YES' : 'NO'
         
     | 
| 
      
 154 
     | 
    
         
            +
                      row[:default] = row.delete(:dflt_value)
         
     | 
| 
      
 155 
     | 
    
         
            +
                      row[:primary_key] = row.delete(:pk).to_i == 1 ? true : false 
         
     | 
| 
      
 156 
     | 
    
         
            +
                      row[:db_type] = row.delete(:type)
         
     | 
| 
      
 157 
     | 
    
         
            +
                      if m = SCHEMA_TYPE_RE.match(row[:db_type])
         
     | 
| 
      
 158 
     | 
    
         
            +
                        row[:db_type] = m[1]
         
     | 
| 
      
 159 
     | 
    
         
            +
                        row[:max_chars] = m[2].to_i
         
     | 
| 
      
 160 
     | 
    
         
            +
                      else
         
     | 
| 
      
 161 
     | 
    
         
            +
                         row[:max_chars] = nil
         
     | 
| 
       129 
162 
     | 
    
         
             
                      end
         
     | 
| 
      
 163 
     | 
    
         
            +
                      row[:numeric_precision] = nil
         
     | 
| 
      
 164 
     | 
    
         
            +
                      row
         
     | 
| 
       130 
165 
     | 
    
         
             
                    end
         
     | 
| 
      
 166 
     | 
    
         
            +
                    schema_parse_rows(rows)
         
     | 
| 
      
 167 
     | 
    
         
            +
                  end
         
     | 
| 
      
 168 
     | 
    
         
            +
             
     | 
| 
      
 169 
     | 
    
         
            +
                  def schema_parse_tables(opts)
         
     | 
| 
      
 170 
     | 
    
         
            +
                    schemas = {}
         
     | 
| 
      
 171 
     | 
    
         
            +
                    tables.each{|table| schemas[table] = schema_parse_table(table, opts)}
         
     | 
| 
      
 172 
     | 
    
         
            +
                    schemas
         
     | 
| 
       131 
173 
     | 
    
         
             
                  end
         
     | 
| 
       132 
174 
     | 
    
         
             
                end
         
     | 
| 
       133 
175 
     | 
    
         | 
| 
       134 
176 
     | 
    
         
             
                class Dataset < Sequel::Dataset
         
     | 
| 
       135 
     | 
    
         
            -
                  def  
     | 
| 
      
 177 
     | 
    
         
            +
                  def quoted_identifier(c)
         
     | 
| 
      
 178 
     | 
    
         
            +
                    "`#{c}`"
         
     | 
| 
      
 179 
     | 
    
         
            +
                  end
         
     | 
| 
       136 
180 
     | 
    
         | 
| 
       137 
181 
     | 
    
         
             
                  def literal(v)
         
     | 
| 
       138 
182 
     | 
    
         
             
                    case v
         
     | 
| 
      
 183 
     | 
    
         
            +
                    when LiteralString
         
     | 
| 
      
 184 
     | 
    
         
            +
                      v
         
     | 
| 
      
 185 
     | 
    
         
            +
                    when String
         
     | 
| 
      
 186 
     | 
    
         
            +
                      "'#{::SQLite3::Database.quote(v)}'"
         
     | 
| 
       139 
187 
     | 
    
         
             
                    when Time
         
     | 
| 
       140 
188 
     | 
    
         
             
                      literal(v.iso8601)
         
     | 
| 
      
 189 
     | 
    
         
            +
                    when Date, DateTime
         
     | 
| 
      
 190 
     | 
    
         
            +
                      literal(v.to_s)
         
     | 
| 
       141 
191 
     | 
    
         
             
                    else
         
     | 
| 
       142 
192 
     | 
    
         
             
                      super
         
     | 
| 
       143 
193 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -1,70 +1,118 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            require 'thread'
         
     | 
| 
       2 
     | 
    
         
            -
             
     | 
| 
       3 
1 
     | 
    
         
             
            # A ConnectionPool manages access to database connections by keeping
         
     | 
| 
       4 
2 
     | 
    
         
             
            # multiple connections and giving threads exclusive access to each
         
     | 
| 
       5 
3 
     | 
    
         
             
            # connection.
         
     | 
| 
       6 
4 
     | 
    
         
             
            class ConnectionPool
         
     | 
| 
       7 
     | 
    
         
            -
               
     | 
| 
      
 5 
     | 
    
         
            +
              # An array of connections currently being used
         
     | 
| 
      
 6 
     | 
    
         
            +
              attr_reader :allocated
         
     | 
| 
      
 7 
     | 
    
         
            +
              
         
     | 
| 
      
 8 
     | 
    
         
            +
              # An array of connections opened but not currently used
         
     | 
| 
      
 9 
     | 
    
         
            +
              attr_reader :available_connections
         
     | 
| 
      
 10 
     | 
    
         
            +
              
         
     | 
| 
      
 11 
     | 
    
         
            +
              # The proc used to create a new database connection.
         
     | 
| 
      
 12 
     | 
    
         
            +
              attr_accessor :connection_proc
         
     | 
| 
       8 
13 
     | 
    
         | 
| 
      
 14 
     | 
    
         
            +
              # The total number of connections opened, should
         
     | 
| 
      
 15 
     | 
    
         
            +
              # be equal to available_connections.length +
         
     | 
| 
      
 16 
     | 
    
         
            +
              # allocated.length
         
     | 
| 
      
 17 
     | 
    
         
            +
              attr_reader :created_count
         
     | 
| 
      
 18 
     | 
    
         
            +
              alias_method :size, :created_count
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
       9 
20 
     | 
    
         
             
              # The maximum number of connections.
         
     | 
| 
       10 
21 
     | 
    
         
             
              attr_reader :max_size
         
     | 
| 
       11 
22 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
              # The  
     | 
| 
       13 
     | 
    
         
            -
               
     | 
| 
      
 23 
     | 
    
         
            +
              # The mutex that protects access to the other internal vairables.  You must use
         
     | 
| 
      
 24 
     | 
    
         
            +
              # this if you want to manipulate the variables safely.
         
     | 
| 
      
 25 
     | 
    
         
            +
              attr_reader :mutex
         
     | 
| 
       14 
26 
     | 
    
         | 
| 
       15 
     | 
    
         
            -
              attr_reader :available_connections, :allocated, :created_count
         
     | 
| 
       16 
27 
     | 
    
         | 
| 
       17 
28 
     | 
    
         
             
              # Constructs a new pool with a maximum size. If a block is supplied, it
         
     | 
| 
       18 
29 
     | 
    
         
             
              # is used to create new connections as they are needed.
         
     | 
| 
       19 
30 
     | 
    
         
             
              #
         
     | 
| 
       20 
     | 
    
         
            -
              #   pool = ConnectionPool.new(10) {MyConnection.new(opts)}
         
     | 
| 
      
 31 
     | 
    
         
            +
              #   pool = ConnectionPool.new(:max_connections=>10) {MyConnection.new(opts)}
         
     | 
| 
       21 
32 
     | 
    
         
             
              #
         
     | 
| 
       22 
33 
     | 
    
         
             
              # The connection creation proc can be changed at any time by assigning a 
         
     | 
| 
       23 
34 
     | 
    
         
             
              # Proc to pool#connection_proc.
         
     | 
| 
       24 
35 
     | 
    
         
             
              #
         
     | 
| 
       25 
     | 
    
         
            -
              #   pool = ConnectionPool.new(10)
         
     | 
| 
      
 36 
     | 
    
         
            +
              #   pool = ConnectionPool.new(:max_connections=>10)
         
     | 
| 
       26 
37 
     | 
    
         
             
              #   pool.connection_proc = proc {MyConnection.new(opts)}
         
     | 
| 
       27 
     | 
    
         
            -
               
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
      
 38 
     | 
    
         
            +
              #
         
     | 
| 
      
 39 
     | 
    
         
            +
              # The connection pool takes the following options:
         
     | 
| 
      
 40 
     | 
    
         
            +
              #
         
     | 
| 
      
 41 
     | 
    
         
            +
              # * :max_connections - The maximum number of connections the connection pool
         
     | 
| 
      
 42 
     | 
    
         
            +
              #   will open (default 4)
         
     | 
| 
      
 43 
     | 
    
         
            +
              # * :pool_convert_exceptions - Whether to convert non-StandardError based exceptions
         
     | 
| 
      
 44 
     | 
    
         
            +
              #   to RuntimeError exceptions (default true)
         
     | 
| 
      
 45 
     | 
    
         
            +
              # * :pool_reuse_connections - Which strategy to follow in regards to reusing connections:
         
     | 
| 
      
 46 
     | 
    
         
            +
              #   * :always - Always reuse a connection that belongs to the same thread
         
     | 
| 
      
 47 
     | 
    
         
            +
              #   * :allow - Only reuse a connection that belongs to the same thread if
         
     | 
| 
      
 48 
     | 
    
         
            +
              #     another cannot be acquired immediately (default)
         
     | 
| 
      
 49 
     | 
    
         
            +
              #   * :last_resort - Only reuse a connection that belongs to the same thread if
         
     | 
| 
      
 50 
     | 
    
         
            +
              #     the pool timeout has expired
         
     | 
| 
      
 51 
     | 
    
         
            +
              #   * :never - Never reuse a connection that belongs to the same thread
         
     | 
| 
      
 52 
     | 
    
         
            +
              # * :pool_sleep_time - The amount of time to sleep before attempting to acquire
         
     | 
| 
      
 53 
     | 
    
         
            +
              #   a connection again (default 0.001)
         
     | 
| 
      
 54 
     | 
    
         
            +
              # * :pool_timeout - The amount of seconds to wait to acquire a connection
         
     | 
| 
      
 55 
     | 
    
         
            +
              #   before raising a PoolTimeoutError (default 5)
         
     | 
| 
      
 56 
     | 
    
         
            +
              def initialize(opts = {}, &block)
         
     | 
| 
      
 57 
     | 
    
         
            +
                @max_size = opts[:max_connections] || 4
         
     | 
| 
       29 
58 
     | 
    
         
             
                @mutex = Mutex.new
         
     | 
| 
       30 
59 
     | 
    
         
             
                @connection_proc = block
         
     | 
| 
       31 
60 
     | 
    
         | 
| 
       32 
61 
     | 
    
         
             
                @available_connections = []
         
     | 
| 
       33 
     | 
    
         
            -
                @allocated =  
     | 
| 
      
 62 
     | 
    
         
            +
                @allocated = []
         
     | 
| 
       34 
63 
     | 
    
         
             
                @created_count = 0
         
     | 
| 
      
 64 
     | 
    
         
            +
                @timeout = opts[:pool_timeout] || 5
         
     | 
| 
      
 65 
     | 
    
         
            +
                @sleep_time = opts[:pool_sleep_time] || 0.001
         
     | 
| 
      
 66 
     | 
    
         
            +
                @reuse_connections = opts[:pool_reuse_connections] || :allow
         
     | 
| 
      
 67 
     | 
    
         
            +
                @convert_exceptions = opts.include?(:pool_convert_exceptions) ? opts[:pool_convert_exceptions] : true
         
     | 
| 
       35 
68 
     | 
    
         
             
              end
         
     | 
| 
       36 
69 
     | 
    
         | 
| 
       37 
     | 
    
         
            -
              #  
     | 
| 
       38 
     | 
    
         
            -
               
     | 
| 
       39 
     | 
    
         
            -
                @created_count
         
     | 
| 
       40 
     | 
    
         
            -
              end
         
     | 
| 
       41 
     | 
    
         
            -
              
         
     | 
| 
       42 
     | 
    
         
            -
              # Assigns a connection to the current thread, yielding the connection
         
     | 
| 
       43 
     | 
    
         
            -
              # to the supplied block.
         
     | 
| 
      
 70 
     | 
    
         
            +
              # Chooses the first available connection, or if none are available,
         
     | 
| 
      
 71 
     | 
    
         
            +
              # creates a new connection.  Passes the connection to the supplied block:
         
     | 
| 
       44 
72 
     | 
    
         
             
              # 
         
     | 
| 
       45 
73 
     | 
    
         
             
              #   pool.hold {|conn| conn.execute('DROP TABLE posts')}
         
     | 
| 
       46 
74 
     | 
    
         
             
              # 
         
     | 
| 
       47 
     | 
    
         
            -
              # Pool#hold  
     | 
| 
       48 
     | 
    
         
            -
              # the same thread without blocking 
     | 
| 
      
 75 
     | 
    
         
            +
              # Pool#hold can be re-entrant, meaning it can be called recursively in
         
     | 
| 
      
 76 
     | 
    
         
            +
              # the same thread without blocking if the :pool_reuse_connections option
         
     | 
| 
      
 77 
     | 
    
         
            +
              # was set to :always or :allow.  Depending on the :pool_reuse_connections
         
     | 
| 
      
 78 
     | 
    
         
            +
              # option you may get the connection currently used by the thread or a new connection.
         
     | 
| 
       49 
79 
     | 
    
         
             
              #
         
     | 
| 
       50 
     | 
    
         
            -
              # If no connection is available 
     | 
| 
       51 
     | 
    
         
            -
              #  
     | 
| 
      
 80 
     | 
    
         
            +
              # If no connection is immediately available and the pool is already using the maximum
         
     | 
| 
      
 81 
     | 
    
         
            +
              # number of connections, Pool#hold will block until a connection
         
     | 
| 
      
 82 
     | 
    
         
            +
              # is available or the timeout expires.  If the timeout expires before a
         
     | 
| 
      
 83 
     | 
    
         
            +
              # connection can be acquired, a Sequel::Error::PoolTimeoutError is 
         
     | 
| 
      
 84 
     | 
    
         
            +
              # raised.
         
     | 
| 
       52 
85 
     | 
    
         
             
              def hold
         
     | 
| 
       53 
     | 
    
         
            -
                t = Thread.current
         
     | 
| 
       54 
     | 
    
         
            -
                if (conn = owned_connection(t))
         
     | 
| 
       55 
     | 
    
         
            -
                  return yield(conn)
         
     | 
| 
       56 
     | 
    
         
            -
                end
         
     | 
| 
       57 
     | 
    
         
            -
                while !(conn = acquire(t))
         
     | 
| 
       58 
     | 
    
         
            -
                  sleep 0.001
         
     | 
| 
       59 
     | 
    
         
            -
                end
         
     | 
| 
       60 
86 
     | 
    
         
             
                begin
         
     | 
| 
       61 
     | 
    
         
            -
                   
     | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
                   
     | 
| 
      
 87 
     | 
    
         
            +
                  t = Thread.current
         
     | 
| 
      
 88 
     | 
    
         
            +
                  time = Time.new
         
     | 
| 
      
 89 
     | 
    
         
            +
                  timeout = time + @timeout
         
     | 
| 
      
 90 
     | 
    
         
            +
                  sleep_time = @sleep_time
         
     | 
| 
      
 91 
     | 
    
         
            +
                  reuse = @reuse_connections
         
     | 
| 
      
 92 
     | 
    
         
            +
                  if (reuse == :always) && (conn = owned_connection(t))
         
     | 
| 
      
 93 
     | 
    
         
            +
                    return yield(conn)
         
     | 
| 
      
 94 
     | 
    
         
            +
                  end
         
     | 
| 
      
 95 
     | 
    
         
            +
                  reuse = reuse == :allow ? true : false
         
     | 
| 
      
 96 
     | 
    
         
            +
                  until conn = acquire(t)
         
     | 
| 
      
 97 
     | 
    
         
            +
                    if reuse && (conn = owned_connection(t))
         
     | 
| 
      
 98 
     | 
    
         
            +
                      return yield(conn)
         
     | 
| 
      
 99 
     | 
    
         
            +
                    end
         
     | 
| 
      
 100 
     | 
    
         
            +
                    if Time.new > timeout
         
     | 
| 
      
 101 
     | 
    
         
            +
                      if (@reuse_connections == :last_resort) && (conn = owned_connection(t))
         
     | 
| 
      
 102 
     | 
    
         
            +
                        return yield(conn)
         
     | 
| 
      
 103 
     | 
    
         
            +
                      end
         
     | 
| 
      
 104 
     | 
    
         
            +
                      raise(::Sequel::Error::PoolTimeoutError)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    end
         
     | 
| 
      
 106 
     | 
    
         
            +
                    sleep sleep_time
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
      
 108 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 109 
     | 
    
         
            +
                    yield conn
         
     | 
| 
      
 110 
     | 
    
         
            +
                  ensure
         
     | 
| 
      
 111 
     | 
    
         
            +
                    release(t, conn)
         
     | 
| 
      
 112 
     | 
    
         
            +
                  end
         
     | 
| 
      
 113 
     | 
    
         
            +
                rescue Exception => e
         
     | 
| 
      
 114 
     | 
    
         
            +
                  raise(@convert_exceptions && !e.is_a?(StandardError) ? RuntimeError.new(e.message) : e)
         
     | 
| 
       64 
115 
     | 
    
         
             
                end
         
     | 
| 
       65 
     | 
    
         
            -
              rescue Exception => e
         
     | 
| 
       66 
     | 
    
         
            -
                # if the error is not a StandardError it is converted into RuntimeError.
         
     | 
| 
       67 
     | 
    
         
            -
                raise e.is_a?(StandardError) ? e : e.message
         
     | 
| 
       68 
116 
     | 
    
         
             
              end
         
     | 
| 
       69 
117 
     | 
    
         | 
| 
       70 
118 
     | 
    
         
             
              # Removes all connection currently available, optionally yielding each 
         
     | 
| 
         @@ -80,65 +128,84 @@ class ConnectionPool 
     | 
|
| 
       80 
128 
     | 
    
         
             
              end
         
     | 
| 
       81 
129 
     | 
    
         | 
| 
       82 
130 
     | 
    
         
             
              private
         
     | 
| 
       83 
     | 
    
         
            -
             
     | 
| 
       84 
     | 
    
         
            -
             
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
      
 131 
     | 
    
         
            +
             
     | 
| 
      
 132 
     | 
    
         
            +
              # Returns the connection owned by the supplied thread, if any.
         
     | 
| 
      
 133 
     | 
    
         
            +
              def owned_connection(thread)
         
     | 
| 
      
 134 
     | 
    
         
            +
                @mutex.synchronize do 
         
     | 
| 
      
 135 
     | 
    
         
            +
                  x = @allocated.assoc(thread)
         
     | 
| 
      
 136 
     | 
    
         
            +
                  x[1] if x
         
     | 
| 
       86 
137 
     | 
    
         
             
                end
         
     | 
| 
       87 
     | 
    
         
            -
             
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
             
     | 
| 
       90 
     | 
    
         
            -
             
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
             
     | 
| 
       93 
     | 
    
         
            -
                     
     | 
| 
      
 138 
     | 
    
         
            +
              end
         
     | 
| 
      
 139 
     | 
    
         
            +
              
         
     | 
| 
      
 140 
     | 
    
         
            +
              # Assigns a connection to the supplied thread, if one is available.
         
     | 
| 
      
 141 
     | 
    
         
            +
              def acquire(thread)
         
     | 
| 
      
 142 
     | 
    
         
            +
                @mutex.synchronize do
         
     | 
| 
      
 143 
     | 
    
         
            +
                  if conn = available
         
     | 
| 
      
 144 
     | 
    
         
            +
                    @allocated << [thread, conn]
         
     | 
| 
      
 145 
     | 
    
         
            +
                    conn
         
     | 
| 
       94 
146 
     | 
    
         
             
                  end
         
     | 
| 
       95 
147 
     | 
    
         
             
                end
         
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
                 
     | 
| 
       102 
     | 
    
         
            -
             
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
       104 
     | 
    
         
            -
             
     | 
| 
       105 
     | 
    
         
            -
             
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
             
     | 
| 
       108 
     | 
    
         
            -
             
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
             
     | 
| 
      
 148 
     | 
    
         
            +
              end
         
     | 
| 
      
 149 
     | 
    
         
            +
              
         
     | 
| 
      
 150 
     | 
    
         
            +
              # Returns an available connection. If no connection is available,
         
     | 
| 
      
 151 
     | 
    
         
            +
              # tries to create a new connection.
         
     | 
| 
      
 152 
     | 
    
         
            +
              def available
         
     | 
| 
      
 153 
     | 
    
         
            +
                @available_connections.pop || make_new
         
     | 
| 
      
 154 
     | 
    
         
            +
              end
         
     | 
| 
      
 155 
     | 
    
         
            +
              
         
     | 
| 
      
 156 
     | 
    
         
            +
              # Creates a new connection if the size of the pool is less than the
         
     | 
| 
      
 157 
     | 
    
         
            +
              # maximum size.
         
     | 
| 
      
 158 
     | 
    
         
            +
              def make_new
         
     | 
| 
      
 159 
     | 
    
         
            +
                if @created_count < @max_size
         
     | 
| 
      
 160 
     | 
    
         
            +
                  @created_count += 1
         
     | 
| 
      
 161 
     | 
    
         
            +
                  @connection_proc ? @connection_proc.call : \
         
     | 
| 
      
 162 
     | 
    
         
            +
                    (raise Error, "No connection proc specified")
         
     | 
| 
       111 
163 
     | 
    
         
             
                end
         
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
             
     | 
| 
       114 
     | 
    
         
            -
             
     | 
| 
       115 
     | 
    
         
            -
             
     | 
| 
       116 
     | 
    
         
            -
             
     | 
| 
       117 
     | 
    
         
            -
             
     | 
| 
       118 
     | 
    
         
            -
                   
     | 
| 
      
 164 
     | 
    
         
            +
              end
         
     | 
| 
      
 165 
     | 
    
         
            +
              
         
     | 
| 
      
 166 
     | 
    
         
            +
              # Releases the connection assigned to the supplied thread.
         
     | 
| 
      
 167 
     | 
    
         
            +
              def release(thread, conn)
         
     | 
| 
      
 168 
     | 
    
         
            +
                @mutex.synchronize do
         
     | 
| 
      
 169 
     | 
    
         
            +
                  @allocated.delete([thread, conn])
         
     | 
| 
      
 170 
     | 
    
         
            +
                  @available_connections << conn
         
     | 
| 
       119 
171 
     | 
    
         
             
                end
         
     | 
| 
      
 172 
     | 
    
         
            +
              end
         
     | 
| 
       120 
173 
     | 
    
         
             
            end
         
     | 
| 
       121 
174 
     | 
    
         | 
| 
       122 
175 
     | 
    
         
             
            # A SingleThreadedPool acts as a replacement for a ConnectionPool for use
         
     | 
| 
       123 
176 
     | 
    
         
             
            # in single-threaded applications. ConnectionPool imposes a substantial
         
     | 
| 
       124 
177 
     | 
    
         
             
            # performance penalty, so SingleThreadedPool is used to gain some speed.
         
     | 
| 
      
 178 
     | 
    
         
            +
            #
         
     | 
| 
      
 179 
     | 
    
         
            +
            # Note that using a single threaded pool with some adapters can cause
         
     | 
| 
      
 180 
     | 
    
         
            +
            # errors in certain cases, see Sequel.single_threaded=.
         
     | 
| 
       125 
181 
     | 
    
         
             
            class SingleThreadedPool
         
     | 
| 
      
 182 
     | 
    
         
            +
              # The single database connection for the pool
         
     | 
| 
       126 
183 
     | 
    
         
             
              attr_reader :conn
         
     | 
| 
      
 184 
     | 
    
         
            +
             
     | 
| 
      
 185 
     | 
    
         
            +
              # The proc used to create a new database connection
         
     | 
| 
       127 
186 
     | 
    
         
             
              attr_writer :connection_proc
         
     | 
| 
       128 
187 
     | 
    
         | 
| 
       129 
188 
     | 
    
         
             
              # Initializes the instance with the supplied block as the connection_proc.
         
     | 
| 
       130 
     | 
    
         
            -
               
     | 
| 
      
 189 
     | 
    
         
            +
              #
         
     | 
| 
      
 190 
     | 
    
         
            +
              # The single threaded pool takes the following options:
         
     | 
| 
      
 191 
     | 
    
         
            +
              #
         
     | 
| 
      
 192 
     | 
    
         
            +
              # * :pool_convert_exceptions - Whether to convert non-StandardError based exceptions
         
     | 
| 
      
 193 
     | 
    
         
            +
              #   to RuntimeError exceptions (default true)
         
     | 
| 
      
 194 
     | 
    
         
            +
              def initialize(opts={}, &block)
         
     | 
| 
       131 
195 
     | 
    
         
             
                @connection_proc = block
         
     | 
| 
      
 196 
     | 
    
         
            +
                @convert_exceptions = opts.include?(:pool_convert_exceptions) ? opts[:pool_convert_exceptions] : true
         
     | 
| 
       132 
197 
     | 
    
         
             
              end
         
     | 
| 
       133 
198 
     | 
    
         | 
| 
       134 
199 
     | 
    
         
             
              # Yields the connection to the supplied block. This method simulates the
         
     | 
| 
       135 
200 
     | 
    
         
             
              # ConnectionPool#hold API.
         
     | 
| 
       136 
201 
     | 
    
         
             
              def hold
         
     | 
| 
       137 
     | 
    
         
            -
                 
     | 
| 
       138 
     | 
    
         
            -
             
     | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
       140 
     | 
    
         
            -
                 
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
      
 202 
     | 
    
         
            +
                begin
         
     | 
| 
      
 203 
     | 
    
         
            +
                  @conn ||= @connection_proc.call
         
     | 
| 
      
 204 
     | 
    
         
            +
                  yield @conn
         
     | 
| 
      
 205 
     | 
    
         
            +
                rescue Exception => e
         
     | 
| 
      
 206 
     | 
    
         
            +
                  # if the error is not a StandardError it is converted into RuntimeError.
         
     | 
| 
      
 207 
     | 
    
         
            +
                  raise(@convert_exceptions && !e.is_a?(StandardError) ? RuntimeError.new(e.message) : e)
         
     | 
| 
      
 208 
     | 
    
         
            +
                end
         
     | 
| 
       142 
209 
     | 
    
         
             
              end
         
     | 
| 
       143 
210 
     | 
    
         | 
| 
       144 
211 
     | 
    
         
             
              # Disconnects from the database. Once a connection is requested using
         
     | 
    
        data/lib/sequel_core/core_ext.rb
    CHANGED
    
    | 
         @@ -1,66 +1,201 @@ 
     | 
|
| 
       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 
     | 
    
         
            -
            class 
     | 
| 
       47 
     | 
    
         
            -
               
     | 
| 
       48 
     | 
    
         
            -
             
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
             
     | 
| 
       51 
     | 
    
         
            -
             
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
            class  
     | 
| 
       54 
     | 
    
         
            -
              #  
     | 
| 
       55 
     | 
    
         
            -
               
     | 
| 
       56 
     | 
    
         
            -
             
     | 
| 
       57 
     | 
    
         
            -
               
     | 
| 
       58 
     | 
    
         
            -
             
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
       61 
     | 
    
         
            -
               
     | 
| 
       62 
     | 
    
         
            -
              #  
     | 
| 
       63 
     | 
    
         
            -
               
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
               
     | 
| 
       66 
     | 
    
         
            -
            end
         
     | 
| 
      
 1 
     | 
    
         
            +
            # This file includes augmentations to the core ruby classes the Sequel uses,
         
     | 
| 
      
 2 
     | 
    
         
            +
            # which are unrelated to the creation of SQL.  It includes common
         
     | 
| 
      
 3 
     | 
    
         
            +
            # idioms to reduce the amount of code duplication.
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            class Array
         
     | 
| 
      
 6 
     | 
    
         
            +
              # True if the array is not empty and all of its elements are
         
     | 
| 
      
 7 
     | 
    
         
            +
              # arrays of size 2.  This is used to determine if the array
         
     | 
| 
      
 8 
     | 
    
         
            +
              # could be a specifier of conditions, used similarly to a hash
         
     | 
| 
      
 9 
     | 
    
         
            +
              # but allowing for duplicate keys.
         
     | 
| 
      
 10 
     | 
    
         
            +
              #
         
     | 
| 
      
 11 
     | 
    
         
            +
              #    hash.to_a.all_two_pairs? # => true unless hash is empty
         
     | 
| 
      
 12 
     | 
    
         
            +
              def all_two_pairs?
         
     | 
| 
      
 13 
     | 
    
         
            +
                !empty? && all?{|i| (Array === i) && (i.length == 2)}
         
     | 
| 
      
 14 
     | 
    
         
            +
              end
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
              # Removes and returns the last member of the array if it is a hash. Otherwise,
         
     | 
| 
      
 17 
     | 
    
         
            +
              # an empty hash is returned This method is useful when writing methods that
         
     | 
| 
      
 18 
     | 
    
         
            +
              # take an options hash as the last parameter. For example:
         
     | 
| 
      
 19 
     | 
    
         
            +
              #
         
     | 
| 
      
 20 
     | 
    
         
            +
              #   def validate_each(*args, &block)
         
     | 
| 
      
 21 
     | 
    
         
            +
              #     opts = args.extract_options!
         
     | 
| 
      
 22 
     | 
    
         
            +
              #     ...
         
     | 
| 
      
 23 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 24 
     | 
    
         
            +
              def extract_options!
         
     | 
| 
      
 25 
     | 
    
         
            +
                last.is_a?(Hash) ? pop : {}
         
     | 
| 
      
 26 
     | 
    
         
            +
              end
         
     | 
| 
      
 27 
     | 
    
         
            +
            end
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            module Enumerable
         
     | 
| 
      
 30 
     | 
    
         
            +
              # Invokes the specified method for each item, along with the supplied
         
     | 
| 
      
 31 
     | 
    
         
            +
              # arguments.
         
     | 
| 
      
 32 
     | 
    
         
            +
              def send_each(sym, *args)
         
     | 
| 
      
 33 
     | 
    
         
            +
                each{|i| i.send(sym, *args)}
         
     | 
| 
      
 34 
     | 
    
         
            +
              end
         
     | 
| 
      
 35 
     | 
    
         
            +
            end
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            class FalseClass
         
     | 
| 
      
 38 
     | 
    
         
            +
              # false is always blank
         
     | 
| 
      
 39 
     | 
    
         
            +
              def blank?
         
     | 
| 
      
 40 
     | 
    
         
            +
                true
         
     | 
| 
      
 41 
     | 
    
         
            +
              end
         
     | 
| 
      
 42 
     | 
    
         
            +
            end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
            # Add some metaprogramming methods to avoid class << self
         
     | 
| 
      
 45 
     | 
    
         
            +
            class Module
         
     | 
| 
      
 46 
     | 
    
         
            +
              # Defines an instance method within a class/module
         
     | 
| 
      
 47 
     | 
    
         
            +
              def class_def(name, &block)
         
     | 
| 
      
 48 
     | 
    
         
            +
                class_eval{define_method(name, &block)}
         
     | 
| 
      
 49 
     | 
    
         
            +
              end 
         
     | 
| 
      
 50 
     | 
    
         
            +
             
     | 
| 
      
 51 
     | 
    
         
            +
              private
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
              # Define instance method(s) that calls class method(s) of the
         
     | 
| 
      
 54 
     | 
    
         
            +
              # same name. Replaces the construct:
         
     | 
| 
      
 55 
     | 
    
         
            +
              #
         
     | 
| 
      
 56 
     | 
    
         
            +
              #   define_method(meth){self.class.send(meth)}
         
     | 
| 
      
 57 
     | 
    
         
            +
              def class_attr_reader(*meths)
         
     | 
| 
      
 58 
     | 
    
         
            +
                meths.each{|meth| define_method(meth){self.class.send(meth)}}
         
     | 
| 
      
 59 
     | 
    
         
            +
              end
         
     | 
| 
      
 60 
     | 
    
         
            +
             
     | 
| 
      
 61 
     | 
    
         
            +
              # Create an alias for a singleton/class method.
         
     | 
| 
      
 62 
     | 
    
         
            +
              # Replaces the construct:
         
     | 
| 
      
 63 
     | 
    
         
            +
              #
         
     | 
| 
      
 64 
     | 
    
         
            +
              #   class << self
         
     | 
| 
      
 65 
     | 
    
         
            +
              #     alias_method to, from
         
     | 
| 
      
 66 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 67 
     | 
    
         
            +
              def metaalias(to, from)
         
     | 
| 
      
 68 
     | 
    
         
            +
                metaclass.instance_eval{alias_method to, from}
         
     | 
| 
      
 69 
     | 
    
         
            +
              end
         
     | 
| 
      
 70 
     | 
    
         
            +
              
         
     | 
| 
      
 71 
     | 
    
         
            +
              # Make a singleton/class attribute accessor method(s).
         
     | 
| 
      
 72 
     | 
    
         
            +
              # Replaces the construct:
         
     | 
| 
      
 73 
     | 
    
         
            +
              #
         
     | 
| 
      
 74 
     | 
    
         
            +
              #   class << self
         
     | 
| 
      
 75 
     | 
    
         
            +
              #     attr_accessor *meths
         
     | 
| 
      
 76 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 77 
     | 
    
         
            +
              def metaattr_accessor(*meths)
         
     | 
| 
      
 78 
     | 
    
         
            +
                metaclass.instance_eval{attr_accessor(*meths)}
         
     | 
| 
      
 79 
     | 
    
         
            +
              end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
              # Make a singleton/class method(s) private.
         
     | 
| 
      
 82 
     | 
    
         
            +
              # Make a singleton/class attribute reader method(s).
         
     | 
| 
      
 83 
     | 
    
         
            +
              # Replaces the construct:
         
     | 
| 
      
 84 
     | 
    
         
            +
              #
         
     | 
| 
      
 85 
     | 
    
         
            +
              #   class << self
         
     | 
| 
      
 86 
     | 
    
         
            +
              #     attr_reader *meths
         
     | 
| 
      
 87 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 88 
     | 
    
         
            +
              def metaattr_reader(*meths)
         
     | 
| 
      
 89 
     | 
    
         
            +
                metaclass.instance_eval{attr_reader(*meths)}
         
     | 
| 
      
 90 
     | 
    
         
            +
              end
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
              # Make a singleton/class method(s) private.
         
     | 
| 
      
 93 
     | 
    
         
            +
              # Replaces the construct:
         
     | 
| 
      
 94 
     | 
    
         
            +
              #
         
     | 
| 
      
 95 
     | 
    
         
            +
              #   class << self
         
     | 
| 
      
 96 
     | 
    
         
            +
              #     private *meths
         
     | 
| 
      
 97 
     | 
    
         
            +
              #   end
         
     | 
| 
      
 98 
     | 
    
         
            +
              def metaprivate(*meths)
         
     | 
| 
      
 99 
     | 
    
         
            +
                metaclass.instance_eval{private(*meths)}
         
     | 
| 
      
 100 
     | 
    
         
            +
              end
         
     | 
| 
      
 101 
     | 
    
         
            +
            end
         
     | 
| 
      
 102 
     | 
    
         
            +
             
     | 
| 
      
 103 
     | 
    
         
            +
            # Helpers from Metaid and a bit more
         
     | 
| 
      
 104 
     | 
    
         
            +
            class Object
         
     | 
| 
      
 105 
     | 
    
         
            +
              # Objects are blank if they respond true to empty?
         
     | 
| 
      
 106 
     | 
    
         
            +
              def blank?
         
     | 
| 
      
 107 
     | 
    
         
            +
                respond_to?(:empty?) && empty?
         
     | 
| 
      
 108 
     | 
    
         
            +
              end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
              # Returns true if the object is an instance of one of the classes
         
     | 
| 
      
 111 
     | 
    
         
            +
              def is_one_of?(*classes)
         
     | 
| 
      
 112 
     | 
    
         
            +
                !!classes.find{|c| is_a?(c)}
         
     | 
| 
      
 113 
     | 
    
         
            +
              end
         
     | 
| 
      
 114 
     | 
    
         
            +
             
     | 
| 
      
 115 
     | 
    
         
            +
              # Add methods to the object's metaclass
         
     | 
| 
      
 116 
     | 
    
         
            +
              def meta_def(name, &block)
         
     | 
| 
      
 117 
     | 
    
         
            +
                meta_eval{define_method(name, &block)}
         
     | 
| 
      
 118 
     | 
    
         
            +
              end 
         
     | 
| 
      
 119 
     | 
    
         
            +
             
     | 
| 
      
 120 
     | 
    
         
            +
              # Evaluate the block in the context of the object's metaclass
         
     | 
| 
      
 121 
     | 
    
         
            +
              def meta_eval(&block)
         
     | 
| 
      
 122 
     | 
    
         
            +
                metaclass.instance_eval(&block)
         
     | 
| 
      
 123 
     | 
    
         
            +
              end 
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
              # The hidden singleton lurks behind everyone
         
     | 
| 
      
 126 
     | 
    
         
            +
              def metaclass
         
     | 
| 
      
 127 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 128 
     | 
    
         
            +
                  self
         
     | 
| 
      
 129 
     | 
    
         
            +
                end 
         
     | 
| 
      
 130 
     | 
    
         
            +
              end 
         
     | 
| 
      
 131 
     | 
    
         
            +
            end
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
            class NilClass
         
     | 
| 
      
 134 
     | 
    
         
            +
              # nil is always blank
         
     | 
| 
      
 135 
     | 
    
         
            +
              def blank?
         
     | 
| 
      
 136 
     | 
    
         
            +
                true
         
     | 
| 
      
 137 
     | 
    
         
            +
              end
         
     | 
| 
      
 138 
     | 
    
         
            +
            end
         
     | 
| 
      
 139 
     | 
    
         
            +
             
     | 
| 
      
 140 
     | 
    
         
            +
            class Numeric
         
     | 
| 
      
 141 
     | 
    
         
            +
              # Numerics are never blank (not even 0)
         
     | 
| 
      
 142 
     | 
    
         
            +
              def blank?
         
     | 
| 
      
 143 
     | 
    
         
            +
                false
         
     | 
| 
      
 144 
     | 
    
         
            +
              end
         
     | 
| 
      
 145 
     | 
    
         
            +
            end
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
            class Range
         
     | 
| 
      
 148 
     | 
    
         
            +
              # Returns the interval between the beginning and end of the range.
         
     | 
| 
      
 149 
     | 
    
         
            +
              #
         
     | 
| 
      
 150 
     | 
    
         
            +
              # For exclusive ranges, is one less than the inclusive range:
         
     | 
| 
      
 151 
     | 
    
         
            +
              #
         
     | 
| 
      
 152 
     | 
    
         
            +
              #   (0..10).interval # => 10
         
     | 
| 
      
 153 
     | 
    
         
            +
              #   (0...10).interval # => 9
         
     | 
| 
      
 154 
     | 
    
         
            +
              #
         
     | 
| 
      
 155 
     | 
    
         
            +
              # Only works for numeric ranges, for other ranges the result is undefined,
         
     | 
| 
      
 156 
     | 
    
         
            +
              # and the method may raise an error.
         
     | 
| 
      
 157 
     | 
    
         
            +
              def interval
         
     | 
| 
      
 158 
     | 
    
         
            +
                last - first - (exclude_end? ? 1 : 0)
         
     | 
| 
      
 159 
     | 
    
         
            +
              end
         
     | 
| 
      
 160 
     | 
    
         
            +
            end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
            class String
         
     | 
| 
      
 163 
     | 
    
         
            +
              # Strings are blank if they are empty or include only whitespace
         
     | 
| 
      
 164 
     | 
    
         
            +
              def blank?
         
     | 
| 
      
 165 
     | 
    
         
            +
                strip.empty?
         
     | 
| 
      
 166 
     | 
    
         
            +
              end
         
     | 
| 
      
 167 
     | 
    
         
            +
             
     | 
| 
      
 168 
     | 
    
         
            +
              # Converts a string into a Date object.
         
     | 
| 
      
 169 
     | 
    
         
            +
              def to_date
         
     | 
| 
      
 170 
     | 
    
         
            +
                begin
         
     | 
| 
      
 171 
     | 
    
         
            +
                  Date.parse(self)
         
     | 
| 
      
 172 
     | 
    
         
            +
                rescue => e
         
     | 
| 
      
 173 
     | 
    
         
            +
                  raise Sequel::Error::InvalidValue, "Invalid date value '#{self}' (#{e.message})"
         
     | 
| 
      
 174 
     | 
    
         
            +
                end
         
     | 
| 
      
 175 
     | 
    
         
            +
              end
         
     | 
| 
      
 176 
     | 
    
         
            +
             
     | 
| 
      
 177 
     | 
    
         
            +
              # Converts a string into a DateTime object.
         
     | 
| 
      
 178 
     | 
    
         
            +
              def to_datetime
         
     | 
| 
      
 179 
     | 
    
         
            +
                begin
         
     | 
| 
      
 180 
     | 
    
         
            +
                  DateTime.parse(self)
         
     | 
| 
      
 181 
     | 
    
         
            +
                rescue => e
         
     | 
| 
      
 182 
     | 
    
         
            +
                  raise Sequel::Error::InvalidValue, "Invalid date value '#{self}' (#{e.message})"
         
     | 
| 
      
 183 
     | 
    
         
            +
                end
         
     | 
| 
      
 184 
     | 
    
         
            +
              end
         
     | 
| 
      
 185 
     | 
    
         
            +
             
     | 
| 
      
 186 
     | 
    
         
            +
              # Converts a string into a Time object.
         
     | 
| 
      
 187 
     | 
    
         
            +
              def to_time
         
     | 
| 
      
 188 
     | 
    
         
            +
                begin
         
     | 
| 
      
 189 
     | 
    
         
            +
                  Time.parse(self)
         
     | 
| 
      
 190 
     | 
    
         
            +
                rescue => e
         
     | 
| 
      
 191 
     | 
    
         
            +
                  raise Sequel::Error::InvalidValue, "Invalid time value '#{self}' (#{e.message})"
         
     | 
| 
      
 192 
     | 
    
         
            +
                end
         
     | 
| 
      
 193 
     | 
    
         
            +
              end
         
     | 
| 
      
 194 
     | 
    
         
            +
            end
         
     | 
| 
      
 195 
     | 
    
         
            +
             
     | 
| 
      
 196 
     | 
    
         
            +
            class TrueClass
         
     | 
| 
      
 197 
     | 
    
         
            +
              # true is never blank
         
     | 
| 
      
 198 
     | 
    
         
            +
              def blank?
         
     | 
| 
      
 199 
     | 
    
         
            +
                false
         
     | 
| 
      
 200 
     | 
    
         
            +
              end
         
     | 
| 
      
 201 
     | 
    
         
            +
            end
         
     |