From 12b888a674dff984ed51663110566c205753b52b Mon Sep 17 00:00:00 2001 From: Sasha Rybkin Date: Wed, 20 Nov 2024 15:55:20 +0300 Subject: [PATCH] init --- ActiveRecord.php | 36 ++++++++++++++++ Command.php | 61 +++++++++++++++++++++++++++ Connection.php | 41 ++++++++++++++++++ Query.php | 107 +++++++++++++++++++++++++++++++++++++++++++++++ composer.json | 21 ++++++++++ 5 files changed, 266 insertions(+) create mode 100644 ActiveRecord.php create mode 100644 Command.php create mode 100644 Connection.php create mode 100644 Query.php create mode 100644 composer.json diff --git a/ActiveRecord.php b/ActiveRecord.php new file mode 100644 index 0000000..6333aa0 --- /dev/null +++ b/ActiveRecord.php @@ -0,0 +1,36 @@ +attributeLabels()); + }*/ + + public function init() + { + } + +} diff --git a/Command.php b/Command.php new file mode 100644 index 0000000..5843f4a --- /dev/null +++ b/Command.php @@ -0,0 +1,61 @@ +errorInfo, $ex->errorInfo[1]) && $ex->errorInfo[1] >= 2000 && $ex->errorInfo[1] < 3000) + { + AmqpLoger::log('reconnectDB', $ex->errorInfo); + $this->db->close(); + $this->db->open(); + parent::prepare($forRead); + } + else + { + throw $ex; + } + } + } + + protected function internalExecute($rawSql) + { + try + { + parent::internalExecute($rawSql); + } + catch (Exception $ex) + { + if(isset($ex->errorInfo, $ex->errorInfo[1]) && $ex->errorInfo[1] >= 2000 && $ex->errorInfo[1] < 3000) + { + AmqpLoger::log('reconnectDB', $ex->errorInfo); + $this->db->close(); + $this->db->open(); + $this->pdoStatement = $this->db->pdo->prepare($rawSql); + parent::internalExecute($rawSql); + } + else + { + throw $ex; + } + } + } + +} diff --git a/Connection.php b/Connection.php new file mode 100644 index 0000000..130ba4b --- /dev/null +++ b/Connection.php @@ -0,0 +1,41 @@ + 'dominion\db\Command', // PostgreSQL + 'mysqli' => 'dominion\db\Command', // MySQL + 'mysql' => 'dominion\db\Command', // MySQL + 'sqlite' => 'yii\db\sqlite\Command', // sqlite 3 + 'sqlite2' => 'yii\db\sqlite\Command', // sqlite 2 + 'sqlsrv' => 'dominion\db\Command', // newer MSSQL driver on MS Windows hosts + 'oci' => 'yii\db\oci\Command', // Oracle driver + 'mssql' => 'dominion\db\Command', // older MSSQL driver on MS Windows hosts + 'dblib' => 'dominion\db\Command', // dblib drivers on GNU/Linux (and maybe other OSes) hosts + 'cubrid' => 'dominion\db\Command', // CUBRID + ]; + + /* public function open() + { + try + { + return parent::open(); + } + catch (\Exception $ex) + { + AmqpLoger::log('reconnectDB', $ex->errorInfo); + return parent::open(); + } + }*/ +} diff --git a/Query.php b/Query.php new file mode 100644 index 0000000..d9acd83 --- /dev/null +++ b/Query.php @@ -0,0 +1,107 @@ + ['name' => 'обновленное название 23', 'description' => 'обновленное описание 23'], + * 24 => ['name' => 'обновленное название 24', 'description' => 'обновленное описание 24'], + * ] + * Обновит поля name и description у полей с id=23 и id=24 одним запросом + * @return int Количество обновленных записей + */ + public function batchUpdate($table, $data) + { + $fields = []; + $columns = []; + $rows = []; + foreach ($data as $id => $values) + { + if (empty($columns)) + { + $fields = array_keys($values); + $columns = array_merge(['id'], $fields); + } + + $row = [$id]; + foreach ($values as $value) + { + $row[] = $value; + } + + $rows[] = $row; + } + + $sql = Yii::$app->db->getQueryBuilder()->batchInsert($table, $columns, $rows); + $update = []; + foreach ($fields as $field) + { + $field = Yii::$app->db->quoteColumnName($field); + $update[] = $field . ' = VALUES(' . $field . ')'; + } + + if (!empty($update)) + { + $sql .= ' ON DUPLICATE KEY UPDATE ' . implode(',', $update); + } + \Yii::beginProfile('batchUpdate_' . $table); + $result = Yii::$app->db->createCommand($sql)->execute(); + \Yii::endProfile('batchUpdate_' . $table); + return $result; + } + + /** + * Множественное добавление записей в таблицу + * @param string $table Название таблицы бд + * @param array $data Массив данных для добавления + * Например: + * [ + * ['name' => 'Название 1', 'description' => 'Описание 1'], + * ['name' => 'Название 2', 'description' => 'Описание 2'], + * ] + * Добавит две записи с заполненными полями name и description одним запросом + * Если в массиве больще 5000 элементов, то будет несколько запросов с добавлением по 5000 элементов в одном запросе + */ + public function batchInsert($table, $data) + { + $columns = []; + $rows = []; + foreach ($data as $values) + { + if (empty($columns)) + { + $columns = array_keys($values); + } + + $row = []; + foreach ($values as $value) + { + $row[] = $value; + } + + $rows[] = $row; + } + + $limit = 5000; + $count = (int) floor(count($rows) / $limit); + for ($i = 0; $i <= $count; $i++) + { + $partRows = array_slice($rows, $i * $limit, $limit); + Yii::$app->db->createCommand()->batchInsert($table, $columns, $partRows)->execute(); + } + } + +} diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..ace4b9e --- /dev/null +++ b/composer.json @@ -0,0 +1,21 @@ +{ + "name": "dominion/db", + "description": "Функционал для работы с db", + "type": "yii2-extension", + "keywords": ["yii2","extension"], + "license": "MIT", + "authors": [ + { + "name": "Rybkin Sasha", + "email": "ribkin@dominion.ru" + } + ], + "require": { + "yiisoft/yii2": "~2.0.0" + }, + "autoload": { + "psr-4": { + "dominion\\db\\": "" + } + } +} \ No newline at end of file