From ce6e92b736b872faa4e39c9ded0073eeb9dbe10c Mon Sep 17 00:00:00 2001 From: Matvey Vasenin Date: Fri, 14 Aug 2015 12:27:21 +0300 Subject: [PATCH] add comment control methods --- framework/db/Command.php | 56 +++++++++ framework/db/Migration.php | 60 ++++++++++ framework/db/QueryBuilder.php | 48 ++++++++ framework/db/mysql/QueryBuilder.php | 110 +++++++++++++++++- tests/data/mysql.sql | 9 ++ tests/data/postgres.sql | 7 ++ tests/framework/db/QueryBuilderTest.php | 30 +++++ .../db/pgsql/PostgreSQLQueryBuilderTest.php | 26 +++++ 8 files changed, 345 insertions(+), 1 deletion(-) diff --git a/framework/db/Command.php b/framework/db/Command.php index d2b4e5e3ce..b0456304a7 100644 --- a/framework/db/Command.php +++ b/framework/db/Command.php @@ -753,6 +753,62 @@ class Command extends Component return $this->setSql($sql); } + /** + * Builds a SQL command for adding comment to column + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @param string $column the name of the column to be commented. The column name will be properly quoted by the method. + * @param string $comment the text of the comment to be added. The comment will be properly quoted by the method. + * @return $this the command object itself + */ + public function addCommentOnColumn($table, $column, $comment) + { + $sql = $this->db->getQueryBuilder()->addCommentOnColumn($table, $column, $comment); + + return $this->setSql($sql); + } + + /** + * Builds a SQL command for adding comment to table + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @param string $comment the text of the comment to be added. The comment will be properly quoted by the method. + * @return $this the command object itself + */ + public function addCommentOnTable($table, $comment) + { + $sql = $this->db->getQueryBuilder()->addCommentOnTable($table, $comment); + + return $this->setSql($sql); + } + + /** + * Builds a SQL command for dropping comment from column + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @param string $column the name of the column to be commented. The column name will be properly quoted by the method. + * @return $this the command object itself + */ + public function dropCommentFromColumn($table, $column) + { + $sql = $this->db->getQueryBuilder()->dropCommentFromColumn($table, $column); + + return $this->setSql($sql); + } + + /** + * Builds a SQL command for dropping comment from table + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @return $this the command object itself + */ + public function dropCommentFromTable($table) + { + $sql = $this->db->getQueryBuilder()->dropCommentFromTable($table); + + return $this->setSql($sql); + } + /** * Executes the SQL statement. * This method should only be used for executing non-query SQL statement, such as `INSERT`, `DELETE`, `UPDATE` SQLs. diff --git a/framework/db/Migration.php b/framework/db/Migration.php index 6197bf9abb..76819134ac 100644 --- a/framework/db/Migration.php +++ b/framework/db/Migration.php @@ -446,4 +446,64 @@ class Migration extends Component implements MigrationInterface $this->db->createCommand()->dropIndex($name, $table)->execute(); echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; } + + /** + * Builds and execute a SQL statement for adding comment to column + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @param string $column the name of the column to be commented. The column name will be properly quoted by the method. + * @param string $comment the text of the comment to be added. The comment will be properly quoted by the method. + * @return $this the command object itself + */ + public function addCommentOnColumn($table, $column, $comment) + { + echo " > add comment on column $column ..."; + $time = microtime(true); + $this->db->createCommand()->addCommentOnColumn($table, $column, $comment)->execute(); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + } + + /** + * Builds a SQL statement for adding comment to table + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @param string $comment the text of the comment to be added. The comment will be properly quoted by the method. + * @return $this the command object itself + */ + public function addCommentOnTable($table, $comment) + { + echo " > add comment on table $table ..."; + $time = microtime(true); + $this->db->createCommand()->addCommentOnTable($table, $comment)->execute(); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + } + + /** + * Builds and execute a SQL statement for dropping comment from column + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @param string $column the name of the column to be commented. The column name will be properly quoted by the method. + * @return $this the command object itself + */ + public function dropCommentFromColumn($table, $column) + { + echo " > drop comment from column $column ..."; + $time = microtime(true); + $this->db->createCommand()->dropCommentFromColumn($table, $column, $comment)->execute(); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + } + + /** + * Builds a SQL statement for dropping comment from table + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @return $this the command object itself + */ + public function dropCommentFromTable($table) + { + echo " > drop comment from table $table ..."; + $time = microtime(true); + $this->db->createCommand()->dropCommentFromTable($table, $comment)->execute(); + echo " done (time: " . sprintf('%.3f', microtime(true) - $time) . "s)\n"; + } } diff --git a/framework/db/QueryBuilder.php b/framework/db/QueryBuilder.php index 6d7d5d1acf..9e434072f1 100644 --- a/framework/db/QueryBuilder.php +++ b/framework/db/QueryBuilder.php @@ -552,6 +552,54 @@ class QueryBuilder extends \yii\base\Object throw new NotSupportedException($this->db->getDriverName() . ' does not support enabling/disabling integrity check.'); } + /** + * Builds a SQL command for adding comment to column + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @param string $column the name of the column to be commented. The column name will be properly quoted by the method. + * @param string $comment the text of the comment to be added. The comment will be properly quoted by the method. + * @return $this the command object itself + */ + public function addCommentOnColumn($table, $column, $comment) + { + return 'COMMENT ON COLUMN ' . $this->db->quoteTableName($table) . '.' . $this->db->quoteColumnName($column) . ' IS ' . $this->db->quoteValue($comment); + } + + /** + * Builds a SQL command for adding comment to table + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @param string $comment the text of the comment to be added. The comment will be properly quoted by the method. + * @return $this the command object itself + */ + public function addCommentOnTable($table, $comment) + { + return 'COMMENT ON TABLE ' . $this->db->quoteTableName($table) . ' IS ' . $this->db->quoteValue($comment); + } + + /** + * Builds a SQL command for adding comment to column + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @param string $column the name of the column to be commented. The column name will be properly quoted by the method. + * @return $this the command object itself + */ + public function dropCommentFromColumn($table, $column) + { + return 'COMMENT ON COLUMN ' . $this->db->quoteTableName($table) . '.' . $this->db->quoteColumnName($column) . ' IS NULL'; + } + + /** + * Builds a SQL command for adding comment to table + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @return $this the command object itself + */ + public function dropCommentFromTable($table) + { + return 'COMMENT ON TABLE ' . $this->db->quoteTableName($table) . ' IS NULL'; + } + /** * Converts an abstract column type into a physical column type. * The conversion is done using the type map specified in [[typeMap]]. diff --git a/framework/db/mysql/QueryBuilder.php b/framework/db/mysql/QueryBuilder.php index 17b14168c1..eb7c364280 100644 --- a/framework/db/mysql/QueryBuilder.php +++ b/framework/db/mysql/QueryBuilder.php @@ -217,4 +217,112 @@ class QueryBuilder extends \yii\db\QueryBuilder . (!empty($names) ? ' (' . implode(', ', $names) . ')' : '') . (!empty($placeholders) ? ' VALUES (' . implode(', ', $placeholders) . ')' : ' DEFAULT VALUES'); } -} + + /** + * Builds a SQL command for adding comment to column + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @param string $column the name of the column to be commented. The column name will be properly quoted by the method. + * @param string $comment the text of the comment to be added. The comment will be properly quoted by the method. + * @return $this the command object itself + */ + public function addCommentOnColumn($table, $column, $comment) + { + $quotedTable = $this->db->quoteTableName($table); + $definition = $this->getColumnDefinition($quotedTable, $column); + $definition = trim(preg_replace("/COMMENT '(.*?)'/i", '', $definition)); + return sprintf( + 'ALTER TABLE %s CHANGE %s %s%s COMMENT %s', + $quotedTable, + $this->db->quoteColumnName($column), + $this->db->quoteColumnName($column), + empty($definition) ? '' : ' ' . $definition, + $this->db->quoteValue($comment) + ); + } + + /** + * Builds a SQL command for adding comment to table + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @param string $comment the text of the comment to be added. The comment will be properly quoted by the method. + * @return $this the command object itself + */ + public function addCommentOnTable($table, $comment) + { + $quotedTable = $this->db->quoteTableName($table); + return sprintf( + 'ALTER TABLE %s COMMENT %s', + $quotedTable, + $this->db->quoteValue($comment) + ); + } + + /** + * Builds a SQL command for adding comment to column + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @param string $column the name of the column to be commented. The column name will be properly quoted by the method. + * @return $this the command object itself + */ + public function dropCommentFromColumn($table, $column) + { + $quotedTable = $this->db->quoteTableName($table); + $definition = $this->getColumnDefinition($quotedTable, $column); + $definition = trim(preg_replace("/COMMENT '(.*?)'/i", '', $definition)); + return sprintf( + 'ALTER TABLE %s CHANGE %s %s%s COMMENT \'\'', + $quotedTable, + $this->db->quoteColumnName($column), + $this->db->quoteColumnName($column), + empty($definition) ? '' : ' ' . $definition + ); + } + + /** + * Builds a SQL command for adding comment to table + * + * @param string $table the table whose column is to be commented. The table name will be properly quoted by the method. + * @return $this the command object itself + */ + public function dropCommentFromTable($table) + { + $quotedTable = $this->db->quoteTableName($table); + return sprintf( + "ALTER TABLE %s COMMENT ''", + $quotedTable, + empty($definition) ? '' : ' ' . $definition + ); + } + + + /** + * Gets column definition. + * + * @param string $table table name + * @param string $column column name + * @return null|string the column definition + * @throws Exception in case when table does not contain column + */ + private function getColumnDefinition($table, $column) + { + $row = $this->db->createCommand('SHOW CREATE TABLE ' . $table)->queryOne(); + if ($row === false) { + throw new Exception("Unable to find column '$column' in table '$table'."); + } + if (isset($row['Create Table'])) { + $sql = $row['Create Table']; + } else { + $row = array_values($row); + $sql = $row[1]; + } + if (preg_match_all('/^\s*`(.*?)`\s+(.*?),?$/m', $sql, $matches)) { + foreach ($matches[1] as $i => $c) { + if ($c === $column) { + return $matches[2][$i]; + } + } + } + return null; + } +} \ No newline at end of file diff --git a/tests/data/mysql.sql b/tests/data/mysql.sql index 4b1ae6fa10..c3f1d98008 100644 --- a/tests/data/mysql.sql +++ b/tests/data/mysql.sql @@ -18,6 +18,7 @@ DROP TABLE IF EXISTS `constraints` CASCADE; DROP TABLE IF EXISTS `animal` CASCADE; DROP TABLE IF EXISTS `default_pk` CASCADE; DROP TABLE IF EXISTS `document` CASCADE; +DROP TABLE IF EXISTS `comment` CASCADE; DROP VIEW IF EXISTS `animal_view`; CREATE TABLE `constraints` @@ -150,6 +151,14 @@ CREATE TABLE `document` ( PRIMARY KEY (id) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; +CREATE TABLE `comment` ( + `id` INT(11) NOT NULL AUTO_INCREMENT, + `add_comment` VARCHAR(255) NOT NULL, + `replace_comment` VARCHAR(255) COMMENT 'comment', + `delete_comment` VARCHAR(128) NOT NULL COMMENT 'comment', + PRIMARY KEY (id) +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + CREATE VIEW `animal_view` AS SELECT * FROM `animal`; INSERT INTO `animal` (`type`) VALUES ('yiiunit\data\ar\Cat'); diff --git a/tests/data/postgres.sql b/tests/data/postgres.sql index e37d7351a0..a35c1886d1 100644 --- a/tests/data/postgres.sql +++ b/tests/data/postgres.sql @@ -20,6 +20,7 @@ DROP TABLE IF EXISTS "bool_values" CASCADE; DROP TABLE IF EXISTS "animal" CASCADE; DROP TABLE IF EXISTS "default_pk" CASCADE; DROP TABLE IF EXISTS "document" CASCADE; +DROP TABLE IF EXISTS "comment" CASCADE; DROP VIEW IF EXISTS "animal_view"; DROP SCHEMA IF EXISTS "schema1" CASCADE; DROP SCHEMA IF EXISTS "schema2" CASCADE; @@ -154,6 +155,12 @@ CREATE TABLE "document" ( version integer not null default 0 ); +CREATE TABLE "comment" ( + id serial primary key, + name varchar(255) not null, + message text not null +); + CREATE VIEW "animal_view" AS SELECT * FROM "animal"; INSERT INTO "animal" (type) VALUES ('yiiunit\data\ar\Cat'); diff --git a/tests/framework/db/QueryBuilderTest.php b/tests/framework/db/QueryBuilderTest.php index 95da34abd5..0c71a62aff 100644 --- a/tests/framework/db/QueryBuilderTest.php +++ b/tests/framework/db/QueryBuilderTest.php @@ -517,4 +517,34 @@ class QueryBuilderTest extends DatabaseTestCase ]; (new Query())->from('customer')->where($condition)->all($this->getConnection()); } + + public function testCommentColumn() + { + $qb = $this->getQueryBuilder(); + + $expected = "ALTER TABLE `comment` CHANGE `add_comment` `add_comment` varchar(255) NOT NULL COMMENT 'This is my column.'"; + $sql = $qb->addCommentOnColumn('comment', 'add_comment', 'This is my column.'); + $this->assertEquals($expected, $sql); + + $expected = "ALTER TABLE `comment` CHANGE `replace_comment` `replace_comment` varchar(255) DEFAULT NULL COMMENT 'This is my column.'"; + $sql = $qb->addCommentOnColumn('comment', 'replace_comment', 'This is my column.'); + $this->assertEquals($expected, $sql); + + $expected = "ALTER TABLE `comment` CHANGE `delete_comment` `delete_comment` varchar(128) NOT NULL COMMENT ''"; + $sql = $qb->dropCommentFromColumn('comment', 'delete_comment'); + $this->assertEquals($expected, $sql); + } + + public function testCommentTable() + { + $qb = $this->getQueryBuilder(); + + $expected = "ALTER TABLE `comment` COMMENT 'This is my table.'"; + $sql = $qb->addCommentOnTable('comment', 'This is my table.'); + $this->assertEquals($expected, $sql); + + $expected = "ALTER TABLE `comment` COMMENT ''"; + $sql = $qb->dropCommentFromTable('comment'); + $this->assertEquals($expected, $sql); + } } diff --git a/tests/framework/db/pgsql/PostgreSQLQueryBuilderTest.php b/tests/framework/db/pgsql/PostgreSQLQueryBuilderTest.php index 3ec65d42fb..90f11b535f 100644 --- a/tests/framework/db/pgsql/PostgreSQLQueryBuilderTest.php +++ b/tests/framework/db/pgsql/PostgreSQLQueryBuilderTest.php @@ -126,4 +126,30 @@ class PostgreSQLQueryBuilderTest extends QueryBuilderTest $sql = $qb->alterColumn('foo1', 'bar', 'reset xyz'); $this->assertEquals($expected, $sql); } + + public function testCommentColumn() + { + $qb = $this->getQueryBuilder(); + + $expected = "COMMENT ON COLUMN \"comment\".\"text\" IS 'This is my column.'"; + $sql = $qb->addCommentOnColumn('comment', 'text', 'This is my column.'); + $this->assertEquals($expected, $sql); + + $expected = "COMMENT ON COLUMN \"comment\".\"text\" IS NULL"; + $sql = $qb->dropCommentFromColumn('comment', 'text'); + $this->assertEquals($expected, $sql); + } + + public function testCommentTable() + { + $qb = $this->getQueryBuilder(); + + $expected = "COMMENT ON TABLE \"comment\" IS 'This is my table.'"; + $sql = $qb->addCommentOnTable('comment', 'This is my table.'); + $this->assertEquals($expected, $sql); + + $expected = "COMMENT ON TABLE \"comment\" IS NULL"; + $sql = $qb->dropCommentFromTable('comment'); + $this->assertEquals($expected, $sql); + } }