25 protected $escapeChar =
"`";
31 private $_cacheRecords;
33 protected $_cached =
false;
34 protected $_transaction =
false;
72 abstract function connect($database=
'', $host=
'', $user=
'', $password=
'');
100 if (func_num_args() == 4)
109 $this->connect($args[0], $args[1], $args[2], $args[3]);
116 $this->select($query, $cache);
123 return get_class($this).
'('.$this->currentQuery.
')';
143 function query($query, $appendCurrent =
false)
145 if ($appendCurrent) {
146 $this->currentQuery .= $query;
148 $this->currentQuery = $query;
150 $this->_currentRow = -1;
151 $this->_stmt = $this->_db->query($query);
152 if ($this->_stmt ===
false) {
154 throw new Ego_Sql_Exception(implode(
' ', $this->_db->errorInfo()), (
int) $this->_db->errorCode());
166 ++$this->_currentRow;
167 $this->Record = $this->_stmt?$this->_stmt->fetch(PDO::FETCH_ASSOC):null;
168 if ($this->Record===
false) {
169 $this->Record = null;
171 return $this->Record;
179 $this->_currentRow = -1;
180 $this->_stmt->closeCursor();
181 $this->_stmt->execute();
216 ++$this->_currentRow;
217 ++$this->_cacheIndex;
218 if ($this->_cacheIndex<
sizeof($this->_cacheRecords))
220 return $this->Record = $this->_cacheRecords[$this->_cacheIndex];
224 return $this->_nextRecord();
234 return $this->_stmt?$this->_stmt->rowCount():0;
257 return $this->_cached?
sizeof($this->_cacheRecords):$this->_numRecords();
262 if ($query[
'bitand']) {
263 if (empty($query[
'where'])) {
264 $query[
'where'] =
'1=1';
266 foreach ($query[
'bitand'] as $bit) {
267 $query[
'where'] .=
' AND '.$bit[0].
'&'.$bit[1].
'='.$bit[2];
270 return 'SELECT '.($query[
'no_cache']?
'SQL_NO_CACHE ':
'')
271 .($query[
'distinct']?
'DISTINCT ':
'')
272 .($query[
'fields']?$query[
'fields']:
'*').($query[
'fields2']?
','.$query[
'fields2']:
'')
273 .
' FROM ('.($query[
'table']?$query[
'table']:$query[
'from'])
274 .($query[
'table2']?($query[
'table']?
',':
'').$query[
'table2']:
'').
')' 275 .($query[
'inner']?
' INNER JOIN '.(is_array($query[
'inner'])?
276 implode(
' INNER JOIN ', $query[
'inner']):$query[
'inner']):
'')
277 .($query[
'join']?
' LEFT JOIN '.(is_array($query[
'join'])?
278 implode(
' LEFT JOIN ', $query[
'join']):$query[
'join']):
'')
279 .($query[
'where']?
' WHERE '.$query[
'where']:
'')
280 .($query[
'group']?
' GROUP BY '.$query[
'group']:
'')
281 .($query[
'having']?
' HAVING '.$query[
'having']:
'')
282 .($query[
'order']?
' ORDER BY '.$query[
'order']:
'');
295 if ($query[
'field_as'])
297 foreach ($query[
'field_as'] as $k=>$v)
299 if ($query[
'field_as_bitand'][$k]) {
300 foreach ($query[
'field_as_bitand'][$k] as $bit) {
301 $v .=
' AND '.$bit[0].
'&'.$bit[1].
'='.$bit[2];
304 $query[
'fields2'] = ($query[
'fields2']?$query[
'fields2'].
',':
'').
'('.$v.
') AS '.$k;
306 unset($query[
'field_as']);
308 if ($query[
'proposed_order'])
310 $query[
'order'] =
'FIELD('.$query[
'proposed_order'][
'field'].
','.implode(
',', $query[
'proposed_order'][
'values']).
')';
315 foreach ($query[
'union'] as $union)
317 $union = array_merge($query, $union);
318 $union[
'where'] = $query[
'where']?
'('.$query[
'where'].
') AND ('.$union[
'where'].
')':$union[
'where'];
319 $union[
'join'] = $query[
'join']?array_merge_recursive($query[
'join'], $union[
'join']):$union[
'join'];
320 $unions[] =
'('.$this->_selectString($union).
')';
322 $s = implode(
' UNION ', $unions).($query[
'order']?
' order by'.preg_replace(
'/([, ])[^, .]+?\./',
'$1',
' '.$query[
'order']):
'');
324 $s = $this->_selectString($query);
328 $limit = explode(
',', $query[
'limit']);
329 $s.=
' LIMIT '.$limit[0].(sizeof($limit)>1?
','.$limit[1]:
'');
333 $this->currentQuery = $s;
334 $this->currentBind = $query[
'bind'];
335 $this->_stmt = $this->_db->prepare($s);
336 if ($this->_stmt->execute($query[
'bind']) ===
false) {
338 throw new Ego_Sql_Exception(implode(
' ', $this->_stmt->errorInfo()), (
int) $this->_stmt->errorCode());
342 return $this->query($s);
405 !(
bool)$query[
'limit'] || (
bool)$query[
'order'],
406 'You have to set an order to use limit! Otherwise databases like MS SQL don`t work.'.
407 print_r($query,
true));
409 if ($cache && $this->_cacheInit($query, $cache))
413 $GLOBALS[
'stats'][
'db_select']++;
414 if ($GLOBALS[
'egotec_conf'][
'db'][
'log_select'])
416 $start = microtime(
true);
418 $return = $this->_select($query);
419 if ($GLOBALS[
'egotec_conf'][
'db'][
'log_select'] || $query[
'log'])
421 $time = microtime(
true)-$start;
422 if ($time>$GLOBALS[
'egotec_conf'][
'db'][
'log_select_timeout'] || $query[
'log'])
424 $log =
'=== '.date(
'Y-m-d H:i:s').
' '.$_SERVER[
'REQUEST_URI'].
' '.$time.
"\n".$this->currentQuery.
"\n".print_r($query,
true);
425 if ($GLOBALS[
'egotec_conf'][
'db'][
'profiling'] || $query[
'profile'])
427 $log.= $this->getQueryInfo();
429 if ($GLOBALS[
'egotec_conf'][
'db'][
'log_select']==2)
431 $log.=
"\n".get_backtrace();
465 function delete($query)
467 assert($query[
'table']||$query[
'from']);
469 .($query[
'fields']?$query[
'fields'].
' ':
'')
471 .($query[
'table']?$query[
'table']:$query[
'from'])
472 .($query[
'inner']?
' INNER JOIN '.(is_array($query[
'inner'])?
473 implode(
' INNER JOIN ', $query[
'inner']):$query[
'inner']):
'')
474 .($query[
'join']?
' LEFT JOIN '.(is_array($query[
'join'])?
475 implode(
' LEFT JOIN ', $query[
'join']):$query[
'join']):
'')
476 .($query[
'where']?
' WHERE '.$query[
'where']:
'');
479 $this->currentQuery = $s;
480 $this->currentBind = $query[
'bind'];
481 $this->_stmt = $this->_db->prepare($s);
482 if ($this->_stmt->execute($query[
'bind']) ===
false) {
484 throw new Ego_Sql_Exception(implode(
' ', $this->_stmt->errorInfo()), (
int) $this->_stmt->errorCode());
488 return $this->query($s);
530 if (isset($query[
'key']))
532 $set = array_combine($query[
'key'], $query[
'val']);
533 unset($query[
'val']);
534 } elseif (isset($query[
'set'])) {
535 $query[
'key'] = array_keys($query[
'set']);
536 $set = $query[
'set'];
537 unset($query[
'set']);
539 if (is_array($query[
'key'])) {
540 foreach ($query[
'key'] as $k) {
541 $field[] = $this->escapeChar . $k . $this->escapeChar .
'=:' . $k;
544 if (isset($query[
'set_f']))
546 foreach ($query[
'set_f'] as $k => $v)
548 $field[] = $this->escapeChar.$k.$this->escapeChar.
'='.$v;
551 $s =
'UPDATE '.($query[
'ignore']?
'IGNORE ':
'').
553 ' SET '.implode(
',', $field).
554 ($query[
'where']?
' WHERE '.$query[
'where']:
'');
555 $this->currentQuery = array(
'query' => $s);
556 $this->_stmt = $this->_db->prepare($s);
557 $this->currentQuery[
'set'] = $set;
558 if ($query[
'bind']) {
559 $set = array_merge($set, $query[
'bind']);
561 if ($this->_stmt ===
false) {
563 throw new Ego_Sql_Exception(implode(
' ', $this->_db->errorInfo()), (
int) $this->_db->errorCode());
565 if ($this->_stmt->execute($set) ===
false) {
567 throw new Ego_Sql_Exception(implode(
' ', $this->_stmt->errorInfo()), (
int) $this->_stmt->errorCode());
602 if (isset($query[
'key']))
604 $set = array_combine($query[
'key'], $query[
'val']);
605 unset($query[
'val']);
607 $query[
'key'] = array_keys($query[
'set']);
608 $set = $query[
'set'];
609 unset($query[
'set']);
611 $this->currentQuery = $query;
612 $insert_table = $query[
'table'].
'-'.
sizeof($query[
'key']).
'-'.$query[
'replace'];
613 if ($this->_insertTable != $insert_table)
615 $s = ($query[
'replace']?
'REPLACE':
'INSERT').
" INTO $query[table]".
616 " (".$this->escapeChar.implode($this->escapeChar.
','.$this->escapeChar, $query[
'key']).$this->escapeChar.
")".
617 " VALUES (:".implode(
',:', $query[
'key']).
")";
618 $this->_insertstmt = $this->_db->prepare($s);
619 $this->_insertTable = $insert_table;
621 $this->currentQuery[
'set'] = $set;
622 if ($this->_insertstmt ===
false) {
624 throw new Ego_Sql_Exception(implode(
' ', $this->_db->errorInfo()), (
int) $this->_db->errorCode());
626 if ($this->_insertstmt->execute($set) ===
false) {
628 throw new Ego_Sql_Exception(implode(
' ', $this->_insertstmt->errorInfo()), (
int) $this->_insertstmt->errorCode());
630 return $this->_insertstmt;
655 assert(!$query[
'replace'] || $query[
'primary']);
656 return $this->insert(array_merge($query, array(
'replace' =>
true)));
671 abstract function showColumns($table);
680 return $this->Record;
690 return $this->nextRecord();
700 return $this->_currentRow;
708 return isset($this->Record);
720 $this->_currentRow = -1;
721 $this->_cacheIndex = -1;
725 return $this->next();
736 return $this->numRecords();
749 if (!isset($GLOBALS[
'egotec_conf'][
'no_query_cache']) || $GLOBALS[
'egotec_conf'][
'no_query_cache']!=1)
751 $query_hash = $query[
'hash']?$query[
'hash']:md5(serialize($query));
752 $this->_cacheRecords = $cache->get($query_hash);
753 if ($this->_cacheRecords === null)
755 $this->select($query);
756 $this->_cacheRecords = array();
757 while ($this->nextRecord())
759 $this->_cacheRecords[] = $this->Record;
761 $cache->set($query_hash, $this->_cacheRecords);
763 $GLOBALS[
'stats'][
'db_cache']++;
765 $this->_cached =
true;
766 $this->_cacheIndex = -1;
767 $this->_currentRow = -1;
791 $db->select(array(
'table' => $table));
792 while ($db->nextRecord())
794 $content[] = $db->Record;
814 function import($table, $content, $primary=array(), $c_date_fieldname=
'', $c_date_value=
'')
816 if (!is_array($content))
822 $primary = $this->getPrimary($table);
827 $db->select(array(
'table' => $table));
828 $old_content = array();
829 while ($db->nextRecord())
831 $old_content[md5(serialize($db->Record))] = $db->Record;
834 foreach ($content as $record)
836 $md5 = md5(serialize($record));
837 if ($old_content[$md5])
840 unset($old_content[$md5]);
842 if (
sizeof($primary)==1)
844 $keys = array_keys($primary);
845 $insert[$record[$keys[0]]] = $record;
851 foreach ($old_content as $record)
853 if (!$c_date_fieldname || $record[$c_date_fieldname]<$c_date_value)
858 foreach ($record as $key=>$val)
864 if ($primary[$key]==
'string')
866 $where[] = $key.
'=\''.$val.
'\'';
868 $where[] = $key.
'='.$val;
872 if (is_numeric($val))
874 $where[] = $key.
'='.$val;
876 $where[] = $key.
'=\''.$val.
'\'';
880 $where = implode(
' AND ', $where);
886 $record[$c_date_fieldname] = date(
'Y-m-d H:i:s');
890 'primary' => $primary
892 if (
sizeof($primary)==1)
894 $keys = array_keys($primary);
895 unset($insert[$record[$keys[0]]]);
899 foreach ($insert as $record)
902 $db->insert(array(
'set' => $record,
'table' => $table));
903 }
catch (Exception $e)
905 egotec_error_log($e->getMessage());
937 abstract function createTable($table, $struct, $drop_flag=
true);
963 abstract function alterTable($table, $struct);
979 $this->query(
'DROP TABLE '.$table);
1047 $file = $GLOBALS[
'egotec_conf'][
'var_dir'].
'lib/db.php';
1049 require_once($file);
1050 $func =
'db_'.$action;
1051 if (function_exists($func)) {
1055 egotec_error_log(
'Connection failed');
1065 public abstract function getPrimary($table);
1087 $this->query(
"SHOW TABLES FROM ".$GLOBALS[
'egotec_conf'][
'db'][
'database'].
" LIKE '$like%'");
1089 $this->query(
"SHOW TABLES FROM ".$GLOBALS[
'egotec_conf'][
'db'][
'database']);
1092 $all_table = array();
1095 while($table = $this->nextRecord()) {
1096 $all_table[$count++] = array_pop($this->Record);
1101 public abstract function getVersion();
query($query, $appendCurrent=false)
_cacheInit($query, $cache)
__construct($query=array(), $cache=false)
static file_exists($file)
select($query, $cache=false)
static log($file, $message)