setAttribute(\PDO::ATTR_AUTOCOMMIT, true); $pdo->setAttribute(\PDO::ATTR_CASE, \PDO::CASE_LOWER); $pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false); $pdo->setAttribute(\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC); $this->pdo = $pdo; } public function transaction(callable $fn){ $pdo = $this->pdo; if($pdo->inTransaction()){ throw new \Exception("Unable to start a new transaction"); } $transaction = new Transaction($this); if($fn($transaction) === false){ do{ $transaction->rollback(); }while($transaction->savepoint); $pdo->rollback(); }else{ $transaction->commit(); if($pdo->inTransaction()){ $pdo->commit(); } } unset($transaction); $pdo->setAttribute(\PDO::ATTR_AUTOCOMMIT, true); return $this; } public function table(string $name){ return new Table($this, $name); } public function prepare(string $statement, array $options = []){ $pdo = $this->pdo; if($pdo->getAttribute(\PDO::ATTR_DRIVER_NAME) == 'mysql'){ $options[\PDO::MYSQL_ATTR_USE_BUFFERED_QUERY] = true; } $query = $pdo->prepare($statement); if($query === false){ throw $this->getError(); } return $query; } public function exec(string $statement){ $query = $this->prepare($statement); $query->execute(); $count = 0; while($query->fetch() !== false){ $count++; } if($count === 0){ $query2 = $this->query("select ROW_COUNT()"); $count = $query2->fetchColumn(); $query2->closeCursor(); if($count === 0){ $count = $query->rowCount(); } } $query->closeCursor(); return $count; } public function query(string $statement, int $mode = null, ...$args){ $query = $this->prepare($statement); if(!is_null($mode)){ $query->setFetchMode($mode, ...$args); } $query->execute(); return $query; } public function quote($value, $type = \PDO::PARAM_STR){ if($type == \PDO::PARAM_INT){ return (int)$value; }elseif($type == \PDO::PARAM_BOOL){ return (bool)$value ? "b'1'" : "b'0'"; }elseif($type == \PDO::PARAM_NULL){ return 'null'; } return $this->pdo->quote((string)$value, $type); } public function beginTransaction(...$args){ return $this->pdo->beginTransaction(...$args); } public function commit(...$args){ return $this->pdo->commit(...$args); } public function rollback(...$args){ return $this->pdo->rollback(...$args); } public function setAttribute(...$args){ return $this->pdo->setAttribute(...$args); } public function getAttribute(...$args){ return $this->pdo->getAttribute(...$args); } public function lastInsertId(...$args){ $id = $this->pdo->lastInsertId(...$args); if($id === 0){ $query = $this->pdo->query("select LAST_INSERT_ID()"); $id = $query->fetchColumn(); $query->closeCursor(); } return $id; } public function getError(){ $error = $this->pdo->errorInfo(); return new \Exception($error[2], $error[1]); } public function stringFilter(array $filter = null){ $where = ''; if(!is_null($filter)){ $where = 'where '; foreach($filter as $name => $value){ if($value instanceof Filter){ $where .= "`{$name}` {$value} and"; }else{ if(is_integer($value)){ $type = \PDO::PARAM_INT; }elseif(is_bool($value)){ $type = \PDO::PARAM_BOOL; }elseif(is_null($value)){ $type = \PDO::PARAM_NULL; }else{ $type = \PDO::PARAM_STR; } $where .= "`{$name}` = {$this->quote($value, $type)} and"; } } $where = rtrim($where, ' and'); } return $where; } public function stringSet(array $data){ $sets = ''; foreach($data as $name => $value){ $sets .= "`{$name}` = {$this->quote($value)},"; } if(count($sets) > 0){ $sets = 'set '.rtrim($sets, ','); } return $sets; } public function stringColumn(string $name, array $column){ $default = ''; if(!is_null($column['default'])){ $value = $column['default']; if($value instanceof DefaultValue){ $default .= " DEFAULT {$value}"; }else{ if(is_integer($value)){ $type = \PDO::PARAM_INT; }elseif(is_bool($value)){ $type = \PDO::PARAM_BOOL; }else{ $type = \PDO::PARAM_STR; } $default .= " DEFAULT {$this->quote($value, $type)}"; } } $null = $column['null'] ? ' NULL' : ' NOT NULL'; $ai = $column['increment'] ? ' AUTO_INCREMENT' : ''; return "`{$name}` {$column['type']}{$null}{$default}{$ai}"; } public function stringIndex(string $name, array $idx){ if($idx['unique']){ return "constraint unique index {$name} (".implode(',', $idx['columns']).")"; }else{ return "index {$name} (".implode(',', $idx['columns']).")"; } } public function stringForeignKey(string $name, array $foreignKey){ $cols0 = ''; $cols1 = ''; foreach($foreignKey['columns'] as $row){ $cols0 .= "{$row[0]},"; $cols1 .= "{$row[1]},"; } $cols0 = rtrim($cols0, ','); $cols1 = rtrim($cols1, ','); return "constraint `{$name}` foreign key ({$cols0}) references `{$foreignKey['references']}` ({$cols1})"; } } ?>