1<?php
2
3namespace Illuminate\Database\Schema\Grammars;
4
5use RuntimeException;
6use Illuminate\Support\Fluent;
7use Illuminate\Database\Connection;
8use Illuminate\Database\Schema\Blueprint;
9
10class MySqlGrammar extends Grammar
11{
12    /**
13     * The possible column modifiers.
14     *
15     * @var array
16     */
17    protected $modifiers = [
18        'Unsigned', 'Charset', 'Collate', 'VirtualAs', 'StoredAs', 'Nullable',
19        'Default', 'Increment', 'Comment', 'After', 'First', 'Srid',
20    ];
21
22    /**
23     * The possible column serials.
24     *
25     * @var array
26     */
27    protected $serials = ['bigInteger', 'integer', 'mediumInteger', 'smallInteger', 'tinyInteger'];
28
29    /**
30     * Compile the query to determine the list of tables.
31     *
32     * @return string
33     */
34    public function compileTableExists()
35    {
36        return "select * from information_schema.tables where table_schema = ? and table_name = ? and table_type = 'BASE TABLE'";
37    }
38
39    /**
40     * Compile the query to determine the list of columns.
41     *
42     * @return string
43     */
44    public function compileColumnListing()
45    {
46        return 'select column_name as `column_name` from information_schema.columns where table_schema = ? and table_name = ?';
47    }
48
49    /**
50     * Compile a create table command.
51     *
52     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
53     * @param  \Illuminate\Support\Fluent  $command
54     * @param  \Illuminate\Database\Connection  $connection
55     * @return string
56     */
57    public function compileCreate(Blueprint $blueprint, Fluent $command, Connection $connection)
58    {
59        $sql = $this->compileCreateTable(
60            $blueprint, $command, $connection
61        );
62
63        // Once we have the primary SQL, we can add the encoding option to the SQL for
64        // the table.  Then, we can check if a storage engine has been supplied for
65        // the table. If so, we will add the engine declaration to the SQL query.
66        $sql = $this->compileCreateEncoding(
67            $sql, $connection, $blueprint
68        );
69
70        // Finally, we will append the engine configuration onto this SQL statement as
71        // the final thing we do before returning this finished SQL. Once this gets
72        // added the query will be ready to execute against the real connections.
73        return $this->compileCreateEngine(
74            $sql, $connection, $blueprint
75        );
76    }
77
78    /**
79     * Create the main create table clause.
80     *
81     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
82     * @param  \Illuminate\Support\Fluent  $command
83     * @param  \Illuminate\Database\Connection  $connection
84     * @return string
85     */
86    protected function compileCreateTable($blueprint, $command, $connection)
87    {
88        return sprintf('%s table %s (%s)',
89            $blueprint->temporary ? 'create temporary' : 'create',
90            $this->wrapTable($blueprint),
91            implode(', ', $this->getColumns($blueprint))
92        );
93    }
94
95    /**
96     * Append the character set specifications to a command.
97     *
98     * @param  string  $sql
99     * @param  \Illuminate\Database\Connection  $connection
100     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
101     * @return string
102     */
103    protected function compileCreateEncoding($sql, Connection $connection, Blueprint $blueprint)
104    {
105        // First we will set the character set if one has been set on either the create
106        // blueprint itself or on the root configuration for the connection that the
107        // table is being created on. We will add these to the create table query.
108        if (isset($blueprint->charset)) {
109            $sql .= ' default character set '.$blueprint->charset;
110        } elseif (! is_null($charset = $connection->getConfig('charset'))) {
111            $sql .= ' default character set '.$charset;
112        }
113
114        // Next we will add the collation to the create table statement if one has been
115        // added to either this create table blueprint or the configuration for this
116        // connection that the query is targeting. We'll add it to this SQL query.
117        if (isset($blueprint->collation)) {
118            $sql .= " collate '{$blueprint->collation}'";
119        } elseif (! is_null($collation = $connection->getConfig('collation'))) {
120            $sql .= " collate '{$collation}'";
121        }
122
123        return $sql;
124    }
125
126    /**
127     * Append the engine specifications to a command.
128     *
129     * @param  string  $sql
130     * @param  \Illuminate\Database\Connection  $connection
131     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
132     * @return string
133     */
134    protected function compileCreateEngine($sql, Connection $connection, Blueprint $blueprint)
135    {
136        if (isset($blueprint->engine)) {
137            return $sql.' engine = '.$blueprint->engine;
138        } elseif (! is_null($engine = $connection->getConfig('engine'))) {
139            return $sql.' engine = '.$engine;
140        }
141
142        return $sql;
143    }
144
145    /**
146     * Compile an add column command.
147     *
148     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
149     * @param  \Illuminate\Support\Fluent  $command
150     * @return string
151     */
152    public function compileAdd(Blueprint $blueprint, Fluent $command)
153    {
154        $columns = $this->prefixArray('add', $this->getColumns($blueprint));
155
156        return 'alter table '.$this->wrapTable($blueprint).' '.implode(', ', $columns);
157    }
158
159    /**
160     * Compile a primary key command.
161     *
162     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
163     * @param  \Illuminate\Support\Fluent  $command
164     * @return string
165     */
166    public function compilePrimary(Blueprint $blueprint, Fluent $command)
167    {
168        $command->name(null);
169
170        return $this->compileKey($blueprint, $command, 'primary key');
171    }
172
173    /**
174     * Compile a unique key command.
175     *
176     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
177     * @param  \Illuminate\Support\Fluent  $command
178     * @return string
179     */
180    public function compileUnique(Blueprint $blueprint, Fluent $command)
181    {
182        return $this->compileKey($blueprint, $command, 'unique');
183    }
184
185    /**
186     * Compile a plain index key command.
187     *
188     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
189     * @param  \Illuminate\Support\Fluent  $command
190     * @return string
191     */
192    public function compileIndex(Blueprint $blueprint, Fluent $command)
193    {
194        return $this->compileKey($blueprint, $command, 'index');
195    }
196
197    /**
198     * Compile a spatial index key command.
199     *
200     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
201     * @param  \Illuminate\Support\Fluent  $command
202     * @return string
203     */
204    public function compileSpatialIndex(Blueprint $blueprint, Fluent $command)
205    {
206        return $this->compileKey($blueprint, $command, 'spatial index');
207    }
208
209    /**
210     * Compile an index creation command.
211     *
212     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
213     * @param  \Illuminate\Support\Fluent  $command
214     * @param  string  $type
215     * @return string
216     */
217    protected function compileKey(Blueprint $blueprint, Fluent $command, $type)
218    {
219        return sprintf('alter table %s add %s %s%s(%s)',
220            $this->wrapTable($blueprint),
221            $type,
222            $this->wrap($command->index),
223            $command->algorithm ? ' using '.$command->algorithm : '',
224            $this->columnize($command->columns)
225        );
226    }
227
228    /**
229     * Compile a drop table command.
230     *
231     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
232     * @param  \Illuminate\Support\Fluent  $command
233     * @return string
234     */
235    public function compileDrop(Blueprint $blueprint, Fluent $command)
236    {
237        return 'drop table '.$this->wrapTable($blueprint);
238    }
239
240    /**
241     * Compile a drop table (if exists) command.
242     *
243     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
244     * @param  \Illuminate\Support\Fluent  $command
245     * @return string
246     */
247    public function compileDropIfExists(Blueprint $blueprint, Fluent $command)
248    {
249        return 'drop table if exists '.$this->wrapTable($blueprint);
250    }
251
252    /**
253     * Compile a drop column command.
254     *
255     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
256     * @param  \Illuminate\Support\Fluent  $command
257     * @return string
258     */
259    public function compileDropColumn(Blueprint $blueprint, Fluent $command)
260    {
261        $columns = $this->prefixArray('drop', $this->wrapArray($command->columns));
262
263        return 'alter table '.$this->wrapTable($blueprint).' '.implode(', ', $columns);
264    }
265
266    /**
267     * Compile a drop primary key command.
268     *
269     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
270     * @param  \Illuminate\Support\Fluent  $command
271     * @return string
272     */
273    public function compileDropPrimary(Blueprint $blueprint, Fluent $command)
274    {
275        return 'alter table '.$this->wrapTable($blueprint).' drop primary key';
276    }
277
278    /**
279     * Compile a drop unique key command.
280     *
281     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
282     * @param  \Illuminate\Support\Fluent  $command
283     * @return string
284     */
285    public function compileDropUnique(Blueprint $blueprint, Fluent $command)
286    {
287        $index = $this->wrap($command->index);
288
289        return "alter table {$this->wrapTable($blueprint)} drop index {$index}";
290    }
291
292    /**
293     * Compile a drop index command.
294     *
295     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
296     * @param  \Illuminate\Support\Fluent  $command
297     * @return string
298     */
299    public function compileDropIndex(Blueprint $blueprint, Fluent $command)
300    {
301        $index = $this->wrap($command->index);
302
303        return "alter table {$this->wrapTable($blueprint)} drop index {$index}";
304    }
305
306    /**
307     * Compile a drop spatial index command.
308     *
309     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
310     * @param  \Illuminate\Support\Fluent  $command
311     * @return string
312     */
313    public function compileDropSpatialIndex(Blueprint $blueprint, Fluent $command)
314    {
315        return $this->compileDropIndex($blueprint, $command);
316    }
317
318    /**
319     * Compile a drop foreign key command.
320     *
321     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
322     * @param  \Illuminate\Support\Fluent  $command
323     * @return string
324     */
325    public function compileDropForeign(Blueprint $blueprint, Fluent $command)
326    {
327        $index = $this->wrap($command->index);
328
329        return "alter table {$this->wrapTable($blueprint)} drop foreign key {$index}";
330    }
331
332    /**
333     * Compile a rename table command.
334     *
335     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
336     * @param  \Illuminate\Support\Fluent  $command
337     * @return string
338     */
339    public function compileRename(Blueprint $blueprint, Fluent $command)
340    {
341        $from = $this->wrapTable($blueprint);
342
343        return "rename table {$from} to ".$this->wrapTable($command->to);
344    }
345
346    /**
347     * Compile a rename index command.
348     *
349     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
350     * @param  \Illuminate\Support\Fluent $command
351     * @return string
352     */
353    public function compileRenameIndex(Blueprint $blueprint, Fluent $command)
354    {
355        return sprintf('alter table %s rename index %s to %s',
356            $this->wrapTable($blueprint),
357            $this->wrap($command->from),
358            $this->wrap($command->to)
359        );
360    }
361
362    /**
363     * Compile the SQL needed to drop all tables.
364     *
365     * @param  array  $tables
366     * @return string
367     */
368    public function compileDropAllTables($tables)
369    {
370        return 'drop table '.implode(',', $this->wrapArray($tables));
371    }
372
373    /**
374     * Compile the SQL needed to drop all views.
375     *
376     * @param  array  $views
377     * @return string
378     */
379    public function compileDropAllViews($views)
380    {
381        return 'drop view '.implode(',', $this->wrapArray($views));
382    }
383
384    /**
385     * Compile the SQL needed to retrieve all table names.
386     *
387     * @return string
388     */
389    public function compileGetAllTables()
390    {
391        return 'SHOW FULL TABLES WHERE table_type = \'BASE TABLE\'';
392    }
393
394    /**
395     * Compile the SQL needed to retrieve all view names.
396     *
397     * @return string
398     */
399    public function compileGetAllViews()
400    {
401        return 'SHOW FULL TABLES WHERE table_type = \'VIEW\'';
402    }
403
404    /**
405     * Compile the command to enable foreign key constraints.
406     *
407     * @return string
408     */
409    public function compileEnableForeignKeyConstraints()
410    {
411        return 'SET FOREIGN_KEY_CHECKS=1;';
412    }
413
414    /**
415     * Compile the command to disable foreign key constraints.
416     *
417     * @return string
418     */
419    public function compileDisableForeignKeyConstraints()
420    {
421        return 'SET FOREIGN_KEY_CHECKS=0;';
422    }
423
424    /**
425     * Create the column definition for a char type.
426     *
427     * @param  \Illuminate\Support\Fluent  $column
428     * @return string
429     */
430    protected function typeChar(Fluent $column)
431    {
432        return "char({$column->length})";
433    }
434
435    /**
436     * Create the column definition for a string type.
437     *
438     * @param  \Illuminate\Support\Fluent  $column
439     * @return string
440     */
441    protected function typeString(Fluent $column)
442    {
443        return "varchar({$column->length})";
444    }
445
446    /**
447     * Create the column definition for a text type.
448     *
449     * @param  \Illuminate\Support\Fluent  $column
450     * @return string
451     */
452    protected function typeText(Fluent $column)
453    {
454        return 'text';
455    }
456
457    /**
458     * Create the column definition for a medium text type.
459     *
460     * @param  \Illuminate\Support\Fluent  $column
461     * @return string
462     */
463    protected function typeMediumText(Fluent $column)
464    {
465        return 'mediumtext';
466    }
467
468    /**
469     * Create the column definition for a long text type.
470     *
471     * @param  \Illuminate\Support\Fluent  $column
472     * @return string
473     */
474    protected function typeLongText(Fluent $column)
475    {
476        return 'longtext';
477    }
478
479    /**
480     * Create the column definition for a big integer type.
481     *
482     * @param  \Illuminate\Support\Fluent  $column
483     * @return string
484     */
485    protected function typeBigInteger(Fluent $column)
486    {
487        return 'bigint';
488    }
489
490    /**
491     * Create the column definition for an integer type.
492     *
493     * @param  \Illuminate\Support\Fluent  $column
494     * @return string
495     */
496    protected function typeInteger(Fluent $column)
497    {
498        return 'int';
499    }
500
501    /**
502     * Create the column definition for a medium integer type.
503     *
504     * @param  \Illuminate\Support\Fluent  $column
505     * @return string
506     */
507    protected function typeMediumInteger(Fluent $column)
508    {
509        return 'mediumint';
510    }
511
512    /**
513     * Create the column definition for a tiny integer type.
514     *
515     * @param  \Illuminate\Support\Fluent  $column
516     * @return string
517     */
518    protected function typeTinyInteger(Fluent $column)
519    {
520        return 'tinyint';
521    }
522
523    /**
524     * Create the column definition for a small integer type.
525     *
526     * @param  \Illuminate\Support\Fluent  $column
527     * @return string
528     */
529    protected function typeSmallInteger(Fluent $column)
530    {
531        return 'smallint';
532    }
533
534    /**
535     * Create the column definition for a float type.
536     *
537     * @param  \Illuminate\Support\Fluent  $column
538     * @return string
539     */
540    protected function typeFloat(Fluent $column)
541    {
542        return $this->typeDouble($column);
543    }
544
545    /**
546     * Create the column definition for a double type.
547     *
548     * @param  \Illuminate\Support\Fluent  $column
549     * @return string
550     */
551    protected function typeDouble(Fluent $column)
552    {
553        if ($column->total && $column->places) {
554            return "double({$column->total}, {$column->places})";
555        }
556
557        return 'double';
558    }
559
560    /**
561     * Create the column definition for a decimal type.
562     *
563     * @param  \Illuminate\Support\Fluent  $column
564     * @return string
565     */
566    protected function typeDecimal(Fluent $column)
567    {
568        return "decimal({$column->total}, {$column->places})";
569    }
570
571    /**
572     * Create the column definition for a boolean type.
573     *
574     * @param  \Illuminate\Support\Fluent  $column
575     * @return string
576     */
577    protected function typeBoolean(Fluent $column)
578    {
579        return 'tinyint(1)';
580    }
581
582    /**
583     * Create the column definition for an enumeration type.
584     *
585     * @param  \Illuminate\Support\Fluent  $column
586     * @return string
587     */
588    protected function typeEnum(Fluent $column)
589    {
590        return sprintf('enum(%s)', $this->quoteString($column->allowed));
591    }
592
593    /**
594     * Create the column definition for a set enumeration type.
595     *
596     * @param  \Illuminate\Support\Fluent  $column
597     * @return string
598     */
599    protected function typeSet(Fluent $column)
600    {
601        return sprintf('set(%s)', $this->quoteString($column->allowed));
602    }
603
604    /**
605     * Create the column definition for a json type.
606     *
607     * @param  \Illuminate\Support\Fluent  $column
608     * @return string
609     */
610    protected function typeJson(Fluent $column)
611    {
612        return 'json';
613    }
614
615    /**
616     * Create the column definition for a jsonb type.
617     *
618     * @param  \Illuminate\Support\Fluent  $column
619     * @return string
620     */
621    protected function typeJsonb(Fluent $column)
622    {
623        return 'json';
624    }
625
626    /**
627     * Create the column definition for a date type.
628     *
629     * @param  \Illuminate\Support\Fluent  $column
630     * @return string
631     */
632    protected function typeDate(Fluent $column)
633    {
634        return 'date';
635    }
636
637    /**
638     * Create the column definition for a date-time type.
639     *
640     * @param  \Illuminate\Support\Fluent  $column
641     * @return string
642     */
643    protected function typeDateTime(Fluent $column)
644    {
645        $columnType = $column->precision ? "datetime($column->precision)" : 'datetime';
646
647        return $column->useCurrent ? "$columnType default CURRENT_TIMESTAMP" : $columnType;
648    }
649
650    /**
651     * Create the column definition for a date-time (with time zone) type.
652     *
653     * @param  \Illuminate\Support\Fluent  $column
654     * @return string
655     */
656    protected function typeDateTimeTz(Fluent $column)
657    {
658        return $this->typeDateTime($column);
659    }
660
661    /**
662     * Create the column definition for a time type.
663     *
664     * @param  \Illuminate\Support\Fluent  $column
665     * @return string
666     */
667    protected function typeTime(Fluent $column)
668    {
669        return $column->precision ? "time($column->precision)" : 'time';
670    }
671
672    /**
673     * Create the column definition for a time (with time zone) type.
674     *
675     * @param  \Illuminate\Support\Fluent  $column
676     * @return string
677     */
678    protected function typeTimeTz(Fluent $column)
679    {
680        return $this->typeTime($column);
681    }
682
683    /**
684     * Create the column definition for a timestamp type.
685     *
686     * @param  \Illuminate\Support\Fluent  $column
687     * @return string
688     */
689    protected function typeTimestamp(Fluent $column)
690    {
691        $columnType = $column->precision ? "timestamp($column->precision)" : 'timestamp';
692
693        return $column->useCurrent ? "$columnType default CURRENT_TIMESTAMP" : $columnType;
694    }
695
696    /**
697     * Create the column definition for a timestamp (with time zone) type.
698     *
699     * @param  \Illuminate\Support\Fluent  $column
700     * @return string
701     */
702    protected function typeTimestampTz(Fluent $column)
703    {
704        return $this->typeTimestamp($column);
705    }
706
707    /**
708     * Create the column definition for a year type.
709     *
710     * @param  \Illuminate\Support\Fluent  $column
711     * @return string
712     */
713    protected function typeYear(Fluent $column)
714    {
715        return 'year';
716    }
717
718    /**
719     * Create the column definition for a binary type.
720     *
721     * @param  \Illuminate\Support\Fluent  $column
722     * @return string
723     */
724    protected function typeBinary(Fluent $column)
725    {
726        return 'blob';
727    }
728
729    /**
730     * Create the column definition for a uuid type.
731     *
732     * @param  \Illuminate\Support\Fluent  $column
733     * @return string
734     */
735    protected function typeUuid(Fluent $column)
736    {
737        return 'char(36)';
738    }
739
740    /**
741     * Create the column definition for an IP address type.
742     *
743     * @param  \Illuminate\Support\Fluent  $column
744     * @return string
745     */
746    protected function typeIpAddress(Fluent $column)
747    {
748        return 'varchar(45)';
749    }
750
751    /**
752     * Create the column definition for a MAC address type.
753     *
754     * @param  \Illuminate\Support\Fluent  $column
755     * @return string
756     */
757    protected function typeMacAddress(Fluent $column)
758    {
759        return 'varchar(17)';
760    }
761
762    /**
763     * Create the column definition for a spatial Geometry type.
764     *
765     * @param  \Illuminate\Support\Fluent  $column
766     * @return string
767     */
768    public function typeGeometry(Fluent $column)
769    {
770        return 'geometry';
771    }
772
773    /**
774     * Create the column definition for a spatial Point type.
775     *
776     * @param  \Illuminate\Support\Fluent  $column
777     * @return string
778     */
779    public function typePoint(Fluent $column)
780    {
781        return 'point';
782    }
783
784    /**
785     * Create the column definition for a spatial LineString type.
786     *
787     * @param  \Illuminate\Support\Fluent  $column
788     * @return string
789     */
790    public function typeLineString(Fluent $column)
791    {
792        return 'linestring';
793    }
794
795    /**
796     * Create the column definition for a spatial Polygon type.
797     *
798     * @param  \Illuminate\Support\Fluent  $column
799     * @return string
800     */
801    public function typePolygon(Fluent $column)
802    {
803        return 'polygon';
804    }
805
806    /**
807     * Create the column definition for a spatial GeometryCollection type.
808     *
809     * @param  \Illuminate\Support\Fluent  $column
810     * @return string
811     */
812    public function typeGeometryCollection(Fluent $column)
813    {
814        return 'geometrycollection';
815    }
816
817    /**
818     * Create the column definition for a spatial MultiPoint type.
819     *
820     * @param  \Illuminate\Support\Fluent  $column
821     * @return string
822     */
823    public function typeMultiPoint(Fluent $column)
824    {
825        return 'multipoint';
826    }
827
828    /**
829     * Create the column definition for a spatial MultiLineString type.
830     *
831     * @param  \Illuminate\Support\Fluent  $column
832     * @return string
833     */
834    public function typeMultiLineString(Fluent $column)
835    {
836        return 'multilinestring';
837    }
838
839    /**
840     * Create the column definition for a spatial MultiPolygon type.
841     *
842     * @param  \Illuminate\Support\Fluent  $column
843     * @return string
844     */
845    public function typeMultiPolygon(Fluent $column)
846    {
847        return 'multipolygon';
848    }
849
850    /**
851     * Create the column definition for a generated, computed column type.
852     *
853     * @param  \Illuminate\Support\Fluent  $column
854     * @return void
855     *
856     * @throws \RuntimeException
857     */
858    protected function typeComputed(Fluent $column)
859    {
860        throw new RuntimeException('This database driver requires a type, see the virtualAs / storedAs modifiers.');
861    }
862
863    /**
864     * Get the SQL for a generated virtual column modifier.
865     *
866     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
867     * @param  \Illuminate\Support\Fluent  $column
868     * @return string|null
869     */
870    protected function modifyVirtualAs(Blueprint $blueprint, Fluent $column)
871    {
872        if (! is_null($column->virtualAs)) {
873            return " as ({$column->virtualAs})";
874        }
875    }
876
877    /**
878     * Get the SQL for a generated stored column modifier.
879     *
880     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
881     * @param  \Illuminate\Support\Fluent  $column
882     * @return string|null
883     */
884    protected function modifyStoredAs(Blueprint $blueprint, Fluent $column)
885    {
886        if (! is_null($column->storedAs)) {
887            return " as ({$column->storedAs}) stored";
888        }
889    }
890
891    /**
892     * Get the SQL for an unsigned column modifier.
893     *
894     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
895     * @param  \Illuminate\Support\Fluent  $column
896     * @return string|null
897     */
898    protected function modifyUnsigned(Blueprint $blueprint, Fluent $column)
899    {
900        if ($column->unsigned) {
901            return ' unsigned';
902        }
903    }
904
905    /**
906     * Get the SQL for a character set column modifier.
907     *
908     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
909     * @param  \Illuminate\Support\Fluent  $column
910     * @return string|null
911     */
912    protected function modifyCharset(Blueprint $blueprint, Fluent $column)
913    {
914        if (! is_null($column->charset)) {
915            return ' character set '.$column->charset;
916        }
917    }
918
919    /**
920     * Get the SQL for a collation column modifier.
921     *
922     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
923     * @param  \Illuminate\Support\Fluent  $column
924     * @return string|null
925     */
926    protected function modifyCollate(Blueprint $blueprint, Fluent $column)
927    {
928        if (! is_null($column->collation)) {
929            return " collate '{$column->collation}'";
930        }
931    }
932
933    /**
934     * Get the SQL for a nullable column modifier.
935     *
936     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
937     * @param  \Illuminate\Support\Fluent  $column
938     * @return string|null
939     */
940    protected function modifyNullable(Blueprint $blueprint, Fluent $column)
941    {
942        if (is_null($column->virtualAs) && is_null($column->storedAs)) {
943            return $column->nullable ? ' null' : ' not null';
944        }
945    }
946
947    /**
948     * Get the SQL for a default column modifier.
949     *
950     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
951     * @param  \Illuminate\Support\Fluent  $column
952     * @return string|null
953     */
954    protected function modifyDefault(Blueprint $blueprint, Fluent $column)
955    {
956        if (! is_null($column->default)) {
957            return ' default '.$this->getDefaultValue($column->default);
958        }
959    }
960
961    /**
962     * Get the SQL for an auto-increment column modifier.
963     *
964     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
965     * @param  \Illuminate\Support\Fluent  $column
966     * @return string|null
967     */
968    protected function modifyIncrement(Blueprint $blueprint, Fluent $column)
969    {
970        if (in_array($column->type, $this->serials) && $column->autoIncrement) {
971            return ' auto_increment primary key';
972        }
973    }
974
975    /**
976     * Get the SQL for a "first" column modifier.
977     *
978     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
979     * @param  \Illuminate\Support\Fluent  $column
980     * @return string|null
981     */
982    protected function modifyFirst(Blueprint $blueprint, Fluent $column)
983    {
984        if (! is_null($column->first)) {
985            return ' first';
986        }
987    }
988
989    /**
990     * Get the SQL for an "after" column modifier.
991     *
992     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
993     * @param  \Illuminate\Support\Fluent  $column
994     * @return string|null
995     */
996    protected function modifyAfter(Blueprint $blueprint, Fluent $column)
997    {
998        if (! is_null($column->after)) {
999            return ' after '.$this->wrap($column->after);
1000        }
1001    }
1002
1003    /**
1004     * Get the SQL for a "comment" column modifier.
1005     *
1006     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
1007     * @param  \Illuminate\Support\Fluent  $column
1008     * @return string|null
1009     */
1010    protected function modifyComment(Blueprint $blueprint, Fluent $column)
1011    {
1012        if (! is_null($column->comment)) {
1013            return " comment '".addslashes($column->comment)."'";
1014        }
1015    }
1016
1017    /**
1018     * Get the SQL for a SRID column modifier.
1019     *
1020     * @param  \Illuminate\Database\Schema\Blueprint  $blueprint
1021     * @param  \Illuminate\Support\Fluent  $column
1022     * @return string|null
1023     */
1024    protected function modifySrid(Blueprint $blueprint, Fluent $column)
1025    {
1026        if (! is_null($column->srid) && is_int($column->srid) && $column->srid > 0) {
1027            return ' srid '.$column->srid;
1028        }
1029    }
1030
1031    /**
1032     * Wrap a single string in keyword identifiers.
1033     *
1034     * @param  string  $value
1035     * @return string
1036     */
1037    protected function wrapValue($value)
1038    {
1039        if ($value !== '*') {
1040            return '`'.str_replace('`', '``', $value).'`';
1041        }
1042
1043        return $value;
1044    }
1045}
1046