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