1: <?php
2:
3: 4: 5: 6: 7: 8: 9: 10: 11:
12:
13:
14:
15: 16: 17: 18: 19: 20:
21: class SqliteDriver extends Object implements ISupplementalDriver
22: {
23:
24: private $connection;
25:
26:
27: private $fmtDateTime;
28:
29:
30: public function __construct(Connection $connection, array $options)
31: {
32: $this->connection = $connection;
33: $this->fmtDateTime = isset($options['formatDateTime']) ? $options['formatDateTime'] : 'U';
34:
35: }
36:
37:
38:
39:
40:
41: 42: 43:
44: public function delimite($name)
45: {
46: return '[' . strtr($name, '[]', ' ') . ']';
47: }
48:
49:
50: 51: 52:
53: public function formatBool($value)
54: {
55: return $value ? '1' : '0';
56: }
57:
58:
59: 60: 61:
62: public function formatDateTime(DateTime $value)
63: {
64: return $value->format($this->fmtDateTime);
65: }
66:
67:
68: 69: 70:
71: public function formatLike($value, $pos)
72: {
73: $value = addcslashes(substr($this->connection->quote($value), 1, -1), '%_\\');
74: return ($pos <= 0 ? "'%" : "'") . $value . ($pos >= 0 ? "%'" : "'") . " ESCAPE '\\'";
75: }
76:
77:
78: 79: 80:
81: public function applyLimit(& $sql, $limit, $offset)
82: {
83: if ($limit >= 0 || $offset > 0) {
84: $sql .= ' LIMIT ' . $limit . ($offset > 0 ? ' OFFSET ' . (int) $offset : '');
85: }
86: }
87:
88:
89: 90: 91:
92: public function normalizeRow($row, $statement)
93: {
94: foreach ($row as $key => $value) {
95: unset($row[$key]);
96: if ($key[0] === '[' || $key[0] === '"') {
97: $key = substr($key, 1, -1);
98: }
99: $row[$key] = $value;
100: }
101: return $row;
102: }
103:
104:
105:
106:
107:
108: 109: 110:
111: public function getTables()
112: {
113: return $this->connection->query("
114: SELECT name, type = 'view' as view FROM sqlite_master WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%'
115: UNION ALL
116: SELECT name, type = 'view' as view FROM sqlite_temp_master WHERE type IN ('table', 'view') AND name NOT LIKE 'sqlite_%'
117: ORDER BY name
118: ")->fetchAll();
119: }
120:
121:
122: 123: 124:
125: public function getColumns($table)
126: {
127: $meta = $this->connection->query("
128: SELECT sql FROM sqlite_master WHERE type = 'table' AND name = {$this->connection->quote($table)}
129: UNION ALL
130: SELECT sql FROM sqlite_temp_master WHERE type = 'table' AND name = {$this->connection->quote($table)}
131: ")->fetch();
132:
133: $columns = array();
134: foreach ($this->connection->query("PRAGMA table_info({$this->delimite($table)})") as $row) {
135: $column = $row['name'];
136: $pattern = "/(\"$column\"|\[$column\]|$column)\\s+[^,]+\\s+PRIMARY\\s+KEY\\s+AUTOINCREMENT/Ui";
137: $type = explode('(', $row['type']);
138: $columns[] = array(
139: 'name' => $column,
140: 'table' => $table,
141: 'fullname' => "$table.$column",
142: 'nativetype' => strtoupper($type[0]),
143: 'size' => isset($type[1]) ? (int) $type[1] : NULL,
144: 'nullable' => $row['notnull'] == '0',
145: 'default' => $row['dflt_value'],
146: 'autoincrement' => (bool) preg_match($pattern, $meta['sql']),
147: 'primary' => $row['pk'] == '1',
148: 'vendor' => (array) $row,
149: );
150: }
151: return $columns;
152: }
153:
154:
155: 156: 157:
158: public function getIndexes($table)
159: {
160: $indexes = array();
161: foreach ($this->connection->query("PRAGMA index_list({$this->delimite($table)})") as $row) {
162: $indexes[$row['name']]['name'] = $row['name'];
163: $indexes[$row['name']]['unique'] = (bool) $row['unique'];
164: }
165:
166: foreach ($indexes as $index => $values) {
167: $res = $this->connection->query("PRAGMA index_info({$this->delimite($index)})");
168: while ($row = $res->fetch(TRUE)) {
169: $indexes[$index]['columns'][$row['seqno']] = $row['name'];
170: }
171: }
172:
173: $columns = $this->getColumns($table);
174: foreach ($indexes as $index => $values) {
175: $column = $indexes[$index]['columns'][0];
176: $primary = FALSE;
177: foreach ($columns as $info) {
178: if ($column == $info['name']) {
179: $primary = $info['primary'];
180: break;
181: }
182: }
183: $indexes[$index]['primary'] = (bool) $primary;
184: }
185: if (!$indexes) {
186: foreach ($columns as $column) {
187: if ($column['vendor']['pk']) {
188: $indexes[] = array(
189: 'name' => 'ROWID',
190: 'unique' => TRUE,
191: 'primary' => TRUE,
192: 'columns' => array($column['name']),
193: );
194: break;
195: }
196: }
197: }
198:
199: return array_values($indexes);
200: }
201:
202:
203: 204: 205:
206: public function getForeignKeys($table)
207: {
208: $keys = array();
209: foreach ($this->connection->query("PRAGMA foreign_key_list({$this->delimite($table)})") as $row) {
210: $keys[$row['id']]['name'] = $row['id'];
211: $keys[$row['id']]['local'] = $row['from'];
212: $keys[$row['id']]['table'] = $row['table'];
213: $keys[$row['id']]['foreign'] = $row['to'];
214: $keys[$row['id']]['onDelete'] = $row['on_delete'];
215: $keys[$row['id']]['onUpdate'] = $row['on_update'];
216:
217: if ($keys[$row['id']]['foreign'][0] == NULL) {
218: $keys[$row['id']]['foreign'] = NULL;
219: }
220: }
221: return array_values($keys);
222: }
223:
224:
225: 226: 227:
228: public function isSupported($item)
229: {
230: return FALSE;
231: }
232:
233: }
234: