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