_lockName = $lockpath; } /* [INHERITED DOCS] */ function destroy() { parent::destroy(); $this->disconnect(); } /* [INHERITED DOCS] */ function connect() { global $kjw_suppressed_error; if ($this->_lockHandle) return true; if ($this->_lockHandle === null) if (($this->_lockHandle = @fopen($this->_lockName, 'a')) === false) $this->croak('Database Data Transfer Failure', 'Can\'t open lockfile "' . $this->_lockName . '": ' . $kjw_suppressed_error); return true; } /* [INHERITED DOCS] */ function disconnect() { if ($this->_locked) $this->_releaseLock(); if ($this->_lockHandle && fclose($this->_lockHandle)) $this->_lockHandle = null; return $this->_locked === null && !$this->_lockHandle; } function _acquireLock($type = 'RW', $retryCount = 3, $waitMs = 64) { $this->trace("_acquireLock: $type, $retryCount, $waitMs"); switch ($type) { case 'R': $flocktype = LOCK_SH /*| LOCK_NB*/; break; case 'RW': $flocktype = LOCK_EX /*| LOCK_NB*/; break; default: return false; } if ($this->_lockHandle === null) $this->connect(); if (!$this->_lockHandle) return false; if (flock($this->_lockHandle, $flocktype)) { $this->_locked = $type; return true; } elseif ($retryCount > 1) { //usleep($waitMs * 1000); for LOCK_NB return $this->_acquireLock($type, $retryCount - 1, $waitMs << 1); } return false; } function _releaseLock() { if ($this->_locked && flock($this->_lockHandle, LOCK_UN)) $this->_locked = null; } /* [INHERITED DOCS] */ function execute($query) { $this->_last_query = $query; // // MATCH SELECT // select * from mytable order by a desc, b, c asc limit 2, 3 // if (preg_match('/^\s* select\s+(\*)\s+ from\s+([0-9A-Za-z%_-]+) (\s+order\s+by\s+([0-9A-Za-z%_-]+(\s+asc|\s+desc)?(\s*,\s[0-9A-Za-z%_-]+(\s+asc|\s+desc))?))? (\s+limit\s+([0-9]+)(\s*,\s*([0-9]+))?)? \s*$/ix', $query, $m)) { $columns = $m[1]; $table = $this->_nameUnquote($m[2]); $order = array(); if (isset($m[4])) { foreach (preg_split('/\s*,\s*/', $m[4]) as $v) { $tmp = preg_split('/\s+/', $v); if (sizeof($tmp) == 1) array_push($order, "+" . $this->_nameUnquote($v)); else array_push($order, ($tmp[1] == 'asc' ? '+' : '-') . $this->_nameUnquote($tmp[0])); } } if (isset($m[11])) { $skip = (int)$m[9]; $max = (int)$m[11]; } else { $skip = 0; $max = isset($m[9]) ? (int)$m[9] : -1; } return $this->_simpleSelect($table, $columns, $order, $skip, $max); } elseif (preg_match('/^\s* insert\s+into\s+([0-9A-Za-z%_-]+)\s* (\(([\s,0-9A-Za-z%_-]+)\))? \s*values\s* \(\s*(.*?)\s*\) \s*$/ix', $query, $m)) { $table = $m[1]; $columns = $m[3] != '' ? $this->_splitColumns($m[3]) : null; $values = $this->_splitValues($m[4]); if ($columns === null) return $this->_simpleInsert($table, $values); if (sizeof($columns) != sizeof($values)) $this->croak('Database Data Transfer Failure', 'Column and value count differ.'); $args = array(); reset($values); foreach ($columns as $key) { $value = each($values); $args[$key] = $value['value']; } return $this->_simpleInsert($table, $args); } echo $query; $this->croak('Database Data Transfer Failure', 'Unknown or unsupported SQL command.' . (KJW_DEBUG ? " Query was: $query" : '')); } /* [INHERITED DOCS] */ function nameQuote($name) { /* This way we know that we won't have to look for quotes and escaped quotes */ return urlencode($name); } /** * [PRIVATE] Undo what nameQuote does. */ function _nameUnquote($quoted) { return urldecode($quoted); } /* [INHERITED DOCS] */ function safeQuote($mixed) { if (is_string($mixed)) return "'" . str_replace("'", "''", str_replace("\x00", '', $mixed)) . "'"; return parent::safeQuote($mixed); } function _safeUnquote($quoted) { if (strcasecmp($quoted, 'null') == 0) return null; if ($quoted[0] == "'") return str_replace("''", "'", substr($quoted, 1, -1)); if (!is_numeric($quoted)) $this->croak('Database Data Transfer Failure', 'Non-numeric literal found.'); if (strpos($quoted, '.') === false) return (int)$quoted; return (float)$quoted; } function _splitColumns($string) { return array_map(array($this, '_nameUnquote'), preg_split('/\s*,\s*/', $string)); } function _splitValues($string) { if (preg_match_all('/\s*([^\',\s]+|\'(\'\'|[^\'])*\')(\s*,\s*|\s*$)/', $string, $m) !== false) return array_map(array($this, '_safeUnquote'), $m[1]); $this->croak('Database Data Transfer Failure', 'Unable to parse value list.'); } } ?>