db = new SQLiteDatabase($filename, '0666', $error); // Throw an exception if there's an error if ( ! empty($error)) throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error)); $query = "SELECT name FROM sqlite_master WHERE type = 'table' AND name = 'caches'"; $tables = $this->db->query($query, SQLITE_BOTH, $error); // Throw an exception if there's an error if ( ! empty($error)) throw new Kohana_Exception('cache.driver_error', sqlite_error_string($error)); if ($tables->numRows() == 0) { Kohana::log('error', 'Cache: Initializing new SQLite cache database'); // Issue a CREATE TABLE command $this->db->unbufferedQuery(Kohana::config('cache_sqlite.schema')); } } /** * Checks if a cache id is already set. * * @param string cache id * @return boolean */ public function exists($id) { // Find the id that matches $query = "SELECT id FROM caches WHERE id = '$id'"; return ($this->db->query($query)->numRows() > 0); } /** * Sets a cache item to the given data, tags, and lifetime. * * @param string cache id to set * @param string data in the cache * @param array cache tags * @param integer lifetime * @return bool */ public function set($id, $data, array $tags = NULL, $lifetime) { // Serialize and escape the data $data = sqlite_escape_string(serialize($data)); if ( ! empty($tags)) { // Escape the tags, adding brackets so the tag can be explicitly matched $tags = sqlite_escape_string('<'.implode('>,<', $tags).'>'); } // Cache Sqlite driver expects unix timestamp if ($lifetime !== 0) { $lifetime += time(); } $query = $this->exists($id) ? "UPDATE caches SET tags = '$tags', expiration = '$lifetime', cache = '$data' WHERE id = '$id'" : "INSERT INTO caches VALUES('$id', '$tags', '$lifetime', '$data')"; // Run the query $this->db->unbufferedQuery($query, SQLITE_BOTH, $error); if ( ! empty($error)) { self::log_error($error); return FALSE; } else { return TRUE; } } /** * Finds an array of ids for a given tag. * * @param string tag name * @return array of ids that match the tag */ public function find($tag) { $query = "SELECT id,cache FROM caches WHERE tags LIKE '%<{$tag}>%'"; $query = $this->db->query($query, SQLITE_BOTH, $error); // An array will always be returned $result = array(); if ( ! empty($error)) { self::log_error($error); } elseif ($query->numRows() > 0) { // Disable notices for unserializing $ER = error_reporting(~E_NOTICE); while ($row = $query->fetchObject()) { // Add each cache to the array $result[$row->id] = unserialize($row->cache); } // Turn notices back on error_reporting($ER); } return $result; } /** * Fetches a cache item. This will delete the item if it is expired or if * the hash does not match the stored hash. * * @param string cache id * @return mixed|NULL */ public function get($id) { $query = "SELECT id, expiration, cache FROM caches WHERE id = '$id' LIMIT 0, 1"; $query = $this->db->query($query, SQLITE_BOTH, $error); if ( ! empty($error)) { self::log_error($error); } elseif ($cache = $query->fetchObject()) { // Make sure the expiration is valid and that the hash matches if ($cache->expiration != 0 AND $cache->expiration <= time()) { // Cache is not valid, delete it now $this->delete($cache->id); } else { // Disable notices for unserializing $ER = error_reporting(~E_NOTICE); // Return the valid cache data $data = $cache->cache; // Turn notices back on error_reporting($ER); } } // No valid cache found return NULL; } /** * Deletes a cache item by id or tag * * @param string cache id or tag, or TRUE for "all items" * @param bool delete a tag * @return bool */ public function delete($id, $tag = FALSE) { if ($id === TRUE) { // Delete all caches $where = '1'; } elseif ($tag === TRUE) { // Delete by tag $where = "tags LIKE '%<{$id}>%'"; } else { // Delete by id $where = "id = '$id'"; } $this->db->unbufferedQuery('DELETE FROM caches WHERE '.$where, SQLITE_BOTH, $error); if ( ! empty($error)) { self::log_error($error); return FALSE; } else { return TRUE; } } /** * Deletes all cache files that are older than the current time. */ public function delete_expired() { // Delete all expired caches $query = 'DELETE FROM caches WHERE expiration != 0 AND expiration <= '.time(); $this->db->unbufferedQuery($query); return TRUE; } } // End Cache SQLite Driver