|
1 <?php |
|
2 |
|
3 /** |
|
4 * @file |
|
5 * Query code for SQLite embedded database engine. |
|
6 */ |
|
7 |
|
8 /** |
|
9 * @addtogroup database |
|
10 * @{ |
|
11 */ |
|
12 |
|
13 /** |
|
14 * SQLite specific implementation of InsertQuery. |
|
15 * |
|
16 * We ignore all the default fields and use the clever SQLite syntax: |
|
17 * INSERT INTO table DEFAULT VALUES |
|
18 * for degenerated "default only" queries. |
|
19 */ |
|
20 class InsertQuery_sqlite extends InsertQuery { |
|
21 |
|
22 public function execute() { |
|
23 if (!$this->preExecute()) { |
|
24 return NULL; |
|
25 } |
|
26 if (count($this->insertFields)) { |
|
27 return parent::execute(); |
|
28 } |
|
29 else { |
|
30 return $this->connection->query('INSERT INTO {' . $this->table . '} DEFAULT VALUES', array(), $this->queryOptions); |
|
31 } |
|
32 } |
|
33 |
|
34 public function __toString() { |
|
35 // Create a sanitized comment string to prepend to the query. |
|
36 $comments = $this->connection->makeComment($this->comments); |
|
37 |
|
38 // Produce as many generic placeholders as necessary. |
|
39 $placeholders = array_fill(0, count($this->insertFields), '?'); |
|
40 |
|
41 // If we're selecting from a SelectQuery, finish building the query and |
|
42 // pass it back, as any remaining options are irrelevant. |
|
43 if (!empty($this->fromQuery)) { |
|
44 $insert_fields_string = $this->insertFields ? ' (' . implode(', ', $this->insertFields) . ') ' : ' '; |
|
45 return $comments . 'INSERT INTO {' . $this->table . '}' . $insert_fields_string . $this->fromQuery; |
|
46 } |
|
47 |
|
48 return $comments . 'INSERT INTO {' . $this->table . '} (' . implode(', ', $this->insertFields) . ') VALUES (' . implode(', ', $placeholders) . ')'; |
|
49 } |
|
50 |
|
51 } |
|
52 |
|
53 /** |
|
54 * SQLite specific implementation of UpdateQuery. |
|
55 * |
|
56 * SQLite counts all the rows that match the conditions as modified, even if they |
|
57 * will not be affected by the query. We workaround this by ensuring that |
|
58 * we don't select those rows. |
|
59 * |
|
60 * A query like this one: |
|
61 * UPDATE test SET col1 = 'newcol1', col2 = 'newcol2' WHERE tid = 1 |
|
62 * will become: |
|
63 * UPDATE test SET col1 = 'newcol1', col2 = 'newcol2' WHERE tid = 1 AND (col1 <> 'newcol1' OR col2 <> 'newcol2') |
|
64 */ |
|
65 class UpdateQuery_sqlite extends UpdateQuery { |
|
66 public function execute() { |
|
67 if (!empty($this->queryOptions['sqlite_return_matched_rows'])) { |
|
68 return parent::execute(); |
|
69 } |
|
70 |
|
71 // Get the fields used in the update query. |
|
72 $fields = $this->expressionFields + $this->fields; |
|
73 |
|
74 // Add the inverse of the fields to the condition. |
|
75 $condition = new DatabaseCondition('OR'); |
|
76 foreach ($fields as $field => $data) { |
|
77 if (is_array($data)) { |
|
78 // The field is an expression. |
|
79 $condition->where($field . ' <> ' . $data['expression']); |
|
80 $condition->isNull($field); |
|
81 } |
|
82 elseif (!isset($data)) { |
|
83 // The field will be set to NULL. |
|
84 $condition->isNotNull($field); |
|
85 } |
|
86 else { |
|
87 $condition->condition($field, $data, '<>'); |
|
88 $condition->isNull($field); |
|
89 } |
|
90 } |
|
91 if (count($condition)) { |
|
92 $condition->compile($this->connection, $this); |
|
93 $this->condition->where((string) $condition, $condition->arguments()); |
|
94 } |
|
95 return parent::execute(); |
|
96 } |
|
97 |
|
98 } |
|
99 |
|
100 /** |
|
101 * SQLite specific implementation of DeleteQuery. |
|
102 */ |
|
103 class DeleteQuery_sqlite extends DeleteQuery { |
|
104 public function execute() { |
|
105 // When the WHERE is omitted from a DELETE statement and the table being |
|
106 // deleted has no triggers, SQLite uses an optimization to erase the entire |
|
107 // table content without having to visit each row of the table individually. |
|
108 // Prior to SQLite 3.6.5, SQLite does not return the actual number of rows |
|
109 // deleted by that optimized "truncate" optimization. But we want to return |
|
110 // the number of rows affected, so we calculate it directly. |
|
111 if (!count($this->condition)) { |
|
112 $total_rows = $this->connection->query('SELECT COUNT(*) FROM {' . $this->connection->escapeTable($this->table) . '}')->fetchField(); |
|
113 parent::execute(); |
|
114 return $total_rows; |
|
115 } |
|
116 else { |
|
117 return parent::execute(); |
|
118 } |
|
119 } |
|
120 } |
|
121 |
|
122 /** |
|
123 * SQLite specific implementation of TruncateQuery. |
|
124 * |
|
125 * SQLite doesn't support TRUNCATE, but a DELETE query with no condition has |
|
126 * exactly the effect (it is implemented by DROPing the table). |
|
127 */ |
|
128 class TruncateQuery_sqlite extends TruncateQuery { |
|
129 public function __toString() { |
|
130 // Create a sanitized comment string to prepend to the query. |
|
131 $comments = $this->connection->makeComment($this->comments); |
|
132 |
|
133 return $comments . 'DELETE FROM {' . $this->connection->escapeTable($this->table) . '} '; |
|
134 } |
|
135 } |
|
136 |
|
137 /** |
|
138 * @} End of "addtogroup database". |
|
139 */ |