/[drupal]/contributions/modules/transaction/transaction.module
ViewVC logotype

Contents of /contributions/modules/transaction/transaction.module

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.2 - (show annotations) (download) (as text)
Mon Mar 9 18:38:29 2009 UTC (8 months, 2 weeks ago) by straussd
Branch: MAIN
CVS Tags: DRUPAL-6--0-1, HEAD
Changes since 1.1: +14 -90 lines
File MIME type: text/x-php
Port to D6.
1 <?php
2 // $Id$
3 /**
4 * @file Provides a database transaction system for use with InnoDB tables
5 * in MySQL.
6 */
7
8 /**
9 * Provides a nestable transaction system for handling commits and rollbacks.
10 *
11 * Although transactions can be nested, a rollback or commit from a nested
12 * transaction will cause it to propagate upwards.
13 */
14 class Transaction {
15 /** The number of transactions that have been nested within this one. */
16 private static $Layers = 0;
17
18 /** Will the commit be allowed? */
19 private static $AllowCommit = TRUE;
20
21 /**
22 * Create a new transaction.
23 */
24 public function __construct()
25 {
26 if (self::$Layers == 0)
27 db_query('BEGIN');
28 self::$Layers++;
29 }
30
31 /**
32 * Complete the transaction by either performing a commit or a rollback
33 * depending on the state of the object's allow_commit property.
34 */
35 public function __destruct()
36 {
37 self::$Layers--;
38 if (self::$Layers == 0) {
39 if (self::$AllowCommit) {
40 db_query('COMMIT');
41 } else {
42 db_query('ROLLBACK');
43 }
44
45 // Reset the ROLLBACK propagator
46 self::$AllowCommit = TRUE;
47 }
48 }
49
50 /**
51 * If the given value is FALSE (value AND type), roll back the current
52 * transaction.
53 *
54 * @param boolean $var Roll back the current transaction iff TRUE.
55 */
56 public static function rollbackIfFalse($var)
57 {
58 if ($var === FALSE) {
59 self::rollback();
60 }
61 }
62
63 /**
64 * Force this transaction to roll back when finished.
65 */
66 public static function rollback()
67 {
68 self::$AllowCommit = FALSE;
69 }
70
71 /**
72 * Will this transaction roll back instead of committing?
73 *
74 * @return boolean TRUE if the transaction will roll back, FALSE if it
75 * will commit.
76 */
77 public static function willRollback()
78 {
79 return !self::$AllowCommit;
80 }
81 }
82
83 /**
84 * Utility function that abstracts transactionalized updates or inserts
85 * on a single row.
86 *
87 * @param string $table (required) The un-prefixed table name without curly
88 * braces.
89 * @param mixed $key_field (required) The name(s) of the column(s) to use when
90 * identifying the row to update. If only a single column is being used
91 * to select the row, this may be a string. If more than one column
92 * is being used, this must be an array of strings.
93 * If this operation is an update, these columns must be present as keys
94 * in $fields with their desired WHERE = values.
95 * @param array $fields An associative array mapping column names (keys) to
96 * the values to be inserted/updated. For updates, only the columns
97 * with updated values need to be in this array.
98 *
99 * @return mixed
100 */
101 function transaction_update($table, $key_field, $fields) {
102 $txn = new Transaction();
103
104 // Accept a string if the key field is one column
105 $return_simple_key_field = FALSE;
106 if (!is_array($key_field)) {
107 $return_simple_key_field = TRUE;
108 $key_field = array($key_field);
109 }
110
111 // Convert a passed object to an array
112 $fields = (array) $fields;
113
114 // Check if key columns are specified
115 $key_field_set = TRUE;
116 foreach ($key_field as $column) {
117 if (!array_key_exists($column, $fields)) {
118 $key_field_set = FALSE;
119 }
120 }
121
122 // Update
123 if ($key_field_set) {
124 $sql = 'UPDATE {' . db_escape_table($table) . '} t SET ';
125 $where = '';
126 $updates = array();
127 foreach ($fields as $key => $value) {
128 if (!in_array($key, $key_field)) {
129 if ($value !== NULL) {
130 $updates[] = 't.' . $key . ' = "' . db_escape_string($value) . '"';
131 }
132 else {
133 $updates[] = 't.' . $key . ' = NULL';
134 }
135 }
136 }
137 $sql .= implode(',', $updates) . ' ';
138 $where .= ' WHERE 1 ';
139
140 foreach ($key_field as $column) {
141 if ($fields[$column] !== NULL) {
142 $where .= 'AND ' . $column . ' = "' . $fields[$column] . '" ';
143 }
144 else {
145 $where .= 'AND ' . $column . ' IS NULL ';
146 }
147 }
148
149 $sql .= $where;
150
151 db_query($sql);
152
153 // Return if we've actually updated something
154 if (db_affected_rows()) {
155 // If we were passed a simple key, return the same
156 if ($return_simple_key_field) {
157 return $fields[$key_field[0]];
158 }
159
160 $return_fields = array();
161 foreach ($key_field as $column) {
162 $return_fields[$column] = $fields[$column];
163 }
164 return $return_fields;
165 }
166
167 // Return if there was nothing to change, but the row actually exists
168 $sql = 'SELECT COUNT(*) FROM {' . db_escape_table($table) . '} ' . $where;
169 $exists = db_result(db_query($sql, 0, 1));
170 if ($exists) {
171 $return_fields = array();
172 foreach ($key_field as $column) {
173 $return_fields[$column] = $fields[$column];
174 }
175 return $return_fields;
176 }
177 }
178 else {
179 // We can't autogenerate if the key is more than one column
180 if (count($key_field) > 1) {
181 return FALSE;
182 }
183 }
184
185 // Insert
186 $sql = 'INSERT INTO {' . db_escape_table($table) . '} ';
187 $keys = array_keys($fields);
188 $values = array();
189 foreach ($fields as $key => $value) {
190 if ($value !== NULL) {
191 $values[] = '"' . db_escape_string($value) . '"';
192 }
193 else {
194 $values[] = 'NULL';
195 }
196 }
197 $sql .= '({' . db_escape_table($table) . '}.' . implode(',{' . db_escape_table($table) . '}.', $keys) . ') ';
198 $sql .= 'VALUES (' . implode(',', $values) . ')';
199 db_query($sql);
200
201 if (!$key_field_set) {
202 $fields[$key_field[0]] = db_last_insert_id($table, $key_field[0]);
203 }
204
205 // If we were passed a scalar key, return the key of the new row as a scalar
206 if ($return_simple_key_field) {
207 return $fields[$key_field[0]];
208 }
209
210 $return_fields = array();
211 foreach ($key_field as $column) {
212 $return_fields[$column] = $fields[$column];
213 }
214 return $return_fields;
215 }

  ViewVC Help
Powered by ViewVC 1.1.2