00001 <?php
00002
00003 require_once(dirname(__FILE__) . '/KjwSql.php');
00004
00005
00006
00007
00008
00009
00015 class KjwFakeSql extends KjwSql {
00016 var $_lockName = null;
00017 var $_lockHandle = null;
00018 var $_locked = null;
00019
00030 function KjwFakeSql($sqltype, $unused_host, $unused_port, $unused_user, $unused_pass, $lockpath = null) {
00031 parent::KjwSql($sqltype, $unused_host, $unused_port, $unused_user, $unused_pass, $lockpath);
00032 $this->_lockName = $lockpath;
00033 }
00034
00035
00036 function destroy() {
00037 parent::destroy();
00038 $this->disconnect();
00039 }
00040
00041
00042 function connect() {
00043 global $kjw_suppressed_error;
00044 if ($this->_lockHandle)
00045 return true;
00046 if ($this->_lockHandle === null)
00047 if (($this->_lockHandle = @fopen($this->_lockName, 'a')) === false)
00048 $this->croak('Database Data Transfer Failure',
00049 'Can\'t open lockfile "' . $this->_lockName . '": ' . $kjw_suppressed_error);
00050 return true;
00051 }
00052
00053
00054 function disconnect() {
00055 if ($this->_locked)
00056 $this->_releaseLock();
00057 if ($this->_lockHandle && fclose($this->_lockHandle))
00058 $this->_lockHandle = null;
00059 return $this->_locked === null && !$this->_lockHandle;
00060 }
00061
00062 function _acquireLock($type = 'RW', $retryCount = 3, $waitMs = 64) {
00063 $this->trace("_acquireLock: $type, $retryCount, $waitMs");
00064 switch ($type) {
00065 case 'R': $flocktype = LOCK_SH ; break;
00066 case 'RW': $flocktype = LOCK_EX ; break;
00067 default: return false;
00068 }
00069
00070 if ($this->_lockHandle === null)
00071 $this->connect();
00072 if (!$this->_lockHandle)
00073 return false;
00074 if (flock($this->_lockHandle, $flocktype)) {
00075 $this->_locked = $type;
00076 return true;
00077 } elseif ($retryCount > 1) {
00078
00079 return $this->_acquireLock($type, $retryCount - 1, $waitMs << 1);
00080 }
00081 return false;
00082 }
00083
00084 function _releaseLock() {
00085 if ($this->_locked && flock($this->_lockHandle, LOCK_UN))
00086 $this->_locked = null;
00087 }
00088
00089
00090 function execute($query) {
00091 $this->_last_query = $query;
00092
00093
00094
00095
00096 if (preg_match('/^\s*
00097 select\s+(\*)\s+
00098 from\s+([0-9A-Za-z%_-]+)
00099 (\s+order\s+by\s+([0-9A-Za-z%_-]+(\s+asc|\s+desc)?(\s*,\s[0-9A-Za-z%_-]+(\s+asc|\s+desc))?))?
00100 (\s+limit\s+([0-9]+)(\s*,\s*([0-9]+))?)?
00101 \s*$/ix', $query, $m)) {
00102 $columns = $m[1];
00103 $table = $this->_nameUnquote($m[2]);
00104 $order = array();
00105 if (isset($m[4])) {
00106 foreach (preg_split('/\s*,\s*/', $m[4]) as $v) {
00107 $tmp = preg_split('/\s+/', $v);
00108 if (sizeof($tmp) == 1)
00109 array_push($order, "+" . $this->_nameUnquote($v));
00110 else
00111 array_push($order, ($tmp[1] == 'asc' ? '+' : '-') . $this->_nameUnquote($tmp[0]));
00112 }
00113 }
00114 if (isset($m[11])) {
00115 $skip = (int)$m[9];
00116 $max = (int)$m[11];
00117 } else {
00118 $skip = 0;
00119 $max = isset($m[9]) ? (int)$m[9] : -1;
00120 }
00121 return $this->_simpleSelect($table, $columns, $order, $skip, $max);
00122 } elseif (preg_match('/^\s*
00123 insert\s+into\s+([0-9A-Za-z%_-]+)\s*
00124 (\(([\s,0-9A-Za-z%_-]+)\))?
00125 \s*values\s*
00126 \(\s*(.*?)\s*\)
00127 \s*$/ix', $query, $m)) {
00128 $table = $m[1];
00129 $columns = $m[3] != '' ? $this->_splitColumns($m[3]) : null;
00130 $values = $this->_splitValues($m[4]);
00131 if ($columns === null)
00132 return $this->_simpleInsert($table, $values);
00133 if (sizeof($columns) != sizeof($values))
00134 $this->croak('Database Data Transfer Failure', 'Column and value count differ.');
00135 $args = array();
00136 reset($values);
00137 foreach ($columns as $key) {
00138 $value = each($values);
00139 $args[$key] = $value['value'];
00140 }
00141 return $this->_simpleInsert($table, $args);
00142 }
00143 echo $query;
00144
00145 $this->croak('Database Data Transfer Failure',
00146 'Unknown or unsupported SQL command.' . (KJW_DEBUG ? " Query was: $query" : ''));
00147 }
00148
00149
00150 function nameQuote($name) {
00151
00152 return urlencode($name);
00153 }
00154
00158 function _nameUnquote($quoted) {
00159 return urldecode($quoted);
00160 }
00161
00162
00163 function safeQuote($mixed) {
00164 if (is_string($mixed))
00165 return "'" . str_replace("'", "''", str_replace("\x00", '', $mixed)) . "'";
00166 return parent::safeQuote($mixed);
00167 }
00168
00169 function _safeUnquote($quoted) {
00170 if (strcasecmp($quoted, 'null') == 0)
00171 return null;
00172 if ($quoted[0] == "'")
00173 return str_replace("''", "'", substr($quoted, 1, -1));
00174 if (!is_numeric($quoted))
00175 $this->croak('Database Data Transfer Failure', 'Non-numeric literal found.');
00176 if (strpos($quoted, '.') === false)
00177 return (int)$quoted;
00178 return (float)$quoted;
00179 }
00180
00181 function _splitColumns($string) {
00182 return array_map(array($this, '_nameUnquote'), preg_split('/\s*,\s*/', $string));
00183 }
00184
00185 function _splitValues($string) {
00186 if (preg_match_all('/\s*([^\',\s]+|\'(\'\'|[^\'])*\')(\s*,\s*|\s*$)/', $string, $m) !== false)
00187 return array_map(array($this, '_safeUnquote'), $m[1]);
00188 $this->croak('Database Data Transfer Failure', 'Unable to parse value list.');
00189 }
00190 }
00191
00192 ?>