Merge branch 'noglob' of https://gitlab.edu.yar.ru/composer/PHP_Library into noglob
This commit is contained in:
commit
7163158baf
1 changed files with 209 additions and 200 deletions
|
|
@ -2,226 +2,235 @@
|
|||
|
||||
namespace ctiso\Database;
|
||||
use ctiso\Database,
|
||||
ctiso\Tools\SQLStatementExtractor,
|
||||
ctiso\Path,
|
||||
Exception;
|
||||
ctiso\Tools\SQLStatementExtractor,
|
||||
ctiso\Path,
|
||||
Exception;
|
||||
|
||||
class Manager
|
||||
{
|
||||
public $db/*: Database*/;
|
||||
public $db/*: Database*/;
|
||||
|
||||
function __construct(Database $db) {
|
||||
$this->db = $db;
|
||||
}
|
||||
function __construct(Database $db) {
|
||||
$this->db = $db;
|
||||
}
|
||||
|
||||
public function ExecuteAction($action/*: array*/, $db_file = "") {
|
||||
switch($action["type"]) {
|
||||
case "dropTable":
|
||||
$this->DropTableQuery($action["table_name"], true);
|
||||
break;
|
||||
case "createTable":
|
||||
$constraints = isset($action["constraints"]) ? $action["constraints"] : NULL;
|
||||
$this->CreateTableQuery($action["table_name"], $action["fields"], $constraints);
|
||||
break;
|
||||
case "addColumn":
|
||||
$this->AddColumn($action["table_name"], $action["column_name"], $action["field"]);
|
||||
break;
|
||||
case "insert":
|
||||
$this->db->insertQuery($action["table_name"], $action["values"]);
|
||||
break;
|
||||
case "alterReference":
|
||||
$this->AlterReference($action["table"], $action["column"], $action["refTable"], $action["refColumn"]);
|
||||
break;
|
||||
case "renameColumn":
|
||||
$this->RenameColumn($action["table"], $action["old_name"], $action["new_name"]);
|
||||
break;
|
||||
case "executeFile":
|
||||
if ($this->db->isPostgres() && isset($action["pgsql"])) {
|
||||
$file = $action["pgsql"];
|
||||
} else {
|
||||
$file = $action["source"];
|
||||
}
|
||||
public function ExecuteAction($action/*: array*/, $db_file = "") {
|
||||
switch($action["type"]) {
|
||||
case "dropTable":
|
||||
$this->DropTableQuery($action["table_name"], true);
|
||||
break;
|
||||
case "createTable":
|
||||
$constraints = isset($action["constraints"]) ? $action["constraints"] : NULL;
|
||||
$this->CreateTableQuery($action["table_name"], $action["fields"], $constraints);
|
||||
break;
|
||||
case "addColumn":
|
||||
$this->AddColumn($action["table_name"], $action["column_name"], $action["field"]);
|
||||
break;
|
||||
case "insert":
|
||||
$this->db->insertQuery($action["table_name"], $action["values"]);
|
||||
break;
|
||||
case "alterReference":
|
||||
$this->AlterReference($action["table"], $action["column"], $action["refTable"], $action["refColumn"]);
|
||||
break;
|
||||
case "renameColumn":
|
||||
$this->RenameColumn($action["table"], $action["old_name"], $action["new_name"]);
|
||||
break;
|
||||
case "createView":
|
||||
$this->recreateView($action["view"], $action["select"]);
|
||||
break;
|
||||
case "executeFile":
|
||||
if ($this->db->isPostgres() && isset($action["pgsql"])) {
|
||||
$file = $action["pgsql"];
|
||||
} else {
|
||||
$file = $action["source"];
|
||||
}
|
||||
|
||||
$stmtList = SQLStatementExtractor::extractFile(Path::join(dirname($db_file), $file));
|
||||
foreach($stmtList as $stmt) {
|
||||
$this->db->executeQuery($stmt);
|
||||
}
|
||||
$stmtList = SQLStatementExtractor::extractFile(Path::join(dirname($db_file), $file));
|
||||
foreach($stmtList as $stmt) {
|
||||
$this->db->executeQuery($stmt);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
throw new Exception("unknown action ". $action["type"] . PHP_EOL);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new Exception("unknown action ". $action["type"] . PHP_EOL);
|
||||
}
|
||||
}
|
||||
|
||||
public function DropTableQuery($table, $cascade=false) {
|
||||
$statement = "DROP TABLE IF EXISTS ".$table;
|
||||
if ($this->db->isPostgres()&&$cascade) {
|
||||
$statement = $statement." CASCADE";
|
||||
}
|
||||
$this->db->query($statement);
|
||||
}
|
||||
//Дропает и создаёт SQL VIEW
|
||||
public function recreateView($viewName, $selectStatement) {
|
||||
$this->db->query("DROP VIEW ".$viewName);
|
||||
$this->db->query("CREATE VIEW ".$viewName." AS ".$selectStatement);
|
||||
}
|
||||
|
||||
public function AlterReference($table,$column,$refTable,$refColumn) {
|
||||
$this->db->query("ALTER TABLE ".$table." ADD CONSTRAINT ".$table."_".$column."fk"." FOREIGN KEY (".$column.") REFERENCES ".$refTable." (".$refColumn.")");
|
||||
}
|
||||
public function DropTableQuery($table, $cascade=false) {
|
||||
$statement = "DROP TABLE IF EXISTS ".$table;
|
||||
if ($this->db->isPostgres()&&$cascade) {
|
||||
$statement = $statement." CASCADE";
|
||||
}
|
||||
$this->db->query($statement);
|
||||
}
|
||||
|
||||
//Извлечение информации о полях таблицы
|
||||
public function TableInfo($table) {
|
||||
$pg = $this->db->isPostgres();
|
||||
if ($pg) {
|
||||
throw new Exception("Not implemented for postgres");
|
||||
} else {
|
||||
$results = $this->db->fetchAllArray("PRAGMA table_info(".$table.");");
|
||||
if (empty($results)) {
|
||||
return null;
|
||||
}
|
||||
$fields = [];
|
||||
foreach ($results as $result) {
|
||||
$fields[$result["name"]] = [
|
||||
"type"=> $result["type"],
|
||||
"not_null"=> boolval($result["notnull"]),
|
||||
"constraint"=> ((boolean) $result["pk"]) ? "PRIMARY KEY" : null
|
||||
];
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
}
|
||||
public function AlterReference($table,$column,$refTable,$refColumn) {
|
||||
$this->db->query("ALTER TABLE ".$table." ADD CONSTRAINT ".$table."_".$column."fk"." FOREIGN KEY (".$column.") REFERENCES ".$refTable." (".$refColumn.")");
|
||||
}
|
||||
|
||||
public function RenameColumn($table, $old_name, $new_name) {
|
||||
$pg = $this->db->isPostgres();
|
||||
if ($pg) {
|
||||
$this->db->query("ALTER TABLE ".$table." RENAME COLUMN ".$old_name." TO ".$new_name);
|
||||
} else {
|
||||
$tmp_table = "tmp_" . $table;
|
||||
$this->DropTableQuery($tmp_table);
|
||||
$table_info = $this->TableInfo($table);
|
||||
//Извлечение информации о полях таблицы
|
||||
public function TableInfo($table) {
|
||||
$pg = $this->db->isPostgres();
|
||||
if ($pg) {
|
||||
throw new Exception("Not implemented for postgres");
|
||||
} else {
|
||||
$results = $this->db->fetchAllArray("PRAGMA table_info(".$table.");");
|
||||
if (empty($results)) {
|
||||
return null;
|
||||
}
|
||||
$fields = [];
|
||||
foreach ($results as $result) {
|
||||
$fields[$result["name"]] = [
|
||||
"type"=> $result["type"],
|
||||
"not_null"=> boolval($result["notnull"]),
|
||||
"constraint"=> ((boolean) $result["pk"]) ? "PRIMARY KEY" : null
|
||||
];
|
||||
}
|
||||
return $fields;
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($table_info[$new_name])) {
|
||||
return;
|
||||
}
|
||||
public function RenameColumn($table, $old_name, $new_name) {
|
||||
$pg = $this->db->isPostgres();
|
||||
if ($pg) {
|
||||
$this->db->query("ALTER TABLE ".$table." RENAME COLUMN ".$old_name." TO ".$new_name);
|
||||
} else {
|
||||
$tmp_table = "tmp_" . $table;
|
||||
$this->DropTableQuery($tmp_table);
|
||||
$table_info = $this->TableInfo($table);
|
||||
|
||||
$data/*: array*/ = $this->DumpTable($table);
|
||||
if (isset($table_info[$new_name])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->db->query("ALTER TABLE ".$table." RENAME TO ".$tmp_table.";");
|
||||
$table_info[$new_name] = $table_info[$old_name];
|
||||
unset($table_info[$old_name]);
|
||||
$this->CreateTableQuery($table,$table_info,null);
|
||||
$data/*: array*/ = $this->DumpTable($table);
|
||||
|
||||
foreach ($data as $row) {
|
||||
$values = $row['values'];
|
||||
$values[$new_name] = $values[$old_name];
|
||||
unset($values[$old_name]);
|
||||
$this->db->insertQuery($table, $values);
|
||||
}
|
||||
$this->DropTableQuery($tmp_table);
|
||||
}
|
||||
}
|
||||
$this->db->query("ALTER TABLE ".$table." RENAME TO ".$tmp_table.";");
|
||||
$table_info[$new_name] = $table_info[$old_name];
|
||||
unset($table_info[$old_name]);
|
||||
$this->CreateTableQuery($table,$table_info,null);
|
||||
|
||||
//Обновление ключа serial после ручной вставки
|
||||
public function UpdateSerial($table,$column) {
|
||||
$this->db->query("SELECT setval(pg_get_serial_sequence('".$table."', '".$column."'), coalesce(max(".$column."),0) + 1, false) FROM ".$table);
|
||||
}
|
||||
foreach ($data as $row) {
|
||||
$values = $row['values'];
|
||||
$values[$new_name] = $values[$old_name];
|
||||
unset($values[$old_name]);
|
||||
$this->db->insertQuery($table, $values);
|
||||
}
|
||||
$this->DropTableQuery($tmp_table);
|
||||
}
|
||||
}
|
||||
|
||||
public function Column_Definition($name,$data,$pg){
|
||||
$constraint = isset($data['constraint'])?" ".$data['constraint']:"";
|
||||
$references = "";
|
||||
if (isset($data['references'])) {
|
||||
$references = " REFERENCES ".$data['references'];
|
||||
}
|
||||
if (isset($data["not_null"]) && $data["not_null"])
|
||||
$constraint .=" NOT NULL";
|
||||
$type = $data['type'];
|
||||
if (!$pg) {
|
||||
if (strtolower($type)=="serial")
|
||||
$type = "integer";
|
||||
//if (strtolower($type)=="boolean")
|
||||
// $type = "integer";
|
||||
}
|
||||
return $name." ".$type.$references.$constraint;
|
||||
}
|
||||
//Обновление ключа serial после ручной вставки
|
||||
public function UpdateSerial($table,$column) {
|
||||
$this->db->query("SELECT setval(pg_get_serial_sequence('".$table."', '".$column."'), coalesce(max(".$column."),0) + 1, false) FROM ".$table);
|
||||
}
|
||||
|
||||
public function AddColumn($table_name,$column_name,$field){
|
||||
$pg = $this->db->isPostgres();
|
||||
$q = "ALTER TABLE ".$table_name." ADD COLUMN ".
|
||||
$this->Column_Definition($column_name, $field, $pg);
|
||||
$this->db->query($q);
|
||||
}
|
||||
public function Column_Definition($name,$data,$pg){
|
||||
$constraint = isset($data['constraint'])?" ".$data['constraint']:"";
|
||||
$references = "";
|
||||
if (isset($data['references'])) {
|
||||
$references = " REFERENCES ".$data['references'];
|
||||
}
|
||||
if (isset($data["not_null"]) && $data["not_null"])
|
||||
$constraint .=" NOT NULL";
|
||||
$type = $data['type'];
|
||||
if (!$pg) {
|
||||
if (strtolower($type)=="serial")
|
||||
$type = "integer";
|
||||
//if (strtolower($type)=="boolean")
|
||||
// $type = "integer";
|
||||
}
|
||||
return $name." ".$type.$references.$constraint;
|
||||
}
|
||||
|
||||
function getConstraintDef($c/*: array*/) {
|
||||
if ($c['type'] == 'unique') {
|
||||
return "UNIQUE(" . implode(", ", $c['fields']) . ")";
|
||||
}
|
||||
return "";
|
||||
public function AddColumn($table_name,$column_name,$field){
|
||||
$pg = $this->db->isPostgres();
|
||||
$q = "ALTER TABLE ".$table_name." ADD COLUMN ".
|
||||
$this->Column_Definition($column_name, $field, $pg);
|
||||
$this->db->query($q);
|
||||
}
|
||||
|
||||
function getConstraintDef($c/*: array*/) {
|
||||
if ($c['type'] == 'unique') {
|
||||
return "UNIQUE(" . implode(", ", $c['fields']) . ")";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
//CreateTableQuery('users',['id'=>['type'=>'integer','constraint'=>'PRIMARY KEY']])
|
||||
public function CreateTableQuery($table, $fields, $constraints) {
|
||||
$pg = $this->db->isPostgres();
|
||||
if ($constraints) {
|
||||
if (is_array($constraints)) {
|
||||
$constraints = $this->getConstraintDef($constraints);
|
||||
}
|
||||
$constraints = ", " . $constraints;
|
||||
}
|
||||
|
||||
//CreateTableQuery('users',['id'=>['type'=>'integer','constraint'=>'PRIMARY KEY']])
|
||||
public function CreateTableQuery($table, $fields, $constraints) {
|
||||
$pg = $this->db->isPostgres();
|
||||
if ($constraints) {
|
||||
if (is_array($constraints)) {
|
||||
$constraints = $this->getConstraintDef($constraints);
|
||||
$statement = "CREATE TABLE $table (" . implode(",",
|
||||
array_map(function($name,$data) use ($pg) {
|
||||
return $this->Column_Definition($name,$data,$pg);
|
||||
}, array_keys($fields), array_values($fields))
|
||||
) . " " . $constraints . ")";
|
||||
$this->db->query($statement);
|
||||
}
|
||||
|
||||
public function DumpTable($table_name) {
|
||||
$pg = $this->db->isPostgres();
|
||||
|
||||
$result/*: array*/ = array();
|
||||
$data/*: array*/ = $this->db->fetchAllArray("SELECT * FROM ".$table_name.";");
|
||||
|
||||
if (!$pg) {
|
||||
$table_fields = $this->TableInfo($table_name);
|
||||
foreach ($table_fields as $name => $value) {
|
||||
$type = strtolower($value['type']);
|
||||
if ($type == "boolean") {
|
||||
foreach ($data as &$row) {
|
||||
$row/*: array*/ = $row;
|
||||
if (isset($row[$name])) {
|
||||
$row[$name] = boolval($row[$name]);
|
||||
}
|
||||
$constraints = ", " . $constraints;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($data as $r) {
|
||||
$result[] = array(
|
||||
"type" => "insert",
|
||||
"table_name" => $table_name,
|
||||
"values" => $r
|
||||
);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
$statement = "CREATE TABLE $table (" . implode(",",
|
||||
array_map(function($name,$data) use ($pg) {
|
||||
return $this->Column_Definition($name,$data,$pg);
|
||||
}, array_keys($fields), array_values($fields))
|
||||
) . " " . $constraints . ")";
|
||||
$this->db->query($statement);
|
||||
}
|
||||
public function GetAllTableNames() {
|
||||
$result = [];
|
||||
if ($this->db->isPostgres()) {
|
||||
$query = "SELECT table_name as name FROM information_schema.tables WHERE table_schema='public'";
|
||||
} else {
|
||||
$query = "SELECT * FROM sqlite_master WHERE type='table'";
|
||||
}
|
||||
$tables = $this->db->fetchAllArray($query);
|
||||
foreach ($tables as $table) {
|
||||
$result[] = $table['name'];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function DumpTable($table_name) {
|
||||
$pg = $this->db->isPostgres();
|
||||
|
||||
$result/*: array*/ = array();
|
||||
$data/*: array*/ = $this->db->fetchAllArray("SELECT * FROM ".$table_name.";");
|
||||
|
||||
if (!$pg) {
|
||||
$table_fields = $this->TableInfo($table_name);
|
||||
foreach ($table_fields as $name => $value) {
|
||||
$type = strtolower($value['type']);
|
||||
if ($type == "boolean") {
|
||||
foreach ($data as &$row) {
|
||||
$row/*: array*/ = $row;
|
||||
if (isset($row[$name])) {
|
||||
$row[$name] = boolval($row[$name]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach ($data as $r) {
|
||||
$result[] = array(
|
||||
"type" => "insert",
|
||||
"table_name" => $table_name,
|
||||
"values" => $r
|
||||
);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function GetAllTableNames() {
|
||||
$result = [];
|
||||
if ($this->db->isPostgres()) {
|
||||
$query = "SELECT table_name as name FROM information_schema.tables WHERE table_schema='public'";
|
||||
} else {
|
||||
$query = "SELECT * FROM sqlite_master WHERE type='table'";
|
||||
}
|
||||
$tables = $this->db->fetchAllArray($query);
|
||||
foreach ($tables as $table) {
|
||||
$result[] = $table['name'];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function DumpInserts() {
|
||||
$table_names = $this->GetAllTableNames();
|
||||
$result = array();
|
||||
foreach ($table_names as $table_name) {
|
||||
$result = array_merge($result, $this->DumpTable($table_name));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function DumpInserts() {
|
||||
$table_names = $this->GetAllTableNames();
|
||||
$result = array();
|
||||
foreach ($table_names as $table_name) {
|
||||
$result = array_merge($result, $this->DumpTable($table_name));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue