1<?php 2/** 3 * Implements specific functions of the PHPs Sqlite Extension 4 * 5 * This adapter give sqlite2 support, and is based on code of previous 6 * versions of the sqlite plugin 7 */ 8class helper_plugin_sqlite_adapter_sqlite2 extends helper_plugin_sqlite_adapter { 9 protected $fileextension = '.sqlite'; 10 protected $db; 11 12 /** 13 * return name of adapter 14 * 15 * @return string adapter name 16 */ 17 public function getName() { 18 return DOKU_EXT_SQLITE; 19 } 20 21 /** 22 * open db 23 * 24 * @param bool $init true if this is a new database to initialize 25 * @param bool $sqliteupgrade when connecting to a new database: 26 * false stops connecting to an .sqlite3 db when an .sqlite2 db already exist and warns instead, 27 * true let connecting so upgrading is possible 28 * @return bool true if connecting to sqlite3 db succeed 29 */ 30 public function opendb($init, $sqliteupgrade = false) { 31 if($this->isSqlite3db($this->dbfile)) { 32 msg("SQLite: failed to open SQLite '".$this->dbname."' database (DB has a sqlite3 format instead of sqlite2 format.)", -1); 33 return false; 34 } 35 36 $error = ''; 37 $this->db = sqlite_open($this->dbfile, 0666, $error); 38 if(!$this->db) { 39 msg("SQLite: failed to open SQLite '".$this->dbname."' database ($error)", -1); 40 return false; 41 } 42 43 // register our custom aggregate function 44 sqlite_create_aggregate( 45 $this->db, 'group_concat', 46 array($this, '_sqlite_group_concat_step'), 47 array($this, '_sqlite_group_concat_finalize'), 2 48 ); 49 return true; 50 } 51 52 /** 53 * close current db 54 */ 55 public function closedb() { 56 sqlite_close($this->db); 57 } 58 59 /** 60 * Registers a User Defined Function for use in SQL statements 61 */ 62 public function create_function($function_name, $callback, $num_args) { 63 sqlite_create_function($this->db, $function_name, $callback, $num_args); 64 } 65 66 /** 67 * Execute a query. 68 * 69 * @param string $sql query 70 * @return bool|\SQLiteResult 71 */ 72 public function executeQuery($sql) { 73 $err = ''; 74 $res = @sqlite_query($this->db, $sql, SQLITE_ASSOC, $err); 75 if($err) { 76 msg($err.':<br /><pre>'.hsc($sql).'</pre>', -1); 77 return false; 78 } elseif(!$res) { 79 msg( 80 sqlite_error_string(sqlite_last_error($this->db)). 81 ':<br /><pre>'.hsc($sql).'</pre>', -1 82 ); 83 return false; 84 } 85 86 return $res; 87 } 88 89 /** 90 * Close the result set and it's cursors 91 * 92 * @param bool|\SQLiteResult $res 93 * @return bool 94 */ 95 public function res_close($res) { 96 return true; //seems not to be needed in sqlite2? 97 } 98 99 /** 100 * Returns a complete result set as array 101 * 102 * @param bool|\SQLiteResult $res 103 * @param bool $assoc 104 * @return array of arrays of the rows 105 */ 106 public function res2arr($res, $assoc = true) { 107 $data = array(); 108 109 if(!$res) return $data; 110 if(!sqlite_num_rows($res)) return $data; 111 112 sqlite_rewind($res); 113 $mode = $assoc ? SQLITE_ASSOC : SQLITE_NUM; 114 while(($row = sqlite_fetch_array($res, $mode)) !== false) { 115 $data[] = $row; 116 } 117 return $data; 118 } 119 120 /** 121 * Return the next row of the given result set as associative array 122 * 123 * @param bool|\SQLiteResult $res 124 * @return array|bool next row or false 125 */ 126 public function res2row($res) { 127 if(!$res) return false; 128 return sqlite_fetch_array($res, SQLITE_ASSOC); 129 } 130 131 /** 132 * Return the first value from the next row. 133 * 134 * @param bool|\SQLiteResult $res 135 * @return bool|string 136 */ 137 public function res2single($res) { 138 if(!$res) return false; 139 140 return sqlite_fetch_single($res); 141 } 142 143 /** 144 * Run sqlite_escape_string() on the given string and surround it 145 * with quotes 146 * 147 * @param string $string 148 * @return string escaped and quoted string 149 */ 150 public function quote_string($string) { 151 return "'".sqlite_escape_string($string)."'"; 152 } 153 154 /** 155 * Escape string for sql 156 * 157 * @param string $str 158 * @return string escaped 159 */ 160 public function escape_string($str) { 161 return sqlite_escape_string($str); 162 } 163 164 /** 165 * Aggregation function for SQLite 166 * Callback function called for each row of the result set. 167 * 168 * @link http://devzone.zend.com/article/863-SQLite-Lean-Mean-DB-Machine 169 * 170 * @param array &$context (reference) argument where processed data can be stored 171 * @param string $string column value 172 * @param string $separator separator between the values 173 */ 174 public function _sqlite_group_concat_step(&$context, $string, $separator = ',') { 175 $context['sep'] = $separator; 176 $context['data'][] = $string; 177 } 178 179 /** 180 * Aggregation function for SQLite 181 * Callback function to aggregate the "stepped" data from each row and return it. 182 * 183 * @link http://devzone.zend.com/article/863-SQLite-Lean-Mean-DB-Machine 184 * 185 * @param array &$context (reference) data as collected in step callback 186 * @return string final result of aggregation 187 */ 188 public function _sqlite_group_concat_finalize(&$context) { 189 $context['data'] = array_unique($context['data']); 190 return join($context['sep'], $context['data']); 191 } 192 193 /** 194 * fetch the next row as zero indexed array 195 * 196 * @param bool|\SQLiteResult $res 197 * @return array|bool 198 */ 199 public function res_fetch_array($res) { 200 if(!$res) return false; 201 202 return sqlite_fetch_array($res, SQLITE_NUM); 203 } 204 205 /** 206 * fetch the next row as assocative array 207 * 208 * @param bool|\SQLiteResult $res 209 * @return array|bool 210 */ 211 public function res_fetch_assoc($res) { 212 if(!$res) return false; 213 214 return sqlite_fetch_array($res, SQLITE_ASSOC); 215 } 216 217 /** 218 * Count the number of records in result 219 * 220 * This function is really inperformant in PDO and should be avoided! 221 * 222 * @param bool|\SQLiteResult $res 223 * @return int 224 */ 225 public function res2count($res) { 226 if(!$res) return 0; 227 228 return sqlite_num_rows($res); 229 } 230 231 /** 232 * Count the number of records changed last time 233 * 234 * Don't work after a SELECT statement in PDO 235 * 236 * @param bool|\SQLiteResult $res 237 * @return int 238 */ 239 public function countChanges($res) { 240 if(!$res) return 0; 241 return sqlite_changes($this->db); 242 } 243} 244 245// vim:ts=4:sw=4:et:enc=utf-8: 246