sqlserver.php 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  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
  22. // auto-incrementing keys, no indexes will be created during the first
  23. // creation of the table. They will be added in separate commands.
  24. $sql = 'CREATE TABLE '.$this->wrap($table).' ('.$columns.')';
  25. return $sql;
  26. }
  27. /**
  28. * Geenrate 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 the array of column definitions, we need to add "add"
  38. // to the front of each definition, then we'll concatenate the
  39. // definitions 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 '".$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($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. // SQL Server requires the creation of a full-text "catalog" before
  145. // creating a full-text index, so we'll first create the catalog
  146. // then add another statement for the index. The catalog will
  147. // be updated automatically by the server.
  148. $sql[] = "CREATE FULLTEXT CATALOG {$command->catalog}";
  149. $create = "CREATE FULLTEXT INDEX ON ".$this->wrap($table)." ({$columns}) ";
  150. // Full-text indexes must specify a unique, non-nullable column as
  151. // the index "key" and this should have been created manually by
  152. // the developer in a separate column addition command, so we
  153. // can just specify it in this statement.
  154. $sql[] = $create .= "KEY INDEX {$command->key} ON {$command->catalog}";
  155. return $sql;
  156. }
  157. /**
  158. * Generate the SQL statement for creating a regular index.
  159. *
  160. * @param Table $table
  161. * @param Fluent $command
  162. * @return string
  163. */
  164. public function index(Table $table, Fluent $command)
  165. {
  166. return $this->key($table, $command);
  167. }
  168. /**
  169. * Generate the SQL statement for creating a new index.
  170. *
  171. * @param Table $table
  172. * @param Fluent $command
  173. * @param bool $unique
  174. * @return string
  175. */
  176. protected function key(Table $table, Fluent $command, $unique = false)
  177. {
  178. $columns = $this->columnize($command->columns);
  179. $create = ($unique) ? 'CREATE UNIQUE' : 'CREATE';
  180. return $create." INDEX {$command->name} ON ".$this->wrap($table)." ({$columns})";
  181. }
  182. /**
  183. * Generate the SQL statement for a drop table command.
  184. *
  185. * @param Table $table
  186. * @param Fluent $command
  187. * @return string
  188. */
  189. public function drop(Table $table, Fluent $command)
  190. {
  191. return 'DROP TABLE '.$this->wrap($table);
  192. }
  193. /**
  194. * Generate the SQL statement for a drop column command.
  195. *
  196. * @param Table $table
  197. * @param Fluent $command
  198. * @return string
  199. */
  200. public function drop_column(Table $table, Fluent $command)
  201. {
  202. $columns = array_map(array($this, 'wrap'), $command->columns);
  203. // Once we the array of column names, we need to add "drop" to the
  204. // front of each column, then we'll concatenate the columns using
  205. // commas and generate the alter statement SQL.
  206. $columns = implode(', ', array_map(function($column)
  207. {
  208. return 'DROP '.$column;
  209. }, $columns));
  210. return 'ALTER TABLE '.$this->wrap($table).' '.$columns;
  211. }
  212. /**
  213. * Generate the SQL statement for a drop primary key command.
  214. *
  215. * @param Table $table
  216. * @param Fluent $command
  217. * @return string
  218. */
  219. public function drop_primary(Table $table, Fluent $command)
  220. {
  221. return 'ALTER TABLE '.$this->wrap($table).' DROP CONSTRAINT '.$command->name;
  222. }
  223. /**
  224. * Generate the SQL statement for a drop unqiue key command.
  225. *
  226. * @param Table $table
  227. * @param Fluent $command
  228. * @return string
  229. */
  230. public function drop_unique(Table $table, Fluent $command)
  231. {
  232. return $this->drop_key($table, $command);
  233. }
  234. /**
  235. * Generate the SQL statement for a drop full-text key command.
  236. *
  237. * @param Table $table
  238. * @param Fluent $command
  239. * @return string
  240. */
  241. public function drop_fulltext(Table $table, Fluent $command)
  242. {
  243. $sql[] = "DROP FULLTEXT INDEX ".$command->name;
  244. $sql[] = "DROP FULLTEXT CATALOG ".$command->catalog;
  245. return $sql;
  246. }
  247. /**
  248. * Generate the SQL statement for a drop index command.
  249. *
  250. * @param Table $table
  251. * @param Fluent $command
  252. * @return string
  253. */
  254. public function drop_index(Table $table, Fluent $command)
  255. {
  256. return $this->drop_key($table, $command);
  257. }
  258. /**
  259. * Generate the SQL statement for a drop key command.
  260. *
  261. * @param Table $table
  262. * @param Fluent $command
  263. * @return string
  264. */
  265. protected function drop_key(Table $table, Fluent $command)
  266. {
  267. return "DROP INDEX {$command->name} ON ".$this->wrap($table);
  268. }
  269. /**
  270. * Generate the data-type definition for a string.
  271. *
  272. * @param Fluent $column
  273. * @return string
  274. */
  275. protected function type_string(Fluent $column)
  276. {
  277. return 'NVARCHAR('.$column->length.')';
  278. }
  279. /**
  280. * Generate the data-type definition for an integer.
  281. *
  282. * @param Fluent $column
  283. * @return string
  284. */
  285. protected function type_integer(Fluent $column)
  286. {
  287. return 'INT';
  288. }
  289. /**
  290. * Generate the data-type definition for an integer.
  291. *
  292. * @param Fluent $column
  293. * @return string
  294. */
  295. protected function type_float(Fluent $column)
  296. {
  297. return 'FLOAT';
  298. }
  299. /**
  300. * Generate the data-type definition for a boolean.
  301. *
  302. * @param Fluent $column
  303. * @return string
  304. */
  305. protected function type_boolean(Fluent $column)
  306. {
  307. return 'TINYINT';
  308. }
  309. /**
  310. * Generate the data-type definition for a date.
  311. *
  312. * @param Fluent $column
  313. * @return string
  314. */
  315. protected function type_date(Fluent $column)
  316. {
  317. return 'DATETIME';
  318. }
  319. /**
  320. * Generate the data-type definition for a timestamp.
  321. *
  322. * @param Fluent $column
  323. * @return string
  324. */
  325. protected function type_timestamp(Fluent $column)
  326. {
  327. return 'TIMESTAMP';
  328. }
  329. /**
  330. * Generate the data-type definition for a text column.
  331. *
  332. * @param Fluent $column
  333. * @return string
  334. */
  335. protected function type_text(Fluent $column)
  336. {
  337. return 'NVARCHAR(MAX)';
  338. }
  339. /**
  340. * Generate the data-type definition for a blob.
  341. *
  342. * @param Fluent $column
  343. * @return string
  344. */
  345. protected function type_blob(Fluent $column)
  346. {
  347. return 'VARBINARY(MAX)';
  348. }
  349. }