commit 31d27904d283f60abbf8a4893d4692f5d084d928 Author: Vitaliy Filippov Date: Sun Sep 30 22:44:34 2012 +0000 OO mysql diff --git a/DatabaseMysql.php b/DatabaseMysql.php new file mode 100644 index 0000000..d19366c --- /dev/null +++ b/DatabaseMysql.php @@ -0,0 +1,394 @@ +link = new mysqli($host, $username, $password, $dbname, $port, $socket); + } + elseif ($port !== NULL) + { + $this->link = new mysqli($host, $username, $password, $dbname, $port); + } + else + { + $this->link = new mysqli($host, $username, $password, $dbname); + } + $this->dbName = $dbname; + } + + function getDBName() + { + return $this->dbName; + } + + function quoteId($name) + { + return "`".str_replace("`", "``", $name)."`"; + } + + function quote($value) + { + if ($value === NULL) + return "NULL"; + return "'" . $this->link->real_escape_string($s) . "'"; + } + + function query($sql, $fetchMode = MYSQLI_STORE_RESULT) + { + $this->queryCount++; + if ($this->queryLogFile) + { + file_put_contents($this->queryLogFile, date("[Y-m-d H:i:s] ").$sql."\n", FILE_APPEND); + } + return $this->link->query($sql, $fetchMode); + } + + function where_builder($where) + { + if (!is_array($where)) + return $where; + $wh = array(); + foreach ($where as $k => $v) + { + if (ctype_digit($k)) + $wh[] = $v; + elseif (is_array($v)) + { + if (!$v) + { + throw new DatabaseException(E_DB_EMPTY_IN, "Error: empty array for '$k IN (...)', don't know what to do"); + } + else + { + if (is_array($v[0])) + foreach ($v as &$l) + $l = "(" . implode(",", array_map(array($this, 'quote'), $l)) . ")"; + else + $v = array_map(array($this, 'quote'), $v); + $wh[] = "$k IN (" . implode(",", $v) . ")"; + } + } + elseif ($v !== NULL) + $wh[] = "$k=".$this->quote($v); + else + $wh[] = "$k IS NULL"; + } + if (!$wh) + $where = '1'; + else + $where = '(' . join(') AND (', $wh) . ')'; + return $where; + } + + function select_builder($tables, $fields, $where, $options = NULL) + { + if (!$options) + $options = array(); + else + { + foreach ($options as $k => $v) + if (ctype_digit($k)) + $options[$v] = true; + } + if (is_array($fields)) + $fields = join(',', $fields); + $where = $this->where_builder($where); + $tables = $this->tables_builder($tables); + $sql = 'SELECT '; + if ($options['CALC_FOUND_ROWS'] || $options['SQL_CALC_FOUND_ROWS']) + $sql .= 'SQL_CALC_FOUND_ROWS '; + if ($options['NO_CACHE'] || $options['SQL_NO_CACHE']) + $sql .= 'SQL_NO_CACHE '; + elseif ($options['CACHE'] || $options['SQL_CACHE']) + $sql .= 'SQL_CACHE '; + $sql .= "$fields FROM $tables WHERE $where"; + if ($g = $options['GROUP BY']) + { + if (is_array($g)) + { + $g1 = array(); + foreach ($g as $k => $v) + { + if (ctype_digit($k)) + $g1[] = $v; + else + $g1[] = "$k $v"; + } + $g = join(',', $g1); + } + $sql .= " GROUP BY $g"; + } + if ($g = $options['ORDER BY']) + { + if (is_array($g)) + { + $g1 = array(); + foreach ($g as $k => $v) + { + if (ctype_digit($k)) + $g1[] = $v; + else + $g1[] = "$k $v"; + } + $g = join(',', $g1); + } + $sql .= " ORDER BY $g"; + } + if ($g = $options['LIMIT']) + { + if (is_array($g)) + $g = join(',', $g); + if ($g) + $sql .= " LIMIT $g"; + } + if ($options['FOR UPDATE']) + $sql .= ' FOR UPDATE'; + elseif ($options['LOCK IN SHARE MODE']) + $sql .= ' LOCK IN SHARE MODE'; + return $sql; + } + + function tables_builder($tables) + { + if (is_array($tables)) + { + $t = ''; + foreach ($tables as $k => $v) + { + if (!ctype_digit($k)) + { + if (is_array($v)) + { + $join = substr(strtolower($v[0]), 0, 4); + if ($join == 'righ') + $join = 'RIGHT'; + elseif ($join == 'left') + $join = 'LEFT'; + else /* if (!$join || $join == 'inne' || $join == 'join') */ + $join = 'INNER'; + if (is_array($v[1])) // nested join (left join (A join B on ...) on ...) + $table = '('.$this->tables_builder($v[1]).')'; + else + $table = (isset($this->tableNames[$v[1]]) ? $this->quoteId($this->tableNames[$v[1]]) : $v[1]) . ' ' . $k; + if ($t) + $t .= " $join JOIN $table ON ".$this->where_builder($v[2]); + else + $t = $table; + continue; + } + else + $v = (isset($this->tableNames[$v]) ? $this->quoteId($this->tableNames[$v]) : $v) . ' ' . $k; + } + else + $v = (isset($this->tableNames[$v]) ? $this->quoteId($this->tableNames[$v]).' '.$v : $v); + if ($t) + $t .= " INNER JOIN $v"; + else + $t = $v; + } + $tables = $t; + } + else + $tables = preg_replace_callback('/((?:,|JOIN)\s*`)([^`]+)/s', array($this, 'tables_builder_pregcb1'), $tables); + return $tables; + } + + function tables_builder_pregcb1($m) + { + $t = $this->tableNames[$m[2]]; + if (!$t) + $t = $m[2]; + return $m[1].$t; + } + + function select($tables, $fields = '*', $where = 1, $options = NULL, $format = 0) + { + if (!strcmp(intval($fields), "$fields")) + { + $sql = $tables; + $format = $fields; + } + else + $sql = $this->select_builder($tables, $fields, $where, $options); + if ($format & MS_RESULT) + return $this->query($sql, MYSQLI_USE_RESULT); + if ($format & MS_LIST) + $r = $this->get_rows($sql); + else + $r = $this->get_assocs($sql); + if (!$r) + $r = array(); + if ($format & MS_ROW) + { + if ($format & MS_COL) + { + if (!count($r)) + return NULL; + $r = $r[0]; + $k = array_keys($r); + $r = $r[$k[0]]; + } + else + $r = $r[0]; + } + elseif ($format & MS_COL) + { + foreach ($r as $i => $v) + { + if (!$k) + { + $k = array_keys($v); + $k = $k[0]; + } + $r[$i] = $v[$k]; + } + } + return $r; + } + + function found_rows() + { + return $this->select('SELECT FOUND_ROWS()', MS_VALUE); + } + + function delete($tables, $where, $options = NULL) + { + $tables = $this->tables_builder($tables); + $where = $this->where_builder($where); + $sql = "DELETE FROM $tables WHERE $where"; + if (is_array($options)) + { + if ($g = $options['LIMIT']) + { + if (is_array($g)) + $g = join(',', $g); + if ($g) + $sql .= " LIMIT $g"; + } + } + $this->query($sql); + return $this->link->affected_rows; + } + + function insert_builder($table, $rows, $onduplicatekey = false) + { + if ($this->tableNames[$table]) + $table = $this->tableNames[$table]; + $key = array_keys($rows[0]); + foreach ($rows as &$r) + { + $rs = array(); + foreach ($key as &$k) + $rs[] = $this->quote($r[$k]); + $r = "(".implode(",", $rs).")"; + } + foreach ($key as &$k) + if (strpos($k, '`') === false) + $k = $this->quoteId($k); + $sql = "INSERT INTO $table (".implode(",",$key).") VALUES ".implode(",",$rows); + if ($onduplicatekey) + { + foreach ($key as &$k) + $k = "$k=VALUES($k)"; + $sql .= " ON DUPLICATE KEY UPDATE ".implode(",",$key); + } + return $sql; + } + + function insert_row($table, $row) + { + $sql = $this->insert_builder($table, array($row)); + if ($this->query($sql)) + return $this->link->insert_id; + return NULL; + } + + function update($table, $rows, $where = NULL, $options = NULL) + { + if (!$rows) + return false; + if (is_null($where)) + { + if (!is_array($rows)) + return false; + if (!is_array($rows[0])) + $rows = array($rows); + $sql = $this->insert_builder($table, $rows, true); + } + else + { + $sql = array(); + if (!is_array($rows)) + $rows = array($rows); + foreach ($rows as $k => $v) + { + if (!ctype_digit($k)) + $sql[] = $k.'='.$this->quote($v); + else + $sql[] = $v; + } + $where = $this->where_builder($where); + $sql = 'UPDATE ' . $this->tables_builder($table) . ' SET ' . implode(', ', $sql) . ' WHERE ' . $where; + if (is_array($options)) + { + if ($g = $options['LIMIT']) + { + if (is_array($g)) + $g = join(',', $g); + if ($g) + $sql .= " LIMIT $g"; + } + } + } + if ($this->query($sql)) + return $this->link->affected_rows; + return false; + } + + function get_rows($sql) + { + $r = array(); + if ($res = $this->query($sql)) + { + while ($row = $res->fetch_row()) + $r[] = $row; + $res->free(); + } + return $r; + } + + function get_assocs($sql) + { + $r = array(); + if ($res = $this->query($sql)) + { + while ($row = $res->fetch_assoc()) + $r[] = $row; + $res->free(); + } + return $r; + } +}