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