* @package Mammut\DB\Dialect */ class Mysql extends Sql92 implements iDialect { /** * * @var \mysqli \PDO */ protected $con = null; const MAX_ROWS = 18446744073709551615; public function __construct($connection = null) { $this->con = $connection; } public function getName() { return DB::DIALECT_MYSQL; } public function isOffsetSupported() { return true; } public function getDdl() { if(!is_null($this->ddlInstance)) return $this->ddlInstance; $this->ddlInstance = new \Mammut\DB\Sql\Dialect\Ddl\MysqlDdl($this->con); return $this->ddlInstance; } public function quoteIdent($identifier) { if(is_array($identifier)) { $identifier = str_replace('`', '``', $identifier); $identifier = implode('`.`', $identifier); return '`' . $identifier . '`'; } return '`' . str_replace('`', '``', $identifier) . '`'; } public function quoteIdentInFragment($identifier, array $safeWords = array()) { $parts = preg_split('#([^0-9,a-z,A-Z$_])#', $identifier, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); if ($safeWords) { $safeWords = array_flip($safeWords); $safeWords = array_change_key_case($safeWords, CASE_LOWER); } foreach ($parts as $i => $part) { if ($safeWords && isset($safeWords[strtolower($part)])) { continue; } switch ($part) { case ' ': case '.': case '*': case 'AS': case 'As': case 'aS': case 'as': break; default: $parts[$i] = '`' . str_replace('`', '``', $part) . '`'; } } return implode('', $parts); } public function quoteValue($value) { if(is_int($value)) return $value; if(is_null($value)) return 'NULL'; if($this->con instanceof \mysqli) return '\'' . $this->con->real_escape_string($value) . '\''; if($this->con instanceof \PDO) return $this->con->quote($value); return '\'' . addcslashes($value, "\x00\n\r\\'\"\x1a") . '\''; } public function escapeString($string) { if(is_int($string)) return $string; if(is_null($string)) return 'NULL'; if($this->con instanceof \mysqli) return $this->con->real_escape_string($string); if($this->con instanceof \PDO) { $st = $this->con->quote($string); return substr($st, 1, -1); } return addcslashes($value, "\x00\n\r\\'\"\x1a"); } public function getSymbol($type) { switch($type) { case self::SYMB_QUOTE_VALUE: return '\''; case self::SYMB_QUOTE_IDENT: return '`'; case self::SYMB_IDENT_SEP: return '.'; } return false; } public function getSelectSQL(array $param = array()) { $sql = 'SELECT'; $this->handleQuantifier($sql, $param); $this->handleColumns($sql, $param); if(isset($param[Select::TABLE])) $this->handleTable($sql, $param); $this->handleJoins($sql, $param); if(isset($param[Select::WHERE])) $sql .= ' WHERE ' . $this->getExpressionSQL($param[Select::WHERE]->getContent()); $this->handleGroup($sql, $param); if(isset($param[Select::HAVING])) $sql .= ' HAVING ' . $this->getExpressionSQL($param[Select::HAVING]->getContent()); $this->handleCombine($sql, $param); $this->handleOrder($sql, $param); if(isset($param[Select::OFFSET])) { $limit = isset($param[Select::LIMIT]) ? $param[Select::LIMIT] : self::MAX_ROWS; $sql .= ' LIMIT ' . $param[Select::OFFSET].','.$limit; } elseif(isset($param[Select::LIMIT])) $sql .= ' LIMIT ' . $param[Select::LIMIT]; return $sql; } public function getTruncateSQL($table) { $table = $this->quoteIdent($table); return "TRUNCATE TABLE {$table}"; } public function getExpressionSQL($param, $hint = NULL) { if($param instanceof Parameter) { $sql = ''; $this->handleParameter($sql, []); return $sql; } return parent::getExpressionSQL($param, $hint); } public function getFunctionSQL(SQLFunction $function) { switch($function->getFunction()) { case SQLFunction::F_RANDOM: if(!empty($function->param)) throw new \InvalidArgumentException('No parameter allowed for RANDOM'); return 'RAND()'; } return parent::getFunctionSQL($function); } public function getNativeType($type) { switch($type) { case Types::TYPE_BOOLEAN: return 'BOOLEAN'; case Types::TYPE_TINY: return 'TINYINT'; case Types::TYPE_SHORT: return 'SMALLINT'; case Types::TYPE_INT: return 'INTEGER'; case Types::TYPE_LONG: return 'BIGINT'; case Types::TYPE_FLOAT: return 'REAL'; case Types::TYPE_DOUBLE: return 'DOUBLE'; case Types::TYPE_DECIMAL: return 'DECIMAL'; case Types::TYPE_CHAR: return 'CHAR'; case Types::TYPE_VCHAR: return 'VARCHAR'; case Types::TYPE_TEXT: return 'LONGTEXT'; case Types::TYPE_BINARY: return 'VARBINARY'; case Types::TYPE_BLOB: return 'LONGBLOB'; case Types::TYPE_DATE: return 'DATE'; case Types::TYPE_DATETIME: return 'DATETIME'; case Types::TYPE_UTS: return 'INT'; case Types::TYPE_ENUM: return 'ENUM'; } return $type; } }