PageRenderTime 26ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/system/libraries/drivers/Database/Pdosqlite.php

https://github.com/yamamoto123/Ushahidi_Web
PHP | 473 lines | 411 code | 35 blank | 27 comment | 22 complexity | a7b968ed6a966c6e18940ff1272b209b MD5 | raw file
  1. <?php defined('SYSPATH') OR die('No direct access allowed.');
  2. /*
  3. * Class: Database_PdoSqlite_Driver
  4. * Provides specific database items for Sqlite.
  5. *
  6. * Connection string should be, eg: "pdosqlite://path/to/database.db"
  7. *
  8. * Version 1.0 alpha
  9. * author - Doutu, updated by gregmac
  10. * copyright - (c) BSD
  11. * license - <no>
  12. */
  13. class Database_Pdosqlite_Driver extends Database_Driver {
  14. // Database connection link
  15. protected $link;
  16. protected $db_config;
  17. /*
  18. * Constructor: __construct
  19. * Sets up the config for the class.
  20. *
  21. * Parameters:
  22. * config - database configuration
  23. *
  24. */
  25. public function __construct($config)
  26. {
  27. $this->db_config = $config;
  28. Kohana::log('debug', 'PDO:Sqlite Database Driver Initialized');
  29. }
  30. public function connect()
  31. {
  32. // Import the connect variables
  33. extract($this->db_config['connection']);
  34. try
  35. {
  36. $this->link = new PDO('sqlite:'.$socket.$database, $user, $pass,
  37. array(PDO::ATTR_PERSISTENT => $this->db_config['persistent']));
  38. $this->link->setAttribute(PDO::ATTR_CASE, PDO::CASE_NATURAL);
  39. $this->link->query('PRAGMA count_changes=1;');
  40. if ($charset = $this->db_config['character_set'])
  41. {
  42. $this->set_charset($charset);
  43. }
  44. }
  45. catch (PDOException $e)
  46. {
  47. throw new Kohana_Database_Exception('database.error', $e->getMessage());
  48. }
  49. // Clear password after successful connect
  50. $this->db_config['connection']['pass'] = NULL;
  51. return $this->link;
  52. }
  53. public function query($sql)
  54. {
  55. try
  56. {
  57. $sth = $this->link->prepare($sql);
  58. }
  59. catch (PDOException $e)
  60. {
  61. throw new Kohana_Database_Exception('database.error', $e->getMessage());
  62. }
  63. return new Pdosqlite_Result($sth, $this->link, $this->db_config['object'], $sql);
  64. }
  65. public function set_charset($charset)
  66. {
  67. $this->link->query('PRAGMA encoding = '.$this->escape_str($charset));
  68. }
  69. public function escape_table($table)
  70. {
  71. if ( ! $this->db_config['escape'])
  72. return $table;
  73. return '`'.str_replace('.', '`.`', $table).'`';
  74. }
  75. public function escape_column($column)
  76. {
  77. if ( ! $this->db_config['escape'])
  78. return $column;
  79. if (strtolower($column) == 'count(*)' OR $column == '*')
  80. return $column;
  81. // This matches any modifiers we support to SELECT.
  82. if ( ! preg_match('/\b(?:rand|all|distinct(?:row)?|high_priority|sql_(?:small_result|b(?:ig_result|uffer_result)|no_cache|ca(?:che|lc_found_rows)))\s/i', $column))
  83. {
  84. if (stripos($column, ' AS ') !== FALSE)
  85. {
  86. // Force 'AS' to uppercase
  87. $column = str_ireplace(' AS ', ' AS ', $column);
  88. // Runs escape_column on both sides of an AS statement
  89. $column = array_map(array($this, __FUNCTION__), explode(' AS ', $column));
  90. // Re-create the AS statement
  91. return implode(' AS ', $column);
  92. }
  93. return preg_replace('/[^.*]+/', '`$0`', $column);
  94. }
  95. $parts = explode(' ', $column);
  96. $column = '';
  97. for ($i = 0, $c = count($parts); $i < $c; $i++)
  98. {
  99. // The column is always last
  100. if ($i == ($c - 1))
  101. {
  102. $column .= preg_replace('/[^.*]+/', '`$0`', $parts[$i]);
  103. }
  104. else // otherwise, it's a modifier
  105. {
  106. $column .= $parts[$i].' ';
  107. }
  108. }
  109. return $column;
  110. }
  111. public function limit($limit, $offset = 0)
  112. {
  113. return 'LIMIT '.$offset.', '.$limit;
  114. }
  115. public function compile_select($database)
  116. {
  117. $sql = ($database['distinct'] == TRUE) ? 'SELECT DISTINCT ' : 'SELECT ';
  118. $sql .= (count($database['select']) > 0) ? implode(', ', $database['select']) : '*';
  119. if (count($database['from']) > 0)
  120. {
  121. $sql .= "\nFROM ";
  122. $sql .= implode(', ', $database['from']);
  123. }
  124. if (count($database['join']) > 0)
  125. {
  126. foreach($database['join'] AS $join)
  127. {
  128. $sql .= "\n".$join['type'].'JOIN '.implode(', ', $join['tables']).' ON '.$join['conditions'];
  129. }
  130. }
  131. if (count($database['where']) > 0)
  132. {
  133. $sql .= "\nWHERE ";
  134. }
  135. $sql .= implode("\n", $database['where']);
  136. if (count($database['groupby']) > 0)
  137. {
  138. $sql .= "\nGROUP BY ";
  139. $sql .= implode(', ', $database['groupby']);
  140. }
  141. if (count($database['having']) > 0)
  142. {
  143. $sql .= "\nHAVING ";
  144. $sql .= implode("\n", $database['having']);
  145. }
  146. if (count($database['orderby']) > 0)
  147. {
  148. $sql .= "\nORDER BY ";
  149. $sql .= implode(', ', $database['orderby']);
  150. }
  151. if (is_numeric($database['limit']))
  152. {
  153. $sql .= "\n";
  154. $sql .= $this->limit($database['limit'], $database['offset']);
  155. }
  156. return $sql;
  157. }
  158. public function escape_str($str)
  159. {
  160. if ( ! $this->db_config['escape'])
  161. return $str;
  162. if (function_exists('sqlite_escape_string'))
  163. {
  164. $res = sqlite_escape_string($str);
  165. }
  166. else
  167. {
  168. $res = str_replace("'", "''", $str);
  169. }
  170. return $res;
  171. }
  172. public function list_tables(Database $db)
  173. {
  174. $sql = "SELECT `name` FROM `sqlite_master` WHERE `type`='table' ORDER BY `name`;";
  175. try
  176. {
  177. $result = $db->query($sql)->result(FALSE, PDO::FETCH_ASSOC);
  178. $tables = array();
  179. foreach ($result as $row)
  180. {
  181. $tables[] = current($row);
  182. }
  183. }
  184. catch (PDOException $e)
  185. {
  186. throw new Kohana_Database_Exception('database.error', $e->getMessage());
  187. }
  188. return $tables;
  189. }
  190. public function show_error()
  191. {
  192. $err = $this->link->errorInfo();
  193. return isset($err[2]) ? $err[2] : 'Unknown error!';
  194. }
  195. public function list_fields($table, $query = FALSE)
  196. {
  197. static $tables;
  198. if (is_object($query))
  199. {
  200. if (empty($tables[$table]))
  201. {
  202. $tables[$table] = array();
  203. foreach ($query->result() as $row)
  204. {
  205. $tables[$table][] = $row->name;
  206. }
  207. }
  208. return $tables[$table];
  209. }
  210. else
  211. {
  212. $result = $this->link->query( 'PRAGMA table_info('.$this->escape_table($table).')' );
  213. foreach ($result as $row)
  214. {
  215. $tables[$table][$row['name']] = $this->sql_type($row['type']);
  216. }
  217. return $tables[$table];
  218. }
  219. }
  220. public function field_data($table)
  221. {
  222. Kohana::log('error', 'This method is under developing');
  223. }
  224. /**
  225. * Version number query string
  226. *
  227. * @access public
  228. * @return string
  229. */
  230. function version()
  231. {
  232. return $this->link->getAttribute(constant("PDO::ATTR_SERVER_VERSION"));
  233. }
  234. } // End Database_PdoSqlite_Driver Class
  235. /*
  236. * PDO-sqlite Result
  237. */
  238. class Pdosqlite_Result extends Database_Result {
  239. // Data fetching types
  240. protected $fetch_type = PDO::FETCH_OBJ;
  241. protected $return_type = PDO::FETCH_ASSOC;
  242. /**
  243. * Sets up the result variables.
  244. *
  245. * @param resource query result
  246. * @param resource database link
  247. * @param boolean return objects or arrays
  248. * @param string SQL query that was run
  249. */
  250. public function __construct($result, $link, $object = TRUE, $sql)
  251. {
  252. if (is_object($result) OR $result = $link->prepare($sql))
  253. {
  254. // run the query
  255. try
  256. {
  257. $result->execute();
  258. }
  259. catch (PDOException $e)
  260. {
  261. throw new Kohana_Database_Exception('database.error', $e->getMessage());
  262. }
  263. if (preg_match('/^SELECT|PRAGMA|EXPLAIN/i', $sql))
  264. {
  265. $this->result = $result;
  266. $this->current_row = 0;
  267. $this->total_rows = $this->sqlite_row_count();
  268. $this->fetch_type = ($object === TRUE) ? PDO::FETCH_OBJ : PDO::FETCH_ASSOC;
  269. }
  270. elseif (preg_match('/^DELETE|INSERT|UPDATE/i', $sql))
  271. {
  272. $this->insert_id = $link->lastInsertId();
  273. }
  274. }
  275. else
  276. {
  277. // SQL error
  278. throw new Kohana_Database_Exception('database.error', $link->errorInfo().' - '.$sql);
  279. }
  280. // Set result type
  281. $this->result($object);
  282. // Store the SQL
  283. $this->sql = $sql;
  284. }
  285. private function sqlite_row_count()
  286. {
  287. $count = 0;
  288. while ($this->result->fetch())
  289. {
  290. $count++;
  291. }
  292. // The query must be re-fetched now.
  293. $this->result->execute();
  294. return $count;
  295. }
  296. /*
  297. * Destructor: __destruct
  298. * Magic __destruct function, frees the result.
  299. */
  300. public function __destruct()
  301. {
  302. if (is_object($this->result))
  303. {
  304. $this->result->closeCursor();
  305. $this->result = NULL;
  306. }
  307. }
  308. public function result($object = TRUE, $type = PDO::FETCH_BOTH)
  309. {
  310. $this->fetch_type = (bool) $object ? PDO::FETCH_OBJ : PDO::FETCH_BOTH;
  311. if ($this->fetch_type == PDO::FETCH_OBJ)
  312. {
  313. $this->return_type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
  314. }
  315. else
  316. {
  317. $this->return_type = $type;
  318. }
  319. return $this;
  320. }
  321. public function as_array($object = NULL, $type = PDO::FETCH_ASSOC)
  322. {
  323. return $this->result_array($object, $type);
  324. }
  325. public function result_array($object = NULL, $type = PDO::FETCH_ASSOC)
  326. {
  327. $rows = array();
  328. if (is_string($object))
  329. {
  330. $fetch = $object;
  331. }
  332. elseif (is_bool($object))
  333. {
  334. if ($object === TRUE)
  335. {
  336. $fetch = PDO::FETCH_OBJ;
  337. // NOTE - The class set by $type must be defined before fetching the result,
  338. // autoloading is disabled to save a lot of stupid overhead.
  339. $type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
  340. }
  341. else
  342. {
  343. $fetch = PDO::FETCH_OBJ;
  344. }
  345. }
  346. else
  347. {
  348. // Use the default config values
  349. $fetch = $this->fetch_type;
  350. if ($fetch == PDO::FETCH_OBJ)
  351. {
  352. $type = (is_string($type) AND Kohana::auto_load($type)) ? $type : 'stdClass';
  353. }
  354. }
  355. try
  356. {
  357. while ($row = $this->result->fetch($fetch))
  358. {
  359. $rows[] = $row;
  360. }
  361. }
  362. catch(PDOException $e)
  363. {
  364. throw new Kohana_Database_Exception('database.error', $e->getMessage());
  365. return FALSE;
  366. }
  367. return $rows;
  368. }
  369. public function list_fields()
  370. {
  371. $field_names = array();
  372. for ($i = 0, $max = $this->result->columnCount(); $i < $max; $i++)
  373. {
  374. $info = $this->result->getColumnMeta($i);
  375. $field_names[] = $info['name'];
  376. }
  377. return $field_names;
  378. }
  379. public function seek($offset)
  380. {
  381. // To request a scrollable cursor for your PDOStatement object, you must
  382. // set the PDO::ATTR_CURSOR attribute to PDO::CURSOR_SCROLL when you
  383. // prepare the statement.
  384. Kohana::log('error', get_class($this).' does not support scrollable cursors, '.__FUNCTION__.' call ignored');
  385. return FALSE;
  386. }
  387. public function offsetGet($offset)
  388. {
  389. try
  390. {
  391. return $this->result->fetch($this->fetch_type, PDO::FETCH_ORI_ABS, $offset);
  392. }
  393. catch(PDOException $e)
  394. {
  395. throw new Kohana_Database_Exception('database.error', $e->getMessage());
  396. }
  397. }
  398. public function rewind()
  399. {
  400. // Same problem that seek() has, see above.
  401. return $this->seek(0);
  402. }
  403. } // End PdoSqlite_Result Class