DatabaseSchemaBlueprintTest.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. <?php
  2. namespace Illuminate\Tests\Database;
  3. use Illuminate\Database\Connection;
  4. use Illuminate\Database\Schema\Blueprint;
  5. use Illuminate\Database\Schema\Builder;
  6. use Illuminate\Database\Schema\Grammars\MySqlGrammar;
  7. use Illuminate\Database\Schema\Grammars\PostgresGrammar;
  8. use Illuminate\Database\Schema\Grammars\SQLiteGrammar;
  9. use Illuminate\Database\Schema\Grammars\SqlServerGrammar;
  10. use Mockery as m;
  11. use PHPUnit\Framework\TestCase;
  12. class DatabaseSchemaBlueprintTest extends TestCase
  13. {
  14. protected function tearDown(): void
  15. {
  16. m::close();
  17. Builder::$defaultMorphKeyType = 'int';
  18. }
  19. public function testToSqlRunsCommandsFromBlueprint()
  20. {
  21. $conn = m::mock(Connection::class);
  22. $conn->shouldReceive('statement')->once()->with('foo');
  23. $conn->shouldReceive('statement')->once()->with('bar');
  24. $grammar = m::mock(MySqlGrammar::class);
  25. $blueprint = $this->getMockBuilder(Blueprint::class)->onlyMethods(['toSql'])->setConstructorArgs(['users'])->getMock();
  26. $blueprint->expects($this->once())->method('toSql')->with($this->equalTo($conn), $this->equalTo($grammar))->willReturn(['foo', 'bar']);
  27. $blueprint->build($conn, $grammar);
  28. }
  29. public function testIndexDefaultNames()
  30. {
  31. $blueprint = new Blueprint('users');
  32. $blueprint->unique(['foo', 'bar']);
  33. $commands = $blueprint->getCommands();
  34. $this->assertSame('users_foo_bar_unique', $commands[0]->index);
  35. $blueprint = new Blueprint('users');
  36. $blueprint->index('foo');
  37. $commands = $blueprint->getCommands();
  38. $this->assertSame('users_foo_index', $commands[0]->index);
  39. $blueprint = new Blueprint('geo');
  40. $blueprint->spatialIndex('coordinates');
  41. $commands = $blueprint->getCommands();
  42. $this->assertSame('geo_coordinates_spatialindex', $commands[0]->index);
  43. }
  44. public function testIndexDefaultNamesWhenPrefixSupplied()
  45. {
  46. $blueprint = new Blueprint('users', null, 'prefix_');
  47. $blueprint->unique(['foo', 'bar']);
  48. $commands = $blueprint->getCommands();
  49. $this->assertSame('prefix_users_foo_bar_unique', $commands[0]->index);
  50. $blueprint = new Blueprint('users', null, 'prefix_');
  51. $blueprint->index('foo');
  52. $commands = $blueprint->getCommands();
  53. $this->assertSame('prefix_users_foo_index', $commands[0]->index);
  54. $blueprint = new Blueprint('geo', null, 'prefix_');
  55. $blueprint->spatialIndex('coordinates');
  56. $commands = $blueprint->getCommands();
  57. $this->assertSame('prefix_geo_coordinates_spatialindex', $commands[0]->index);
  58. }
  59. public function testDropIndexDefaultNames()
  60. {
  61. $blueprint = new Blueprint('users');
  62. $blueprint->dropUnique(['foo', 'bar']);
  63. $commands = $blueprint->getCommands();
  64. $this->assertSame('users_foo_bar_unique', $commands[0]->index);
  65. $blueprint = new Blueprint('users');
  66. $blueprint->dropIndex(['foo']);
  67. $commands = $blueprint->getCommands();
  68. $this->assertSame('users_foo_index', $commands[0]->index);
  69. $blueprint = new Blueprint('geo');
  70. $blueprint->dropSpatialIndex(['coordinates']);
  71. $commands = $blueprint->getCommands();
  72. $this->assertSame('geo_coordinates_spatialindex', $commands[0]->index);
  73. }
  74. public function testDropIndexDefaultNamesWhenPrefixSupplied()
  75. {
  76. $blueprint = new Blueprint('users', null, 'prefix_');
  77. $blueprint->dropUnique(['foo', 'bar']);
  78. $commands = $blueprint->getCommands();
  79. $this->assertSame('prefix_users_foo_bar_unique', $commands[0]->index);
  80. $blueprint = new Blueprint('users', null, 'prefix_');
  81. $blueprint->dropIndex(['foo']);
  82. $commands = $blueprint->getCommands();
  83. $this->assertSame('prefix_users_foo_index', $commands[0]->index);
  84. $blueprint = new Blueprint('geo', null, 'prefix_');
  85. $blueprint->dropSpatialIndex(['coordinates']);
  86. $commands = $blueprint->getCommands();
  87. $this->assertSame('prefix_geo_coordinates_spatialindex', $commands[0]->index);
  88. }
  89. public function testDefaultCurrentDateTime()
  90. {
  91. $base = new Blueprint('users', function ($table) {
  92. $table->dateTime('created')->useCurrent();
  93. });
  94. $connection = m::mock(Connection::class);
  95. $blueprint = clone $base;
  96. $this->assertEquals(['alter table `users` add `created` datetime default CURRENT_TIMESTAMP not null'], $blueprint->toSql($connection, new MySqlGrammar));
  97. $blueprint = clone $base;
  98. $this->assertEquals(['alter table "users" add column "created" timestamp(0) without time zone default CURRENT_TIMESTAMP not null'], $blueprint->toSql($connection, new PostgresGrammar));
  99. $blueprint = clone $base;
  100. $this->assertEquals(['alter table "users" add column "created" datetime default CURRENT_TIMESTAMP not null'], $blueprint->toSql($connection, new SQLiteGrammar));
  101. $blueprint = clone $base;
  102. $this->assertEquals(['alter table "users" add "created" datetime default CURRENT_TIMESTAMP not null'], $blueprint->toSql($connection, new SqlServerGrammar));
  103. }
  104. public function testDefaultCurrentTimestamp()
  105. {
  106. $base = new Blueprint('users', function ($table) {
  107. $table->timestamp('created')->useCurrent();
  108. });
  109. $connection = m::mock(Connection::class);
  110. $blueprint = clone $base;
  111. $this->assertEquals(['alter table `users` add `created` timestamp default CURRENT_TIMESTAMP not null'], $blueprint->toSql($connection, new MySqlGrammar));
  112. $blueprint = clone $base;
  113. $this->assertEquals(['alter table "users" add column "created" timestamp(0) without time zone default CURRENT_TIMESTAMP not null'], $blueprint->toSql($connection, new PostgresGrammar));
  114. $blueprint = clone $base;
  115. $this->assertEquals(['alter table "users" add column "created" datetime default CURRENT_TIMESTAMP not null'], $blueprint->toSql($connection, new SQLiteGrammar));
  116. $blueprint = clone $base;
  117. $this->assertEquals(['alter table "users" add "created" datetime default CURRENT_TIMESTAMP not null'], $blueprint->toSql($connection, new SqlServerGrammar));
  118. }
  119. public function testUnsignedDecimalTable()
  120. {
  121. $base = new Blueprint('users', function ($table) {
  122. $table->unsignedDecimal('money', 10, 2)->useCurrent();
  123. });
  124. $connection = m::mock(Connection::class);
  125. $blueprint = clone $base;
  126. $this->assertEquals(['alter table `users` add `money` decimal(10, 2) unsigned not null'], $blueprint->toSql($connection, new MySqlGrammar));
  127. }
  128. public function testRemoveColumn()
  129. {
  130. $base = new Blueprint('users', function ($table) {
  131. $table->string('foo');
  132. $table->string('remove_this');
  133. $table->removeColumn('remove_this');
  134. });
  135. $connection = m::mock(Connection::class);
  136. $blueprint = clone $base;
  137. $this->assertEquals(['alter table `users` add `foo` varchar(255) not null'], $blueprint->toSql($connection, new MySqlGrammar));
  138. }
  139. public function testMacroable()
  140. {
  141. Blueprint::macro('foo', function () {
  142. return $this->addCommand('foo');
  143. });
  144. MySqlGrammar::macro('compileFoo', function () {
  145. return 'bar';
  146. });
  147. $blueprint = new Blueprint('users', function ($table) {
  148. $table->foo();
  149. });
  150. $connection = m::mock(Connection::class);
  151. $this->assertEquals(['bar'], $blueprint->toSql($connection, new MySqlGrammar));
  152. }
  153. public function testDefaultUsingIdMorph()
  154. {
  155. $base = new Blueprint('comments', function ($table) {
  156. $table->morphs('commentable');
  157. });
  158. $connection = m::mock(Connection::class);
  159. $blueprint = clone $base;
  160. $this->assertEquals([
  161. 'alter table `comments` add `commentable_type` varchar(255) not null, add `commentable_id` bigint unsigned not null',
  162. 'alter table `comments` add index `comments_commentable_type_commentable_id_index`(`commentable_type`, `commentable_id`)',
  163. ], $blueprint->toSql($connection, new MySqlGrammar));
  164. }
  165. public function testDefaultUsingNullableIdMorph()
  166. {
  167. $base = new Blueprint('comments', function ($table) {
  168. $table->nullableMorphs('commentable');
  169. });
  170. $connection = m::mock(Connection::class);
  171. $blueprint = clone $base;
  172. $this->assertEquals([
  173. 'alter table `comments` add `commentable_type` varchar(255) null, add `commentable_id` bigint unsigned null',
  174. 'alter table `comments` add index `comments_commentable_type_commentable_id_index`(`commentable_type`, `commentable_id`)',
  175. ], $blueprint->toSql($connection, new MySqlGrammar));
  176. }
  177. public function testDefaultUsingUuidMorph()
  178. {
  179. Builder::defaultMorphKeyType('uuid');
  180. $base = new Blueprint('comments', function ($table) {
  181. $table->morphs('commentable');
  182. });
  183. $connection = m::mock(Connection::class);
  184. $blueprint = clone $base;
  185. $this->assertEquals([
  186. 'alter table `comments` add `commentable_type` varchar(255) not null, add `commentable_id` char(36) not null',
  187. 'alter table `comments` add index `comments_commentable_type_commentable_id_index`(`commentable_type`, `commentable_id`)',
  188. ], $blueprint->toSql($connection, new MySqlGrammar));
  189. }
  190. public function testDefaultUsingNullableUuidMorph()
  191. {
  192. Builder::defaultMorphKeyType('uuid');
  193. $base = new Blueprint('comments', function ($table) {
  194. $table->nullableMorphs('commentable');
  195. });
  196. $connection = m::mock(Connection::class);
  197. $blueprint = clone $base;
  198. $this->assertEquals([
  199. 'alter table `comments` add `commentable_type` varchar(255) null, add `commentable_id` char(36) null',
  200. 'alter table `comments` add index `comments_commentable_type_commentable_id_index`(`commentable_type`, `commentable_id`)',
  201. ], $blueprint->toSql($connection, new MySqlGrammar));
  202. }
  203. public function testGenerateRelationshipColumnWithIncrementalModel()
  204. {
  205. $base = new Blueprint('posts', function ($table) {
  206. $table->foreignIdFor('Illuminate\Foundation\Auth\User');
  207. });
  208. $connection = m::mock(Connection::class);
  209. $blueprint = clone $base;
  210. $this->assertEquals([
  211. 'alter table `posts` add `user_id` bigint unsigned not null',
  212. ], $blueprint->toSql($connection, new MySqlGrammar));
  213. }
  214. public function testGenerateRelationshipColumnWithUuidModel()
  215. {
  216. require_once __DIR__.'/stubs/EloquentModelUuidStub.php';
  217. $base = new Blueprint('posts', function ($table) {
  218. $table->foreignIdFor('EloquentModelUuidStub');
  219. });
  220. $connection = m::mock(Connection::class);
  221. $blueprint = clone $base;
  222. $this->assertEquals([
  223. 'alter table `posts` add `eloquent_model_uuid_stub_id` char(36) not null',
  224. ], $blueprint->toSql($connection, new MySqlGrammar));
  225. }
  226. public function testTinyTextColumn()
  227. {
  228. $base = new Blueprint('posts', function ($table) {
  229. $table->tinyText('note');
  230. });
  231. $connection = m::mock(Connection::class);
  232. $blueprint = clone $base;
  233. $this->assertEquals([
  234. 'alter table `posts` add `note` tinytext not null',
  235. ], $blueprint->toSql($connection, new MySqlGrammar));
  236. $blueprint = clone $base;
  237. $this->assertEquals([
  238. 'alter table "posts" add column "note" text not null',
  239. ], $blueprint->toSql($connection, new SQLiteGrammar));
  240. $blueprint = clone $base;
  241. $this->assertEquals([
  242. 'alter table "posts" add column "note" varchar(255) not null',
  243. ], $blueprint->toSql($connection, new PostgresGrammar));
  244. $blueprint = clone $base;
  245. $this->assertEquals([
  246. 'alter table "posts" add "note" nvarchar(255) not null',
  247. ], $blueprint->toSql($connection, new SqlServerGrammar));
  248. }
  249. public function testTinyTextNullableColumn()
  250. {
  251. $base = new Blueprint('posts', function ($table) {
  252. $table->tinyText('note')->nullable();
  253. });
  254. $connection = m::mock(Connection::class);
  255. $blueprint = clone $base;
  256. $this->assertEquals([
  257. 'alter table `posts` add `note` tinytext null',
  258. ], $blueprint->toSql($connection, new MySqlGrammar));
  259. $blueprint = clone $base;
  260. $this->assertEquals([
  261. 'alter table "posts" add column "note" text',
  262. ], $blueprint->toSql($connection, new SQLiteGrammar));
  263. $blueprint = clone $base;
  264. $this->assertEquals([
  265. 'alter table "posts" add column "note" varchar(255) null',
  266. ], $blueprint->toSql($connection, new PostgresGrammar));
  267. $blueprint = clone $base;
  268. $this->assertEquals([
  269. 'alter table "posts" add "note" nvarchar(255) null',
  270. ], $blueprint->toSql($connection, new SqlServerGrammar));
  271. }
  272. }