sqlserver.php 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437
  1. <?php namespace Laravel\Database\Schema\Grammars;
  2. use Laravel\Fluent;
  3. use Laravel\Database\Schema\Table;
  4. class SQLServer extends Grammar {
  5. /**
  6. * The keyword identifier for the database system.
  7. *
  8. * @var string
  9. */
  10. public $wrapper = '[%s]';
  11. /**
  12. * Generate the SQL statements for a table creation command.
  13. *
  14. * @param Table $table
  15. * @param Fluent $command
  16. * @return array
  17. */
  18. public function create(Table $table, Fluent $command)
  19. {
  20. $columns = implode(', ', $this->columns($table));
  21. // First we will generate the base table creation statement. Other than auto
  22. // incrementing keys, no indexes will be created during the first creation
  23. // of the table as they're added in separate commands.
  24. $sql = 'CREATE TABLE '.$this->wrap($table).' ('.$columns.')';
  25. return $sql;
  26. }
  27. /**
  28. * Generate the SQL statements for a table modification command.
  29. *
  30. * @param Table $table
  31. * @param Fluent $command
  32. * @return array
  33. */
  34. public function add(Table $table, Fluent $command)
  35. {
  36. $columns = $this->columns($table);
  37. // Once we have the array of column definitions, we need to add "add" to the
  38. // front of each definition, then we'll concatenate the definitions
  39. // using commas like normal and generate the SQL.
  40. $columns = implode(', ', array_map(function($column)
  41. {
  42. return 'ADD '.$column;
  43. }, $columns));
  44. return 'ALTER TABLE '.$this->wrap($table).' '.$columns;
  45. }
  46. /**
  47. * Create the individual column definitions for the table.
  48. *
  49. * @param Table $table
  50. * @return array
  51. */
  52. protected function columns(Table $table)
  53. {
  54. $columns = array();
  55. foreach ($table->columns as $column)
  56. {
  57. // Each of the data type's have their own definition creation method,
  58. // which is responsible for creating the SQL for the type. This lets
  59. // us to keep the syntax easy and fluent, while translating the
  60. // types to the types used by the database.
  61. $sql = $this->wrap($column).' '.$this->type($column);
  62. $elements = array('incrementer', 'nullable', 'defaults');
  63. foreach ($elements as $element)
  64. {
  65. $sql .= $this->$element($table, $column);
  66. }
  67. $columns[] = $sql;
  68. }
  69. return $columns;
  70. }
  71. /**
  72. * Get the SQL syntax for indicating if a column is nullable.
  73. *
  74. * @param Table $table
  75. * @param Fluent $column
  76. * @return string
  77. */
  78. protected function nullable(Table $table, Fluent $column)
  79. {
  80. return ($column->nullable) ? ' NULL' : ' NOT NULL';
  81. }
  82. /**
  83. * Get the SQL syntax for specifying a default value on a column.
  84. *
  85. * @param Table $table
  86. * @param Fluent $column
  87. * @return string
  88. */
  89. protected function defaults(Table $table, Fluent $column)
  90. {
  91. if ( ! is_null($column->default))
  92. {
  93. return " DEFAULT '".$this->default_value($column->default)."'";
  94. }
  95. }
  96. /**
  97. * Get the SQL syntax for defining an auto-incrementing column.
  98. *
  99. * @param Table $table
  100. * @param Fluent $column
  101. * @return string
  102. */
  103. protected function incrementer(Table $table, Fluent $column)
  104. {
  105. if ($column->type == 'integer' and $column->increment)
  106. {
  107. return ' IDENTITY PRIMARY KEY';
  108. }
  109. }
  110. /**
  111. * Generate the SQL statement for creating a primary key.
  112. *
  113. * @param Table $table
  114. * @param Fluent $command
  115. * @return string
  116. */
  117. public function primary(Table $table, Fluent $command)
  118. {
  119. $name = $command->name;
  120. $columns = $this->columnize($command->columns);
  121. return 'ALTER TABLE '.$this->wrap($table)." ADD CONSTRAINT {$name} PRIMARY KEY ({$columns})";
  122. }
  123. /**
  124. * Generate the SQL statement for creating a unique index.
  125. *
  126. * @param Table $table
  127. * @param Fluent $command
  128. * @return string
  129. */
  130. public function unique(Table $table, Fluent $command)
  131. {
  132. return $this->key($table, $command, true);
  133. }
  134. /**
  135. * Generate the SQL statement for creating a full-text index.
  136. *
  137. * @param Table $table
  138. * @param Fluent $command
  139. * @return string
  140. */
  141. public function fulltext(Table $table, Fluent $command)
  142. {
  143. $columns = $this->columnize($command->columns);
  144. $table = $this->wrap($table);
  145. // SQL Server requires the creation of a full-text "catalog" before creating
  146. // a full-text index, so we'll first create the catalog then add another
  147. // separate statement for the index.
  148. $sql[] = "CREATE FULLTEXT CATALOG {$command->catalog}";
  149. $create = "CREATE FULLTEXT INDEX ON ".$table." ({$columns}) ";
  150. // Full-text indexes must specify a unique, non-null column as the index
  151. // "key" and this should have been created manually by the developer in
  152. // a separate column addition command.
  153. $sql[] = $create .= "KEY INDEX {$command->key} ON {$command->catalog}";
  154. return $sql;
  155. }
  156. /**
  157. * Generate the SQL statement for creating a regular index.
  158. *
  159. * @param Table $table
  160. * @param Fluent $command
  161. * @return string
  162. */
  163. public function index(Table $table, Fluent $command)
  164. {
  165. return $this->key($table, $command);
  166. }
  167. /**
  168. * Generate the SQL statement for creating a new index.
  169. *
  170. * @param Table $table
  171. * @param Fluent $command
  172. * @param bool $unique
  173. * @return string
  174. */
  175. protected function key(Table $table, Fluent $command, $unique = false)
  176. {
  177. $columns = $this->columnize($command->columns);
  178. $create = ($unique) ? 'CREATE UNIQUE' : 'CREATE';
  179. return $create." INDEX {$command->name} ON ".$this->wrap($table)." ({$columns})";
  180. }
  181. /**
  182. * Generate the SQL statement for a rename table command.
  183. *
  184. * @param Table $table
  185. * @param Fluent $command
  186. * @return string
  187. */
  188. public function rename(Table $table, Fluent $command)
  189. {
  190. return 'ALTER TABLE '.$this->wrap($table).' RENAME TO '.$this->wrap($command->name);
  191. }
  192. /**
  193. * Generate the SQL statement for a drop table command.
  194. *
  195. * @param Table $table
  196. * @param Fluent $command
  197. * @return string
  198. */
  199. public function drop(Table $table, Fluent $command)
  200. {
  201. return 'DROP TABLE '.$this->wrap($table);
  202. }
  203. /**
  204. * Generate the SQL statement for a drop column command.
  205. *
  206. * @param Table $table
  207. * @param Fluent $command
  208. * @return string
  209. */
  210. public function drop_column(Table $table, Fluent $command)
  211. {
  212. $columns = array_map(array($this, 'wrap'), $command->columns);
  213. // Once we have the array of column names, we need to add "drop" to the front
  214. // of each column, then we'll concatenate the columns using commas and
  215. // generate the alter statement SQL.
  216. $columns = implode(', ', array_map(function($column)
  217. {
  218. return 'DROP '.$column;
  219. }, $columns));
  220. return 'ALTER TABLE '.$this->wrap($table).' '.$columns;
  221. }
  222. /**
  223. * Generate the SQL statement for a drop primary key command.
  224. *
  225. * @param Table $table
  226. * @param Fluent $command
  227. * @return string
  228. */
  229. public function drop_primary(Table $table, Fluent $command)
  230. {
  231. return 'ALTER TABLE '.$this->wrap($table).' DROP CONSTRAINT '.$command->name;
  232. }
  233. /**
  234. * Generate the SQL statement for a drop unique key command.
  235. *
  236. * @param Table $table
  237. * @param Fluent $command
  238. * @return string
  239. */
  240. public function drop_unique(Table $table, Fluent $command)
  241. {
  242. return $this->drop_key($table, $command);
  243. }
  244. /**
  245. * Generate the SQL statement for a drop full-text key command.
  246. *
  247. * @param Table $table
  248. * @param Fluent $command
  249. * @return string
  250. */
  251. public function drop_fulltext(Table $table, Fluent $command)
  252. {
  253. $sql[] = "DROP FULLTEXT INDEX ".$command->name;
  254. $sql[] = "DROP FULLTEXT CATALOG ".$command->catalog;
  255. return $sql;
  256. }
  257. /**
  258. * Generate the SQL statement for a drop index command.
  259. *
  260. * @param Table $table
  261. * @param Fluent $command
  262. * @return string
  263. */
  264. public function drop_index(Table $table, Fluent $command)
  265. {
  266. return $this->drop_key($table, $command);
  267. }
  268. /**
  269. * Generate the SQL statement for a drop key command.
  270. *
  271. * @param Table $table
  272. * @param Fluent $command
  273. * @return string
  274. */
  275. protected function drop_key(Table $table, Fluent $command)
  276. {
  277. return "DROP INDEX {$command->name} ON ".$this->wrap($table);
  278. }
  279. /**
  280. * Drop a foreign key constraint from the table.
  281. *
  282. * @param Table $table
  283. * @param Fluent $command
  284. * @return string
  285. */
  286. public function drop_foreign(Table $table, Fluent $command)
  287. {
  288. return $this->drop_constraint($table, $command);
  289. }
  290. /**
  291. * Generate the data-type definition for a string.
  292. *
  293. * @param Fluent $column
  294. * @return string
  295. */
  296. protected function type_string(Fluent $column)
  297. {
  298. return 'NVARCHAR('.$column->length.')';
  299. }
  300. /**
  301. * Generate the data-type definition for an integer.
  302. *
  303. * @param Fluent $column
  304. * @return string
  305. */
  306. protected function type_integer(Fluent $column)
  307. {
  308. return 'INT';
  309. }
  310. /**
  311. * Generate the data-type definition for an integer.
  312. *
  313. * @param Fluent $column
  314. * @return string
  315. */
  316. protected function type_float(Fluent $column)
  317. {
  318. return 'FLOAT';
  319. }
  320. /**
  321. * Generate the data-type definition for a decimal.
  322. *
  323. * @param Fluent $column
  324. * @return string
  325. */
  326. protected function type_decimal(Fluent $column)
  327. {
  328. return "DECIMAL({$column->precision}, {$column->scale})";
  329. }
  330. /**
  331. * Generate the data-type definition for a boolean.
  332. *
  333. * @param Fluent $column
  334. * @return string
  335. */
  336. protected function type_boolean(Fluent $column)
  337. {
  338. return 'TINYINT';
  339. }
  340. /**
  341. * Generate the data-type definition for a date.
  342. *
  343. * @param Fluent $column
  344. * @return string
  345. */
  346. protected function type_date(Fluent $column)
  347. {
  348. return 'DATETIME';
  349. }
  350. /**
  351. * Generate the data-type definition for a timestamp.
  352. *
  353. * @param Fluent $column
  354. * @return string
  355. */
  356. protected function type_timestamp(Fluent $column)
  357. {
  358. return 'TIMESTAMP';
  359. }
  360. /**
  361. * Generate the data-type definition for a text column.
  362. *
  363. * @param Fluent $column
  364. * @return string
  365. */
  366. protected function type_text(Fluent $column)
  367. {
  368. return 'NVARCHAR(MAX)';
  369. }
  370. /**
  371. * Generate the data-type definition for a blob.
  372. *
  373. * @param Fluent $column
  374. * @return string
  375. */
  376. protected function type_blob(Fluent $column)
  377. {
  378. return 'VARBINARY(MAX)';
  379. }
  380. }