activerecord 3.1.1 → 3.1.2.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG.md +6592 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +2 -2
- data/lib/active_record/aggregations.rb +4 -3
- data/lib/active_record/associations.rb +5 -5
- data/lib/active_record/associations/collection_association.rb +6 -2
- data/lib/active_record/associations/has_many_through_association.rb +43 -21
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/base.rb +4 -4
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +8 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +2 -3
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +11 -2
- data/lib/active_record/connection_adapters/mysql_adapter.rb +11 -2
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +64 -20
- data/lib/active_record/migration.rb +2 -2
- data/lib/active_record/query_cache.rb +4 -2
- data/lib/active_record/reflection.rb +1 -1
- data/lib/active_record/version.rb +2 -2
- metadata +135 -128
- data/CHANGELOG +0 -6546
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2004-2011 David Heinemeier Hansson
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
CHANGED
@@ -150,7 +150,7 @@ A short rundown of some of the major features:
|
|
150
150
|
* Database agnostic schema management with Migrations.
|
151
151
|
|
152
152
|
class AddSystemSettings < ActiveRecord::Migration
|
153
|
-
def
|
153
|
+
def up
|
154
154
|
create_table :system_settings do |t|
|
155
155
|
t.string :name
|
156
156
|
t.string :label
|
@@ -162,7 +162,7 @@ A short rundown of some of the major features:
|
|
162
162
|
SystemSetting.create :name => "notice", :label => "Use notice?", :value => 1
|
163
163
|
end
|
164
164
|
|
165
|
-
def
|
165
|
+
def down
|
166
166
|
drop_table :system_settings
|
167
167
|
end
|
168
168
|
end
|
@@ -172,8 +172,8 @@ module ActiveRecord
|
|
172
172
|
# with this option.
|
173
173
|
# * <tt>:mapping</tt> - Specifies the mapping of entity attributes to attributes of the value
|
174
174
|
# object. Each mapping is represented as an array where the first item is the name of the
|
175
|
-
# entity attribute and the second item is the name the attribute in the value object. The
|
176
|
-
# order in which mappings are defined
|
175
|
+
# entity attribute and the second item is the name of the attribute in the value object. The
|
176
|
+
# order in which mappings are defined determines the order in which attributes are sent to the
|
177
177
|
# value class constructor.
|
178
178
|
# * <tt>:allow_nil</tt> - Specifies that the value object will not be instantiated when all mapped
|
179
179
|
# attributes are +nil+. Setting the value object to +nil+ has the effect of writing +nil+ to all
|
@@ -191,7 +191,8 @@ module ActiveRecord
|
|
191
191
|
#
|
192
192
|
# Option examples:
|
193
193
|
# composed_of :temperature, :mapping => %w(reading celsius)
|
194
|
-
# composed_of :balance, :class_name => "Money", :mapping => %w(balance amount),
|
194
|
+
# composed_of :balance, :class_name => "Money", :mapping => %w(balance amount),
|
195
|
+
# :converter => Proc.new { |balance| balance.to_money }
|
195
196
|
# composed_of :address, :mapping => [ %w(address_street street), %w(address_city city) ]
|
196
197
|
# composed_of :gps_location
|
197
198
|
# composed_of :gps_location, :allow_nil => true
|
@@ -1420,18 +1420,18 @@ module ActiveRecord
|
|
1420
1420
|
# join table with a migration such as this:
|
1421
1421
|
#
|
1422
1422
|
# class CreateDevelopersProjectsJoinTable < ActiveRecord::Migration
|
1423
|
-
# def
|
1423
|
+
# def change
|
1424
1424
|
# create_table :developers_projects, :id => false do |t|
|
1425
1425
|
# t.integer :developer_id
|
1426
1426
|
# t.integer :project_id
|
1427
1427
|
# end
|
1428
1428
|
# end
|
1429
|
-
#
|
1430
|
-
# def self.down
|
1431
|
-
# drop_table :developers_projects
|
1432
|
-
# end
|
1433
1429
|
# end
|
1434
1430
|
#
|
1431
|
+
# It's also a good idea to add indexes to each of those columns to speed up the joins process.
|
1432
|
+
# However, in MySQL it is advised to add a compound index for both of the columns as MySQL only
|
1433
|
+
# uses one index per table during the lookup.
|
1434
|
+
#
|
1435
1435
|
# Adds the following methods for retrieval and query:
|
1436
1436
|
#
|
1437
1437
|
# [collection(force_reload = false)]
|
@@ -354,8 +354,12 @@ module ActiveRecord
|
|
354
354
|
if options[:counter_sql]
|
355
355
|
interpolate(options[:counter_sql])
|
356
356
|
else
|
357
|
-
# replace the SELECT clause with COUNT(
|
358
|
-
interpolate(options[:finder_sql]).sub(/SELECT\b(\/\*.*?\*\/ )?(.*)\bFROM\b/im)
|
357
|
+
# replace the SELECT clause with COUNT(SELECTS), preserving any hints within /* ... */
|
358
|
+
interpolate(options[:finder_sql]).sub(/SELECT\b(\/\*.*?\*\/ )?(.*)\bFROM\b/im) do
|
359
|
+
count_with = $2.to_s
|
360
|
+
count_with = '*' if count_with.blank? || count_with =~ /,/
|
361
|
+
"SELECT #{$1}COUNT(#{count_with}) FROM"
|
362
|
+
end
|
359
363
|
end
|
360
364
|
end
|
361
365
|
|
@@ -6,6 +6,11 @@ module ActiveRecord
|
|
6
6
|
class HasManyThroughAssociation < HasManyAssociation #:nodoc:
|
7
7
|
include ThroughAssociation
|
8
8
|
|
9
|
+
def initialize(owner, reflection)
|
10
|
+
super
|
11
|
+
@through_records = {}
|
12
|
+
end
|
13
|
+
|
9
14
|
# Returns the size of the collection by executing a SELECT COUNT(*) query if the collection hasn't been
|
10
15
|
# loaded and calling collection.size if it has. If it's more likely than not that the collection does
|
11
16
|
# have a size larger than zero, and you need to fetch that collection afterwards, it'll take one fewer
|
@@ -42,27 +47,36 @@ module ActiveRecord
|
|
42
47
|
end
|
43
48
|
end
|
44
49
|
|
45
|
-
|
50
|
+
save_through_record(record)
|
46
51
|
update_counter(1)
|
47
52
|
record
|
48
53
|
end
|
49
54
|
|
50
55
|
private
|
51
56
|
|
52
|
-
def
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
through_record = Array.wrap(through_association.target).find { |candidate|
|
57
|
-
candidate.attributes.slice(*attributes.keys) == attributes
|
58
|
-
}
|
57
|
+
def through_association
|
58
|
+
owner.association(through_reflection.name)
|
59
|
+
end
|
59
60
|
|
60
|
-
|
61
|
-
|
61
|
+
# We temporarily cache through record that has been build, because if we build a
|
62
|
+
# through record in build_record and then subsequently call insert_record, then we
|
63
|
+
# want to use the exact same object.
|
64
|
+
#
|
65
|
+
# However, after insert_record has been called, we clear the cache entry because
|
66
|
+
# we want it to be possible to have multiple instances of the same record in an
|
67
|
+
# association
|
68
|
+
def build_through_record(record)
|
69
|
+
@through_records[record.object_id] ||= begin
|
70
|
+
through_record = through_association.build(construct_join_attributes(record))
|
62
71
|
through_record.send("#{source_reflection.name}=", record)
|
72
|
+
through_record
|
63
73
|
end
|
74
|
+
end
|
64
75
|
|
65
|
-
|
76
|
+
def save_through_record(record)
|
77
|
+
build_through_record(record).save!
|
78
|
+
ensure
|
79
|
+
@through_records.delete(record.object_id)
|
66
80
|
end
|
67
81
|
|
68
82
|
def build_record(attributes, options = {})
|
@@ -73,9 +87,9 @@ module ActiveRecord
|
|
73
87
|
inverse = source_reflection.inverse_of
|
74
88
|
if inverse
|
75
89
|
if inverse.macro == :has_many
|
76
|
-
record.send(inverse.name) <<
|
90
|
+
record.send(inverse.name) << build_through_record(record)
|
77
91
|
elsif inverse.macro == :has_one
|
78
|
-
record.send("#{inverse.name}=",
|
92
|
+
record.send("#{inverse.name}=", build_through_record(record))
|
79
93
|
end
|
80
94
|
end
|
81
95
|
|
@@ -104,7 +118,7 @@ module ActiveRecord
|
|
104
118
|
def delete_records(records, method)
|
105
119
|
ensure_not_nested
|
106
120
|
|
107
|
-
through =
|
121
|
+
through = through_association
|
108
122
|
scope = through.scoped.where(construct_join_attributes(*records))
|
109
123
|
|
110
124
|
case method
|
@@ -125,15 +139,23 @@ module ActiveRecord
|
|
125
139
|
update_counter(-count)
|
126
140
|
end
|
127
141
|
|
142
|
+
def through_records_for(record)
|
143
|
+
attributes = construct_join_attributes(record)
|
144
|
+
candidates = Array.wrap(through_association.target)
|
145
|
+
candidates.find_all { |c| c.attributes.slice(*attributes.keys) == attributes }
|
146
|
+
end
|
147
|
+
|
128
148
|
def delete_through_records(through, records)
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
through.target = nil if through.target
|
149
|
+
records.each do |record|
|
150
|
+
through_records = through_records_for(record)
|
151
|
+
|
152
|
+
if through_reflection.macro == :has_many
|
153
|
+
through_records.each { |r| through.target.delete(r) }
|
154
|
+
else
|
155
|
+
through.target = nil if through_records.include?(through.target)
|
136
156
|
end
|
157
|
+
|
158
|
+
@through_records.delete(record.object_id)
|
137
159
|
end
|
138
160
|
end
|
139
161
|
|
data/lib/active_record/base.rb
CHANGED
@@ -116,8 +116,8 @@ module ActiveRecord #:nodoc:
|
|
116
116
|
# When joining tables, nested hashes or keys written in the form 'table_name.column_name'
|
117
117
|
# can be used to qualify the table name of a particular condition. For instance:
|
118
118
|
#
|
119
|
-
# Student.joins(:schools).where(:schools => { :
|
120
|
-
# Student.joins(:schools).where('schools.
|
119
|
+
# Student.joins(:schools).where(:schools => { :category => 'public' })
|
120
|
+
# Student.joins(:schools).where('schools.category' => 'public' )
|
121
121
|
#
|
122
122
|
# == Overwriting default accessors
|
123
123
|
#
|
@@ -756,7 +756,7 @@ module ActiveRecord #:nodoc:
|
|
756
756
|
# values, eg:
|
757
757
|
#
|
758
758
|
# class CreateJobLevels < ActiveRecord::Migration
|
759
|
-
# def
|
759
|
+
# def up
|
760
760
|
# create_table :job_levels do |t|
|
761
761
|
# t.integer :id
|
762
762
|
# t.string :name
|
@@ -770,7 +770,7 @@ module ActiveRecord #:nodoc:
|
|
770
770
|
# end
|
771
771
|
# end
|
772
772
|
#
|
773
|
-
# def
|
773
|
+
# def down
|
774
774
|
# drop_table :job_levels
|
775
775
|
# end
|
776
776
|
# end
|
@@ -89,6 +89,14 @@ module ActiveRecord
|
|
89
89
|
retrieve_connection
|
90
90
|
end
|
91
91
|
|
92
|
+
def connection_id
|
93
|
+
Thread.current['ActiveRecord::Base.connection_id']
|
94
|
+
end
|
95
|
+
|
96
|
+
def connection_id=(connection_id)
|
97
|
+
Thread.current['ActiveRecord::Base.connection_id'] = connection_id
|
98
|
+
end
|
99
|
+
|
92
100
|
# Returns the configuration of the associated connection as a hash:
|
93
101
|
#
|
94
102
|
# ActiveRecord::Base.connection_config
|
@@ -46,13 +46,13 @@ module ActiveRecord
|
|
46
46
|
# +change_table+ is actually of this type:
|
47
47
|
#
|
48
48
|
# class SomeMigration < ActiveRecord::Migration
|
49
|
-
# def
|
49
|
+
# def up
|
50
50
|
# create_table :foo do |t|
|
51
51
|
# puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
|
52
52
|
# end
|
53
53
|
# end
|
54
54
|
#
|
55
|
-
# def
|
55
|
+
# def down
|
56
56
|
# ...
|
57
57
|
# end
|
58
58
|
# end
|
@@ -479,4 +479,3 @@ module ActiveRecord
|
|
479
479
|
|
480
480
|
end
|
481
481
|
end
|
482
|
-
|
@@ -573,9 +573,18 @@ module ActiveRecord
|
|
573
573
|
# Returns a table's primary key and belonging sequence.
|
574
574
|
def pk_and_sequence_for(table)
|
575
575
|
keys = []
|
576
|
-
|
576
|
+
sql = <<-SQL
|
577
|
+
SELECT t.constraint_type, k.column_name
|
578
|
+
FROM information_schema.table_constraints t
|
579
|
+
JOIN information_schema.key_column_usage k
|
580
|
+
USING (constraint_name, table_schema, table_name)
|
581
|
+
WHERE t.table_schema = DATABASE()
|
582
|
+
AND t.table_name = '#{table}'
|
583
|
+
SQL
|
584
|
+
|
585
|
+
result = execute(sql, 'SCHEMA')
|
577
586
|
result.each(:symbolize_keys => true, :as => :hash) do |row|
|
578
|
-
keys << row[:
|
587
|
+
keys << row[:column_name] if row[:constraint_type] == "PRIMARY KEY"
|
579
588
|
end
|
580
589
|
keys.length == 1 ? [keys.first, nil] : nil
|
581
590
|
end
|
@@ -756,9 +756,18 @@ module ActiveRecord
|
|
756
756
|
# Returns a table's primary key and belonging sequence.
|
757
757
|
def pk_and_sequence_for(table) #:nodoc:
|
758
758
|
keys = []
|
759
|
-
|
759
|
+
sql = <<-SQL
|
760
|
+
SELECT t.constraint_type, k.column_name
|
761
|
+
FROM information_schema.table_constraints t
|
762
|
+
JOIN information_schema.key_column_usage k
|
763
|
+
USING (constraint_name, table_schema, table_name)
|
764
|
+
WHERE t.table_schema = DATABASE()
|
765
|
+
AND t.table_name = '#{table}'
|
766
|
+
SQL
|
767
|
+
|
768
|
+
result = execute(sql, 'SCHEMA')
|
760
769
|
result.each_hash do |h|
|
761
|
-
keys << h["
|
770
|
+
keys << h["column_name"] if h["constraint_type"] == "PRIMARY KEY"
|
762
771
|
end
|
763
772
|
result.free
|
764
773
|
keys.length == 1 ? [keys.first, nil] : nil
|
@@ -279,13 +279,24 @@ module ActiveRecord
|
|
279
279
|
cache.clear
|
280
280
|
end
|
281
281
|
|
282
|
+
def delete(sql_key)
|
283
|
+
dealloc cache[sql_key]
|
284
|
+
cache.delete sql_key
|
285
|
+
end
|
286
|
+
|
282
287
|
private
|
283
288
|
def cache
|
284
289
|
@cache[$$]
|
285
290
|
end
|
286
291
|
|
287
292
|
def dealloc(key)
|
288
|
-
@connection.query "DEALLOCATE #{key}"
|
293
|
+
@connection.query "DEALLOCATE #{key}" if connection_active?
|
294
|
+
end
|
295
|
+
|
296
|
+
def connection_active?
|
297
|
+
@connection.status == PGconn::CONNECTION_OK
|
298
|
+
rescue PGError
|
299
|
+
false
|
289
300
|
end
|
290
301
|
end
|
291
302
|
|
@@ -743,7 +754,6 @@ module ActiveRecord
|
|
743
754
|
|
744
755
|
# Returns an array of indexes for the given table.
|
745
756
|
def indexes(table_name, name = nil)
|
746
|
-
schemas = schema_search_path.split(/,/).map { |p| quote(p) }.join(',')
|
747
757
|
result = query(<<-SQL, name)
|
748
758
|
SELECT distinct i.relname, d.indisunique, d.indkey, t.oid
|
749
759
|
FROM pg_class t
|
@@ -752,7 +762,7 @@ module ActiveRecord
|
|
752
762
|
WHERE i.relkind = 'i'
|
753
763
|
AND d.indisprimary = 'f'
|
754
764
|
AND t.relname = '#{table_name}'
|
755
|
-
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname
|
765
|
+
AND i.relnamespace IN (SELECT oid FROM pg_namespace WHERE nspname = ANY (current_schemas(false)) )
|
756
766
|
ORDER BY i.relname
|
757
767
|
SQL
|
758
768
|
|
@@ -899,12 +909,14 @@ module ActiveRecord
|
|
899
909
|
# Example:
|
900
910
|
# rename_table('octopuses', 'octopi')
|
901
911
|
def rename_table(name, new_name)
|
912
|
+
clear_cache!
|
902
913
|
execute "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}"
|
903
914
|
end
|
904
915
|
|
905
916
|
# Adds a new column to the named table.
|
906
917
|
# See TableDefinition#column for details of the options you can use.
|
907
918
|
def add_column(table_name, column_name, type, options = {})
|
919
|
+
clear_cache!
|
908
920
|
add_column_sql = "ALTER TABLE #{quote_table_name(table_name)} ADD COLUMN #{quote_column_name(column_name)} #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
|
909
921
|
add_column_options!(add_column_sql, options)
|
910
922
|
|
@@ -913,6 +925,7 @@ module ActiveRecord
|
|
913
925
|
|
914
926
|
# Changes the column of a table.
|
915
927
|
def change_column(table_name, column_name, type, options = {})
|
928
|
+
clear_cache!
|
916
929
|
quoted_table_name = quote_table_name(table_name)
|
917
930
|
|
918
931
|
execute "ALTER TABLE #{quoted_table_name} ALTER COLUMN #{quote_column_name(column_name)} TYPE #{type_to_sql(type, options[:limit], options[:precision], options[:scale])}"
|
@@ -923,10 +936,12 @@ module ActiveRecord
|
|
923
936
|
|
924
937
|
# Changes the default value of a table column.
|
925
938
|
def change_column_default(table_name, column_name, default)
|
939
|
+
clear_cache!
|
926
940
|
execute "ALTER TABLE #{quote_table_name(table_name)} ALTER COLUMN #{quote_column_name(column_name)} SET DEFAULT #{quote(default)}"
|
927
941
|
end
|
928
942
|
|
929
943
|
def change_column_null(table_name, column_name, null, default = nil)
|
944
|
+
clear_cache!
|
930
945
|
unless null || default.nil?
|
931
946
|
execute("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL")
|
932
947
|
end
|
@@ -935,6 +950,7 @@ module ActiveRecord
|
|
935
950
|
|
936
951
|
# Renames a column in a table.
|
937
952
|
def rename_column(table_name, column_name, new_column_name)
|
953
|
+
clear_cache!
|
938
954
|
execute "ALTER TABLE #{quote_table_name(table_name)} RENAME COLUMN #{quote_column_name(column_name)} TO #{quote_column_name(new_column_name)}"
|
939
955
|
end
|
940
956
|
|
@@ -999,27 +1015,55 @@ module ActiveRecord
|
|
999
1015
|
end
|
1000
1016
|
|
1001
1017
|
private
|
1002
|
-
|
1003
|
-
@connection.async_exec(sql)
|
1004
|
-
end
|
1018
|
+
FEATURE_NOT_SUPPORTED = "0A000" # :nodoc:
|
1005
1019
|
|
1006
|
-
|
1007
|
-
|
1008
|
-
|
1009
|
-
|
1010
|
-
|
1020
|
+
def exec_no_cache(sql, binds)
|
1021
|
+
@connection.async_exec(sql)
|
1022
|
+
end
|
1023
|
+
|
1024
|
+
def exec_cache(sql, binds)
|
1025
|
+
begin
|
1026
|
+
stmt_key = prepare_statement sql
|
1027
|
+
|
1028
|
+
# Clear the queue
|
1029
|
+
@connection.get_last_result
|
1030
|
+
@connection.send_query_prepared(stmt_key, binds.map { |col, val|
|
1031
|
+
type_cast(val, col)
|
1032
|
+
})
|
1033
|
+
@connection.block
|
1034
|
+
@connection.get_last_result
|
1035
|
+
rescue PGError => e
|
1036
|
+
# Get the PG code for the failure. Annoyingly, the code for
|
1037
|
+
# prepared statements whose return value may have changed is
|
1038
|
+
# FEATURE_NOT_SUPPORTED. Check here for more details:
|
1039
|
+
# http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573
|
1040
|
+
code = e.result.result_error_field(PGresult::PG_DIAG_SQLSTATE)
|
1041
|
+
if FEATURE_NOT_SUPPORTED == code
|
1042
|
+
@statements.delete sql_key(sql)
|
1043
|
+
retry
|
1044
|
+
else
|
1045
|
+
raise e
|
1046
|
+
end
|
1047
|
+
end
|
1011
1048
|
end
|
1012
1049
|
|
1013
|
-
|
1050
|
+
# Returns the statement identifier for the client side cache
|
1051
|
+
# of statements
|
1052
|
+
def sql_key(sql)
|
1053
|
+
"#{schema_search_path}-#{sql}"
|
1054
|
+
end
|
1014
1055
|
|
1015
|
-
#
|
1016
|
-
|
1017
|
-
|
1018
|
-
|
1019
|
-
|
1020
|
-
|
1021
|
-
|
1022
|
-
|
1056
|
+
# Prepare the statement if it hasn't been prepared, return
|
1057
|
+
# the statement key.
|
1058
|
+
def prepare_statement(sql)
|
1059
|
+
sql_key = sql_key(sql)
|
1060
|
+
unless @statements.key? sql_key
|
1061
|
+
nextkey = @statements.next_key
|
1062
|
+
@connection.prepare nextkey, sql
|
1063
|
+
@statements[sql_key] = nextkey
|
1064
|
+
end
|
1065
|
+
@statements[sql_key]
|
1066
|
+
end
|
1023
1067
|
|
1024
1068
|
# The internal PostgreSQL identifier of the money data type.
|
1025
1069
|
MONEY_COLUMN_TYPE_OID = 790 #:nodoc:
|