Changesets can be listed by changeset number.
The Git repository is here.
- Revision:
- 373
- Log:
Initial import of Radiant 0.9.1, which is now packaged as a gem. This is an
import of the tagged 0.9.1 source checked out from GitHub, which isn't quite
the same as the gem distribution - but it doesn't seem to be available in an
archived form and the installed gem already has modifications, so this is
the closest I can get.
- Author:
- rool
- Date:
- Mon Mar 21 13:40:05 +0000 2011
- Size:
- 10672 Bytes
1 | module ActiveRecord |
2 | module ConnectionAdapters # :nodoc: |
3 | module DatabaseStatements |
4 | # Returns an array of record hashes with the column names as keys and |
5 | # column values as values. |
6 | def select_all(sql, name = nil) |
7 | select(sql, name) |
8 | end |
9 | |
10 | # Returns a record hash with the column names as keys and column values |
11 | # as values. |
12 | def select_one(sql, name = nil) |
13 | result = select_all(sql, name) |
14 | result.first if result |
15 | end |
16 | |
17 | # Returns a single value from a record |
18 | def select_value(sql, name = nil) |
19 | if result = select_one(sql, name) |
20 | result.values.first |
21 | end |
22 | end |
23 | |
24 | # Returns an array of the values of the first column in a select: |
25 | # select_values("SELECT id FROM companies LIMIT 3") => [1,2,3] |
26 | def select_values(sql, name = nil) |
27 | result = select_rows(sql, name) |
28 | result.map { |v| v[0] } |
29 | end |
30 | |
31 | # Returns an array of arrays containing the field values. |
32 | # Order is the same as that returned by +columns+. |
33 | def select_rows(sql, name = nil) |
34 | end |
35 | undef_method :select_rows |
36 | |
37 | # Executes the SQL statement in the context of this connection. |
38 | def execute(sql, name = nil, skip_logging = false) |
39 | end |
40 | undef_method :execute |
41 | |
42 | # Returns the last auto-generated ID from the affected table. |
43 | def insert(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) |
44 | insert_sql(sql, name, pk, id_value, sequence_name) |
45 | end |
46 | |
47 | # Executes the update statement and returns the number of rows affected. |
48 | def update(sql, name = nil) |
49 | update_sql(sql, name) |
50 | end |
51 | |
52 | # Executes the delete statement and returns the number of rows affected. |
53 | def delete(sql, name = nil) |
54 | delete_sql(sql, name) |
55 | end |
56 | |
57 | # Checks whether there is currently no transaction active. This is done |
58 | # by querying the database driver, and does not use the transaction |
59 | # house-keeping information recorded by #increment_open_transactions and |
60 | # friends. |
61 | # |
62 | # Returns true if there is no transaction active, false if there is a |
63 | # transaction active, and nil if this information is unknown. |
64 | # |
65 | # Not all adapters supports transaction state introspection. Currently, |
66 | # only the PostgreSQL adapter supports this. |
67 | def outside_transaction? |
68 | nil |
69 | end |
70 | |
71 | # Runs the given block in a database transaction, and returns the result |
72 | # of the block. |
73 | # |
74 | # == Nested transactions support |
75 | # |
76 | # Most databases don't support true nested transactions. At the time of |
77 | # writing, the only database that supports true nested transactions that |
78 | # we're aware of, is MS-SQL. |
79 | # |
80 | # In order to get around this problem, #transaction will emulate the effect |
81 | # of nested transactions, by using savepoints: |
82 | # http://dev.mysql.com/doc/refman/5.0/en/savepoints.html |
83 | # Savepoints are supported by MySQL and PostgreSQL, but not SQLite3. |
84 | # |
85 | # It is safe to call this method if a database transaction is already open, |
86 | # i.e. if #transaction is called within another #transaction block. In case |
87 | # of a nested call, #transaction will behave as follows: |
88 | # |
89 | # - The block will be run without doing anything. All database statements |
90 | # that happen within the block are effectively appended to the already |
91 | # open database transaction. |
92 | # - However, if +:requires_new+ is set, the block will be wrapped in a |
93 | # database savepoint acting as a sub-transaction. |
94 | # |
95 | # === Caveats |
96 | # |
97 | # MySQL doesn't support DDL transactions. If you perform a DDL operation, |
98 | # then any created savepoints will be automatically released. For example, |
99 | # if you've created a savepoint, then you execute a CREATE TABLE statement, |
100 | # then the savepoint that was created will be automatically released. |
101 | # |
102 | # This means that, on MySQL, you shouldn't execute DDL operations inside |
103 | # a #transaction call that you know might create a savepoint. Otherwise, |
104 | # #transaction will raise exceptions when it tries to release the |
105 | # already-automatically-released savepoints: |
106 | # |
107 | # Model.connection.transaction do # BEGIN |
108 | # Model.connection.transaction(:requires_new => true) do # CREATE SAVEPOINT active_record_1 |
109 | # Model.connection.create_table(...) |
110 | # # active_record_1 now automatically released |
111 | # end # RELEASE SAVEPOINT active_record_1 <--- BOOM! database error! |
112 | # end |
113 | def transaction(options = {}) |
114 | options.assert_valid_keys :requires_new, :joinable |
115 | |
116 | last_transaction_joinable = @transaction_joinable |
117 | if options.has_key?(:joinable) |
118 | @transaction_joinable = options[:joinable] |
119 | else |
120 | @transaction_joinable = true |
121 | end |
122 | requires_new = options[:requires_new] || !last_transaction_joinable |
123 | |
124 | transaction_open = false |
125 | begin |
126 | if block_given? |
127 | if requires_new || open_transactions == 0 |
128 | if open_transactions == 0 |
129 | begin_db_transaction |
130 | elsif requires_new |
131 | create_savepoint |
132 | end |
133 | increment_open_transactions |
134 | transaction_open = true |
135 | end |
136 | yield |
137 | end |
138 | rescue Exception => database_transaction_rollback |
139 | if transaction_open && !outside_transaction? |
140 | transaction_open = false |
141 | decrement_open_transactions |
142 | if open_transactions == 0 |
143 | rollback_db_transaction |
144 | else |
145 | rollback_to_savepoint |
146 | end |
147 | end |
148 | raise unless database_transaction_rollback.is_a?(ActiveRecord::Rollback) |
149 | end |
150 | ensure |
151 | @transaction_joinable = last_transaction_joinable |
152 | |
153 | if outside_transaction? |
154 | @open_transactions = 0 |
155 | elsif transaction_open |
156 | decrement_open_transactions |
157 | begin |
158 | if open_transactions == 0 |
159 | commit_db_transaction |
160 | else |
161 | release_savepoint |
162 | end |
163 | rescue Exception => database_transaction_rollback |
164 | if open_transactions == 0 |
165 | rollback_db_transaction |
166 | else |
167 | rollback_to_savepoint |
168 | end |
169 | raise |
170 | end |
171 | end |
172 | end |
173 | |
174 | # Begins the transaction (and turns off auto-committing). |
175 | def begin_db_transaction() end |
176 | |
177 | # Commits the transaction (and turns on auto-committing). |
178 | def commit_db_transaction() end |
179 | |
180 | # Rolls back the transaction (and turns on auto-committing). Must be |
181 | # done if the transaction block raises an exception or returns false. |
182 | def rollback_db_transaction() end |
183 | |
184 | # Alias for <tt>add_limit_offset!</tt>. |
185 | def add_limit!(sql, options) |
186 | add_limit_offset!(sql, options) if options |
187 | end |
188 | |
189 | # Appends +LIMIT+ and +OFFSET+ options to an SQL statement, or some SQL |
190 | # fragment that has the same semantics as LIMIT and OFFSET. |
191 | # |
192 | # +options+ must be a Hash which contains a +:limit+ option (required) |
193 | # and an +:offset+ option (optional). |
194 | # |
195 | # This method *modifies* the +sql+ parameter. |
196 | # |
197 | # ===== Examples |
198 | # add_limit_offset!('SELECT * FROM suppliers', {:limit => 10, :offset => 50}) |
199 | # generates |
200 | # SELECT * FROM suppliers LIMIT 10 OFFSET 50 |
201 | def add_limit_offset!(sql, options) |
202 | if limit = options[:limit] |
203 | sql << " LIMIT #{sanitize_limit(limit)}" |
204 | if offset = options[:offset] |
205 | sql << " OFFSET #{offset.to_i}" |
206 | end |
207 | end |
208 | sql |
209 | end |
210 | |
211 | # Appends a locking clause to an SQL statement. |
212 | # This method *modifies* the +sql+ parameter. |
213 | # # SELECT * FROM suppliers FOR UPDATE |
214 | # add_lock! 'SELECT * FROM suppliers', :lock => true |
215 | # add_lock! 'SELECT * FROM suppliers', :lock => ' FOR UPDATE' |
216 | def add_lock!(sql, options) |
217 | case lock = options[:lock] |
218 | when true; sql << ' FOR UPDATE' |
219 | when String; sql << " #{lock}" |
220 | end |
221 | end |
222 | |
223 | def default_sequence_name(table, column) |
224 | nil |
225 | end |
226 | |
227 | # Set the sequence to the max value of the table's column. |
228 | def reset_sequence!(table, column, sequence = nil) |
229 | # Do nothing by default. Implement for PostgreSQL, Oracle, ... |
230 | end |
231 | |
232 | # Inserts the given fixture into the table. Overridden in adapters that require |
233 | # something beyond a simple insert (eg. Oracle). |
234 | def insert_fixture(fixture, table_name) |
235 | execute "INSERT INTO #{quote_table_name(table_name)} (#{fixture.key_list}) VALUES (#{fixture.value_list})", 'Fixture Insert' |
236 | end |
237 | |
238 | def empty_insert_statement(table_name) |
239 | "INSERT INTO #{quote_table_name(table_name)} VALUES(DEFAULT)" |
240 | end |
241 | |
242 | def case_sensitive_equality_operator |
243 | "=" |
244 | end |
245 | |
246 | def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key) |
247 | "WHERE #{quoted_primary_key} IN (SELECT #{quoted_primary_key} FROM #{quoted_table_name} #{where_sql})" |
248 | end |
249 | |
250 | protected |
251 | # Returns an array of record hashes with the column names as keys and |
252 | # column values as values. |
253 | def select(sql, name = nil) |
254 | end |
255 | undef_method :select |
256 | |
257 | # Returns the last auto-generated ID from the affected table. |
258 | def insert_sql(sql, name = nil, pk = nil, id_value = nil, sequence_name = nil) |
259 | execute(sql, name) |
260 | id_value |
261 | end |
262 | |
263 | # Executes the update statement and returns the number of rows affected. |
264 | def update_sql(sql, name = nil) |
265 | execute(sql, name) |
266 | end |
267 | |
268 | # Executes the delete statement and returns the number of rows affected. |
269 | def delete_sql(sql, name = nil) |
270 | update_sql(sql, name) |
271 | end |
272 | |
273 | # Sanitizes the given LIMIT parameter in order to prevent SQL injection. |
274 | # |
275 | # +limit+ may be anything that can evaluate to a string via #to_s. It |
276 | # should look like an integer, or a comma-delimited list of integers. |
277 | # |
278 | # Returns the sanitized limit parameter, either as an integer, or as a |
279 | # string which contains a comma-delimited list of integers. |
280 | def sanitize_limit(limit) |
281 | if limit.to_s =~ /,/ |
282 | limit.to_s.split(',').map{ |i| i.to_i }.join(',') |
283 | else |
284 | limit.to_i |
285 | end |
286 | end |
287 | end |
288 | end |
289 | end |