00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 class DboSqlite extends DboSource {
00039
00040
00041
00042
00043
00044
00045 var $description = "SQLite DBO Driver";
00046
00047
00048
00049
00050
00051 var $startQuote = '"';
00052
00053
00054
00055
00056
00057 var $endQuote = '"';
00058
00059
00060
00061
00062
00063
00064 var $_queryStats = array();
00065
00066
00067
00068
00069
00070 var $_baseConfig = array(
00071 'persistent' => true,
00072 'database' => null,
00073 'connect' => 'sqlite_popen'
00074 );
00075
00076
00077
00078
00079
00080
00081 var $_commands = array(
00082 'begin' => 'BEGIN TRANSACTION',
00083 'commit' => 'COMMIT TRANSACTION',
00084 'rollback' => 'ROLLBACK TRANSACTION'
00085 );
00086
00087
00088
00089
00090
00091 var $columns = array(
00092 'primary_key' => array('name' => 'integer primary key'),
00093 'string' => array('name' => 'varchar', 'limit' => '255'),
00094 'text' => array('name' => 'text'),
00095 'integer' => array('name' => 'integer', 'limit' => null, 'formatter' => 'intval'),
00096 'float' => array('name' => 'float', 'formatter' => 'floatval'),
00097 'datetime' => array('name' => 'datetime', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
00098 'timestamp' => array('name' => 'timestamp', 'format' => 'Y-m-d H:i:s', 'formatter' => 'date'),
00099 'time' => array('name' => 'time', 'format' => 'H:i:s', 'formatter' => 'date'),
00100 'date' => array('name' => 'date', 'format' => 'Y-m-d', 'formatter' => 'date'),
00101 'binary' => array('name' => 'blob'),
00102 'boolean' => array('name' => 'boolean')
00103 );
00104
00105
00106
00107
00108
00109
00110 function connect() {
00111 $config = $this->config;
00112 $this->connection = $config['connect']($config['database']);
00113 $this->connected = is_resource($this->connection);
00114
00115 if ($this->connected) {
00116 $this->_execute('PRAGMA count_changes = 1;');
00117 }
00118 return $this->connected;
00119 }
00120
00121
00122
00123
00124
00125 function disconnect() {
00126 @sqlite_close($this->connection);
00127 $this->connected = false;
00128 return $this->connected;
00129 }
00130
00131
00132
00133
00134
00135
00136 function _execute($sql) {
00137 $result = sqlite_query($this->connection, $sql);
00138
00139 if (preg_match('/^(INSERT|UPDATE|DELETE)/', $sql)) {
00140 $this->resultSet($result);
00141 list($this->_queryStats) = $this->fetchResult();
00142 }
00143 return $result;
00144 }
00145
00146
00147
00148
00149
00150
00151 function execute($sql) {
00152 $result = parent::execute($sql);
00153 $this->_queryStats = array();
00154 return $result;
00155 }
00156
00157
00158
00159
00160
00161 function listSources() {
00162 $db = $this->config['database'];
00163 $this->config['database'] = basename($this->config['database']);
00164
00165 $cache = parent::listSources();
00166 if ($cache != null) {
00167 return $cache;
00168 }
00169
00170 $result = $this->fetchAll("SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;");
00171
00172 if (!$result || empty($result)) {
00173 return array();
00174 } else {
00175 $tables = array();
00176 foreach ($result as $table) {
00177 $tables[] = $table[0]['name'];
00178 }
00179 parent::listSources($tables);
00180
00181 $this->config['database'] = $db;
00182 return $tables;
00183 }
00184 $this->config['database'] = $db;
00185 return array();
00186 }
00187
00188
00189
00190
00191
00192
00193 function describe(&$model) {
00194 $cache = parent::describe($model);
00195 if ($cache != null) {
00196 return $cache;
00197 }
00198 $fields = array();
00199 $result = $this->fetchAll('PRAGMA table_info(' . $this->fullTableName($model) . ')');
00200
00201 foreach ($result as $column) {
00202 $fields[$column[0]['name']] = array(
00203 'type' => $this->column($column[0]['type']),
00204 'null' => !$column[0]['notnull'],
00205 'default' => $column[0]['dflt_value'],
00206 'length' => $this->length($column[0]['type'])
00207 );
00208 if($column[0]['pk'] == 1) {
00209 $fields[$column[0]['name']] = array(
00210 'type' => $fields[$column[0]['name']]['type'],
00211 'null' => false,
00212 'default' => $column[0]['dflt_value'],
00213 'key' => $this->index['PRI'],
00214 'length' => 11
00215 );
00216 }
00217 }
00218
00219 $this->__cacheDescription($model->tablePrefix . $model->table, $fields);
00220 return $fields;
00221 }
00222
00223
00224
00225
00226
00227
00228 function value($data, $column = null, $safe = false) {
00229 $parent = parent::value($data, $column, $safe);
00230
00231 if ($parent != null) {
00232 return $parent;
00233 }
00234 if ($data === null) {
00235 return 'NULL';
00236 }
00237 if ($data === '') {
00238 return "''";
00239 }
00240 switch ($column) {
00241 case 'boolean':
00242 $data = $this->boolean((bool)$data);
00243 break;
00244 default:
00245 $data = sqlite_escape_string($data);
00246 break;
00247 }
00248 return "'" . $data . "'";
00249 }
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259 function update(&$model, $fields = array(), $values = null, $conditions = null) {
00260 if (empty($values) && !empty($fields)) {
00261 foreach ($fields as $field => $value) {
00262 if (strpos($field, $model->alias . '.') !== false) {
00263 unset($fields[$field]);
00264 $field = str_replace($model->alias . '.', "", $field);
00265 $field = str_replace($model->alias . '.', "", $field);
00266 $fields[$field] = $value;
00267 }
00268 }
00269 }
00270 $result = parent::update($model, $fields, $values, $conditions);
00271 return $result;
00272 }
00273
00274
00275
00276
00277
00278
00279
00280
00281 function truncate($table) {
00282 return $this->execute('DELETE From ' . $this->fullTableName($table));
00283 }
00284
00285
00286
00287
00288
00289 function lastError() {
00290 $error = sqlite_last_error($this->connection);
00291 if ($error) {
00292 return $error.': '.sqlite_error_string($error);
00293 }
00294 return null;
00295 }
00296
00297
00298
00299
00300
00301 function lastAffected() {
00302 if (!empty($this->_queryStats)) {
00303 foreach (array('rows inserted', 'rows updated', 'rows deleted') as $key) {
00304 if (array_key_exists($key, $this->_queryStats)) {
00305 return $this->_queryStats[$key];
00306 }
00307 }
00308 }
00309 return false;
00310 }
00311
00312
00313
00314
00315
00316
00317 function lastNumRows() {
00318 if ($this->hasResult()) {
00319 sqlite_num_rows($this->_result);
00320 }
00321 return false;
00322 }
00323
00324
00325
00326
00327
00328 function lastInsertId() {
00329 return sqlite_last_insert_rowid($this->connection);
00330 }
00331
00332
00333
00334
00335
00336
00337 function column($real) {
00338 if (is_array($real)) {
00339 $col = $real['name'];
00340 if (isset($real['limit'])) {
00341 $col .= '('.$real['limit'].')';
00342 }
00343 return $col;
00344 }
00345
00346 $col = strtolower(str_replace(')', '', $real));
00347 $limit = null;
00348 if (strpos($col, '(') !== false) {
00349 list($col, $limit) = explode('(', $col);
00350 }
00351
00352 if (in_array($col, array('text', 'integer', 'float', 'boolean', 'timestamp', 'date', 'datetime', 'time'))) {
00353 return $col;
00354 }
00355 if (strpos($col, 'varchar') !== false) {
00356 return 'string';
00357 }
00358 if (in_array($col, array('blob', 'clob'))) {
00359 return 'binary';
00360 }
00361 if (strpos($col, 'numeric') !== false) {
00362 return 'float';
00363 }
00364 return 'text';
00365 }
00366
00367
00368
00369
00370
00371 function resultSet(&$results) {
00372 $this->results =& $results;
00373 $this->map = array();
00374 $fieldCount = sqlite_num_fields($results);
00375 $index = $j = 0;
00376
00377 while ($j < $fieldCount) {
00378 $columnName = str_replace('"', '', sqlite_field_name($results, $j));
00379
00380 if (strpos($columnName, '.')) {
00381 $parts = explode('.', $columnName);
00382 $this->map[$index++] = array($parts[0], $parts[1]);
00383 } else {
00384 $this->map[$index++] = array(0, $columnName);
00385 }
00386 $j++;
00387 }
00388 }
00389
00390
00391
00392
00393
00394 function fetchResult() {
00395 if ($row = sqlite_fetch_array($this->results, SQLITE_ASSOC)) {
00396 $resultRow = array();
00397 $i = 0;
00398
00399 foreach ($row as $index => $field) {
00400 if (strpos($index, '.')) {
00401 list($table, $column) = explode('.', str_replace('"', '', $index));
00402 $resultRow[$table][$column] = $row[$index];
00403 } else {
00404 $resultRow[0][str_replace('"', '', $index)] = $row[$index];
00405 }
00406 $i++;
00407 }
00408 return $resultRow;
00409 } else {
00410 return false;
00411 }
00412 }
00413
00414
00415
00416
00417
00418
00419
00420 function limit ($limit, $offset = null) {
00421 if ($limit) {
00422 $rt = '';
00423 if (!strpos(strtolower($limit), 'limit') || strpos(strtolower($limit), 'limit') === 0) {
00424 $rt = ' LIMIT';
00425 }
00426 $rt .= ' ' . $limit;
00427 if ($offset) {
00428 $rt .= ' OFFSET ' . $offset;
00429 }
00430 return $rt;
00431 }
00432 return null;
00433 }
00434
00435
00436
00437
00438
00439
00440
00441 function buildColumn($column) {
00442 $name = $type = null;
00443 $column = array_merge(array('null' => true), $column);
00444 extract($column);
00445
00446 if (empty($name) || empty($type)) {
00447 trigger_error('Column name or type not defined in schema', E_USER_WARNING);
00448 return null;
00449 }
00450
00451 if (!isset($this->columns[$type])) {
00452 trigger_error("Column type {$type} does not exist", E_USER_WARNING);
00453 return null;
00454 }
00455
00456 $real = $this->columns[$type];
00457 if (isset($column['key']) && $column['key'] == 'primary') {
00458 $out = $this->name($name) . ' ' . $this->columns['primary_key']['name'];
00459 } else {
00460 $out = $this->name($name) . ' ' . $real['name'];
00461
00462 if (isset($real['limit']) || isset($real['length']) || isset($column['limit']) || isset($column['length'])) {
00463 if (isset($column['length'])) {
00464 $length = $column['length'];
00465 } elseif (isset($column['limit'])) {
00466 $length = $column['limit'];
00467 } elseif (isset($real['length'])) {
00468 $length = $real['length'];
00469 } else {
00470 $length = $real['limit'];
00471 }
00472 $out .= '(' . $length . ')';
00473 }
00474 if (isset($column['key']) && $column['key'] == 'primary') {
00475 $out .= ' NOT NULL';
00476 } elseif (isset($column['default']) && isset($column['null']) && $column['null'] == false) {
00477 $out .= ' DEFAULT ' . $this->value($column['default'], $type) . ' NOT NULL';
00478 } elseif (isset($column['default'])) {
00479 $out .= ' DEFAULT ' . $this->value($column['default'], $type);
00480 } elseif (isset($column['null']) && $column['null'] == true) {
00481 $out .= ' DEFAULT NULL';
00482 } elseif (isset($column['null']) && $column['null'] == false) {
00483 $out .= ' NOT NULL';
00484 }
00485 }
00486 return $out;
00487 }
00488
00489
00490
00491
00492
00493 function setEncoding($enc) {
00494 if (!in_array($enc, array("UTF-8", "UTF-16", "UTF-16le", "UTF-16be"))) {
00495 return false;
00496 }
00497 return $this->_execute("PRAGMA encoding = \"{$enc}\"") !== false;
00498 }
00499
00500
00501
00502
00503
00504 function getEncoding() {
00505 return $this->fetchRow('PRAGMA encoding');
00506 }
00507
00508
00509
00510
00511
00512
00513
00514 function buildIndex($indexes, $table = null) {
00515 $join = array();
00516
00517 foreach ($indexes as $name => $value) {
00518
00519 if ($name == 'PRIMARY') {
00520 continue;
00521 }
00522 $out = 'CREATE ';
00523
00524 if (!empty($value['unique'])) {
00525 $out .= 'UNIQUE ';
00526 }
00527 if (is_array($value['column'])) {
00528 $value['column'] = join(', ', array_map(array(&$this, 'name'), $value['column']));
00529 } else {
00530 $value['column'] = $this->name($value['column']);
00531 }
00532 $out .= "INDEX {$name} ON {$table}({$value['column']});";
00533 $join[] = $out;
00534 }
00535 return $join;
00536 }
00537
00538
00539
00540
00541
00542
00543
00544 function renderStatement($type, $data) {
00545 switch (strtolower($type)) {
00546 case 'schema':
00547 extract($data);
00548
00549 foreach (array('columns', 'indexes') as $var) {
00550 if (is_array(${$var})) {
00551 ${$var} = "\t" . join(",\n\t", array_filter(${$var}));
00552 }
00553 }
00554 return "CREATE TABLE {$table} (\n{$columns});\n{$indexes}";
00555 break;
00556 default:
00557 return parent::renderStatement($type, $data);
00558 break;
00559 }
00560 }
00561 }
00562
00563 ?>