Completed
Push — master ( ecc8a1...4e4791 )
by Arjay
53:51 queued 38:55
created

OracleGrammar::typeJson()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 4
ccs 2
cts 2
cp 1
crap 1
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace Yajra\Oci8\Schema\Grammars;
4
5
use Illuminate\Support\Str;
6
use Illuminate\Support\Fluent;
7
use Illuminate\Database\Connection;
8
use Yajra\Oci8\OracleReservedWords;
9
use Illuminate\Database\Schema\Blueprint;
10
use Illuminate\Database\Schema\Grammars\Grammar;
11
12
class OracleGrammar extends Grammar
13
{
14
    use OracleReservedWords;
15
16
    /**
17
     * The keyword identifier wrapper format.
18
     *
19
     * @var string
20
     */
21
    protected $wrapper = '%s';
22
23
    /**
24
     * The possible column modifiers.
25
     *
26
     * @var array
27
     */
28
    protected $modifiers = ['Increment', 'Nullable', 'Default'];
29
30
    /**
31
     * The possible column serials.
32
     *
33
     * @var array
34
     */
35
    protected $serials = ['bigInteger', 'integer', 'mediumInteger', 'smallInteger', 'tinyInteger'];
36
37
    /**
38
     * @var string
39
     */
40
    protected $schema_prefix = '';
41
42
    /**
43
     * If this Grammar supports schema changes wrapped in a transaction.
44
     *
45
     * @var bool
46
     */
47
    protected $transactions = true;
48
49
    /**
50
     * Compile a create table command.
51
     *
52
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
53
     * @param  \Illuminate\Support\Fluent $command
54
     * @return string
55
     */
56 30
    public function compileCreate(Blueprint $blueprint, Fluent $command)
57
    {
58 30
        $columns = implode(', ', $this->getColumns($blueprint));
59
60 30
        $sql = 'create table ' . $this->wrapTable($blueprint) . " ( $columns";
61
62
        /*
63
         * To be able to name the primary/foreign keys when the table is
64
         * initially created we will need to check for a primary/foreign
65
         * key commands and add the columns to the table's declaration
66
         * here so they can be created on the tables.
67
         */
68 30
        $sql .= (string) $this->addForeignKeys($blueprint);
69
70 30
        $sql .= (string) $this->addPrimaryKeys($blueprint);
71
72 30
        $sql .= ' )';
73
74 30
        return $sql;
75
    }
76
77
    /**
78
     * Wrap a table in keyword identifiers.
79
     *
80
     * @param  mixed $table
81
     * @return string
82
     */
83 177
    public function wrapTable($table)
84
    {
85 177
        return $this->getSchemaPrefix() . parent::wrapTable($table);
86
    }
87
88
    /**
89
     * Get the schema prefix.
90
     *
91
     * @return string
92
     */
93 177
    public function getSchemaPrefix()
94
    {
95 177
        return ! empty($this->schema_prefix) ? $this->schema_prefix . '.' : '';
96
    }
97
98
    /**
99
     * Set the schema prefix.
100
     *
101
     * @param string $prefix
102
     */
103
    public function setSchemaPrefix($prefix)
104
    {
105
        $this->schema_prefix = $prefix;
106
    }
107
108
    /**
109
     * Get the foreign key syntax for a table creation statement.
110
     *
111
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
112
     * @return string
113
     */
114 30
    protected function addForeignKeys(Blueprint $blueprint)
115
    {
116 30
        $sql = '';
117
118 30
        $foreigns = $this->getCommandsByName($blueprint, 'foreign');
119
120
        // Once we have all the foreign key commands for the table creation statement
121
        // we'll loop through each of them and add them to the create table SQL we
122
        // are building
123 30
        foreach ($foreigns as $foreign) {
124 9
            $on = $this->wrapTable($foreign->on);
125
126 9
            $columns = $this->columnize($foreign->columns);
127
128 9
            $onColumns = $this->columnize((array) $foreign->references);
129
130 9
            $sql .= ", constraint {$foreign->index} foreign key ( {$columns} ) references {$on} ( {$onColumns} )";
131
132
            // Once we have the basic foreign key creation statement constructed we can
133
            // build out the syntax for what should happen on an update or delete of
134
            // the affected columns, which will get something like "cascade", etc.
135 9
            if (! is_null($foreign->onDelete)) {
136 5
                $sql .= " on delete {$foreign->onDelete}";
137 2
            }
138 20
        }
139
140 30
        return $sql;
141
    }
142
143
    /**
144
     * Get the primary key syntax for a table creation statement.
145
     *
146
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
147
     * @return string|null
148
     */
149 120
    protected function addPrimaryKeys(Blueprint $blueprint)
150
    {
151 120
        $primary = $this->getCommandByName($blueprint, 'primary');
152
153 120
        if (! is_null($primary)) {
154 51
            $columns = $this->columnize($primary->columns);
155
156 51
            return ", constraint {$primary->index} primary key ( {$columns} )";
157
        }
158
159 75
        return '';
160
    }
161
162
    /**
163
     * Compile the query to determine if a table exists.
164
     *
165
     * @return string
166
     */
167 3
    public function compileTableExists()
168
    {
169 3
        return 'select * from all_tables where upper(owner) = upper(?) and upper(table_name) = upper(?)';
170
    }
171
172
    /**
173
     * Compile the query to determine the list of columns.
174
     *
175
     * @param string $database
176
     * @param string $table
177
     * @return string
178
     */
179 3
    public function compileColumnExists($database, $table)
180
    {
181 3
        return "select column_name from all_tab_cols where upper(owner) = upper('{$database}') and upper(table_name) = upper('{$table}')";
182
    }
183
184
    /**
185
     * Compile an add column command.
186
     *
187
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
188
     * @param  \Illuminate\Support\Fluent $command
189
     * @return string
190
     */
191 90
    public function compileAdd(Blueprint $blueprint, Fluent $command)
192
    {
193 90
        $columns = implode(', ', $this->getColumns($blueprint));
194
195 90
        $sql = 'alter table ' . $this->wrapTable($blueprint) . " add ( $columns";
196
197 90
        $sql .= (string) $this->addPrimaryKeys($blueprint);
198
199 90
        return $sql .= ' )';
200
    }
201
202
    /**
203
     * Compile a primary key command.
204
     *
205
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
206
     * @param  \Illuminate\Support\Fluent $command
207
     * @return string
208
     */
209 27
    public function compilePrimary(Blueprint $blueprint, Fluent $command)
210
    {
211 27
        $create = $this->getCommandByName($blueprint, 'create');
212
213 27
        if (is_null($create)) {
214 9
            $columns = $this->columnize($command->columns);
215
216 9
            $table = $this->wrapTable($blueprint);
217
218 9
            return "alter table {$table} add constraint {$command->index} primary key ({$columns})";
219
        }
220 18
    }
221
222
    /**
223
     * Compile a foreign key command.
224
     *
225
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
226
     * @param  \Illuminate\Support\Fluent $command
227
     * @return string|void
228
     */
229 15
    public function compileForeign(Blueprint $blueprint, Fluent $command)
230
    {
231 15
        $create = $this->getCommandByName($blueprint, 'create');
232
233 15
        if (is_null($create)) {
234 6
            $table = $this->wrapTable($blueprint);
235
236 6
            $on = $this->wrapTable($command->on);
237
238
            // We need to prepare several of the elements of the foreign key definition
239
            // before we can create the SQL, such as wrapping the tables and convert
240
            // an array of columns to comma-delimited strings for the SQL queries.
241 6
            $columns = $this->columnize($command->columns);
242
243 6
            $onColumns = $this->columnize((array) $command->references);
244
245 6
            $sql = "alter table {$table} add constraint {$command->index} ";
246
247 6
            $sql .= "foreign key ( {$columns} ) references {$on} ( {$onColumns} )";
248
249
            // Once we have the basic foreign key creation statement constructed we can
250
            // build out the syntax for what should happen on an update or delete of
251
            // the affected columns, which will get something like "cascade", etc.
252 6
            if (! is_null($command->onDelete)) {
253 3
                $sql .= " on delete {$command->onDelete}";
254 2
            }
255
256 6
            return $sql;
257
        }
258 9
    }
259
260
    /**
261
     * Compile a unique key command.
262
     *
263
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
264
     * @param  \Illuminate\Support\Fluent $command
265
     * @return string
266
     */
267 9
    public function compileUnique(Blueprint $blueprint, Fluent $command)
268
    {
269 9
        return 'alter table ' . $this->wrapTable($blueprint) . " add constraint {$command->index} unique ( " . $this->columnize($command->columns) . ' )';
270
    }
271
272
    /**
273
     * Compile a plain index key command.
274
     *
275
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
276
     * @param  \Illuminate\Support\Fluent $command
277
     * @return string
278
     */
279 3
    public function compileIndex(Blueprint $blueprint, Fluent $command)
280
    {
281 3
        return "create index {$command->index} on " . $this->wrapTable($blueprint) . ' ( ' . $this->columnize($command->columns) . ' )';
282
    }
283
284
    /**
285
     * Compile a drop table command.
286
     *
287
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
288
     * @param  \Illuminate\Support\Fluent $command
289
     * @return string
290
     */
291 6
    public function compileDrop(Blueprint $blueprint, Fluent $command)
292
    {
293 6
        return 'drop table ' . $this->wrapTable($blueprint);
294
    }
295
296
    /**
297
     * Compile a drop table (if exists) command.
298
     *
299
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
300
     * @param  \Illuminate\Support\Fluent $command
301
     * @return string
302
     */
303
    public function compileDropIfExists(Blueprint $blueprint, Fluent $command)
304
    {
305
        $table = $this->wrapTable($blueprint);
306
307
        return "declare c int;
308
            begin
309
               select count(*) into c from user_tables where table_name = upper('$table');
310
               if c = 1 then
311
                  execute immediate 'drop table $table';
312
               end if;
313
            end;";
314
    }
315
316
    /**
317
     * Compile a drop column command.
318
     *
319
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
320
     * @param  \Illuminate\Support\Fluent $command
321
     * @return string
322
     */
323 6
    public function compileDropColumn(Blueprint $blueprint, Fluent $command)
324
    {
325 6
        $columns = $this->wrapArray($command->columns);
326
327 6
        $table = $this->wrapTable($blueprint);
328
329 6
        return 'alter table ' . $table . ' drop ( ' . implode(', ', $columns) . ' )';
330
    }
331
332
    /**
333
     * Compile a drop primary key command.
334
     *
335
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
336
     * @param  \Illuminate\Support\Fluent $command
337
     * @return string
338
     */
339 3
    public function compileDropPrimary(Blueprint $blueprint, Fluent $command)
340
    {
341 3
        return $this->dropConstraint($blueprint, $command, 'primary');
342
    }
343
344
    /**
345
     * @param Blueprint $blueprint
346
     * @param Fluent $command
347
     * @param string $type
348
     * @return string
349
     */
350 12
    private function dropConstraint(Blueprint $blueprint, Fluent $command, $type)
351
    {
352 12
        $table = $this->wrapTable($blueprint);
353 12
        $index = substr($command->index, 0, 30);
354
355 12
        if ($type === 'index') {
356 3
            return "drop index {$index}";
357
        }
358
359 9
        return "alter table {$table} drop constraint {$index}";
360
    }
361
362
    /**
363
     * Compile a drop unique key command.
364
     *
365
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
366
     * @param  \Illuminate\Support\Fluent $command
367
     * @return string
368
     */
369 3
    public function compileDropUnique(Blueprint $blueprint, Fluent $command)
370
    {
371 3
        return $this->dropConstraint($blueprint, $command, 'unique');
372
    }
373
374
    /**
375
     * Compile a drop index command.
376
     *
377
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
378
     * @param  \Illuminate\Support\Fluent $command
379
     * @return string
380
     */
381 3
    public function compileDropIndex(Blueprint $blueprint, Fluent $command)
382
    {
383 3
        return $this->dropConstraint($blueprint, $command, 'index');
384
    }
385
386
    /**
387
     * Compile a drop foreign key command.
388
     *
389
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
390
     * @param  \Illuminate\Support\Fluent $command
391
     * @return string
392
     */
393 3
    public function compileDropForeign(Blueprint $blueprint, Fluent $command)
394
    {
395 3
        return $this->dropConstraint($blueprint, $command, 'foreign');
396
    }
397
398
    /**
399
     * Compile a rename table command.
400
     *
401
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
402
     * @param  \Illuminate\Support\Fluent $command
403
     * @return string
404
     */
405 6
    public function compileRename(Blueprint $blueprint, Fluent $command)
406
    {
407 6
        $from = $this->wrapTable($blueprint);
408
409 6
        return "alter table {$from} rename to " . $this->wrapTable($command->to);
410
    }
411
412
    /**
413
     * Compile a rename column command.
414
     *
415
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
416
     * @param  \Illuminate\Support\Fluent $command
417
     * @param  \Illuminate\Database\Connection $connection
418
     * @return array
419
     */
420
    public function compileRenameColumn(Blueprint $blueprint, Fluent $command, Connection $connection)
421
    {
422
        $table = $this->wrapTable($blueprint);
423
424
        $rs    = [];
425
        $rs[0] = 'alter table ' . $table . ' rename column ' . $command->from . ' to ' . $command->to;
426
427
        return (array) $rs;
428
    }
429
430
    /**
431
     * Create the column definition for a char type.
432
     *
433
     * @param  \Illuminate\Support\Fluent $column
434
     * @return string
435
     */
436 3
    protected function typeChar(Fluent $column)
437
    {
438 3
        return "char({$column->length})";
439
    }
440
441
    /**
442
     * Create the column definition for a string type.
443
     *
444
     * @param  \Illuminate\Support\Fluent $column
445
     * @return string
446
     */
447 42
    protected function typeString(Fluent $column)
448
    {
449 42
        return "varchar2({$column->length})";
450
    }
451
452
    /**
453
     * Create column definition for a nvarchar type.
454
     *
455
     * @param \Illuminate\Support\Fluent $column
456
     * @return string
457
     */
458 3
    protected function typeNvarchar2(Fluent $column)
459
    {
460 3
        return "nvarchar2({$column->length})";
461
    }
462
463
    /**
464
     * Create the column definition for a text type.
465
     *
466
     * @param  \Illuminate\Support\Fluent $column
467
     * @return string
468
     */
469 3
    protected function typeText(Fluent $column)
470
    {
471 3
        return 'clob';
472
    }
473
474
    /**
475
     * Create the column definition for a medium text type.
476
     *
477
     * @param  \Illuminate\Support\Fluent $column
478
     * @return string
479
     */
480 3
    protected function typeMediumText(Fluent $column)
481
    {
482 3
        return 'clob';
483
    }
484
485
    /**
486
     * Create the column definition for a long text type.
487
     *
488
     * @param  \Illuminate\Support\Fluent $column
489
     * @return string
490
     */
491 3
    protected function typeLongText(Fluent $column)
492
    {
493 3
        return 'clob';
494
    }
495
496
    /**
497
     * Create the column definition for a integer type.
498
     *
499
     * @param  \Illuminate\Support\Fluent $column
500
     * @return string
501
     */
502 48
    protected function typeInteger(Fluent $column)
503
    {
504 48
        $length = ($column->length) ? $column->length : 10;
505
506 48
        return "number({$length},0)";
507
    }
508
509
    /**
510
     * Create the column definition for a integer type.
511
     *
512
     * @param  \Illuminate\Support\Fluent $column
513
     * @return string
514
     */
515 3
    protected function typeBigInteger(Fluent $column)
516
    {
517 3
        $length = ($column->length) ? $column->length : 19;
518
519 3
        return "number({$length},0)";
520
    }
521
522
    /**
523
     * Create the column definition for a medium integer type.
524
     *
525
     * @param  \Illuminate\Support\Fluent $column
526
     * @return string
527
     */
528 3
    protected function typeMediumInteger(Fluent $column)
529
    {
530 3
        $length = ($column->length) ? $column->length : 7;
531
532 3
        return "number({$length},0)";
533
    }
534
535
    /**
536
     * Create the column definition for a small integer type.
537
     *
538
     * @param  \Illuminate\Support\Fluent $column
539
     * @return string
540
     */
541 3
    protected function typeSmallInteger(Fluent $column)
542
    {
543 3
        $length = ($column->length) ? $column->length : 5;
544
545 3
        return "number({$length},0)";
546
    }
547
548
    /**
549
     * Create the column definition for a tiny integer type.
550
     *
551
     * @param  \Illuminate\Support\Fluent $column
552
     * @return string
553
     */
554 3
    protected function typeTinyInteger(Fluent $column)
555
    {
556 3
        $length = ($column->length) ? $column->length : 3;
557
558 3
        return "number({$length},0)";
559
    }
560
561
    /**
562
     * Create the column definition for a float type.
563
     *
564
     * @param  \Illuminate\Support\Fluent $column
565
     * @return string
566
     */
567 3
    protected function typeFloat(Fluent $column)
568
    {
569 3
        return "number({$column->total}, {$column->places})";
570
    }
571
572
    /**
573
     * Create the column definition for a double type.
574
     *
575
     * @param  \Illuminate\Support\Fluent $column
576
     * @return string
577
     */
578 3
    protected function typeDouble(Fluent $column)
579
    {
580 3
        return "number({$column->total}, {$column->places})";
581
    }
582
583
    /**
584
     * Create the column definition for a decimal type.
585
     *
586
     * @param  \Illuminate\Support\Fluent $column
587
     * @return string
588
     */
589 3
    protected function typeDecimal(Fluent $column)
590
    {
591 3
        return "number({$column->total}, {$column->places})";
592
    }
593
594
    /**
595
     * Create the column definition for a boolean type.
596
     *
597
     * @param  \Illuminate\Support\Fluent $column
598
     * @return string
599
     */
600 3
    protected function typeBoolean(Fluent $column)
601
    {
602 3
        return 'char(1)';
603
    }
604
605
    /**
606
     * Create the column definition for a enum type.
607
     *
608
     * @param  \Illuminate\Support\Fluent $column
609
     * @return string
610
     */
611 6
    protected function typeEnum(Fluent $column)
612
    {
613 6
        $length = ($column->length) ? $column->length : 255;
614
615 6
        return "varchar2({$length})";
616
    }
617
618
    /**
619
     * Create the column definition for a date type.
620
     *
621
     * @param  \Illuminate\Support\Fluent $column
622
     * @return string
623
     */
624 3
    protected function typeDate(Fluent $column)
625
    {
626 3
        return 'date';
627
    }
628
629
    /**
630
     * Create the column definition for a date-time type.
631
     *
632
     * @param  \Illuminate\Support\Fluent $column
633
     * @return string
634
     */
635 3
    protected function typeDateTime(Fluent $column)
636
    {
637 3
        return 'date';
638
    }
639
640
    /**
641
     * Create the column definition for a time type.
642
     *
643
     * @param  \Illuminate\Support\Fluent $column
644
     * @return string
645
     */
646 3
    protected function typeTime(Fluent $column)
647
    {
648 3
        return 'date';
649
    }
650
651
    /**
652
     * Create the column definition for a timestamp type.
653
     *
654
     * @param  \Illuminate\Support\Fluent $column
655
     * @return string
656
     */
657 9
    protected function typeTimestamp(Fluent $column)
658
    {
659 9
        return 'timestamp';
660
    }
661
662
    /**
663
     * Create the column definition for a timestamp type with timezone.
664
     *
665
     * @param Fluent $column
666
     * @return string
667
     */
668 6
    protected function typeTimestampTz(Fluent $column)
669
    {
670 6
        return 'timestamp with time zone';
671
    }
672
673
    /**
674
     * Create the column definition for a binary type.
675
     *
676
     * @param  \Illuminate\Support\Fluent $column
677
     * @return string
678
     */
679 3
    protected function typeBinary(Fluent $column)
680
    {
681 3
        return 'blob';
682
    }
683
684
    /**
685
     * Create the column definition for a uuid type.
686
     *
687
     * @param  \Illuminate\Support\Fluent  $column
688
     * @return string
689
     */
690
    protected function typeUuid(Fluent $column)
691 120
    {
692
        return 'char(36)';
693
    }
694 120
695 120
    /**
696 6
     * Create the column definition for a json type.
697 4
     *
698
     * @param  \Illuminate\Support\Fluent $column
699 120
     * @return string
700 120
     */
701
    protected function typeJson(Fluent $column)
702 120
    {
703 9
        return 'clob';
704
    }
705
706 117
    /**
707
     * Create the column definition for a jsonb type.
708
     *
709
     * @param  \Illuminate\Support\Fluent $column
710
     * @return string
711
     */
712
    protected function typeJsonb(Fluent $column)
713
    {
714
        return 'clob';
715
    }
716 120
717
    /**
718
     * Get the SQL for a nullable column modifier.
719 120
     *
720
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
721
     * @param  \Illuminate\Support\Fluent $column
722
     * @return string
723
     */
724
    protected function modifyNullable(Blueprint $blueprint, Fluent $column)
725
    {
726
        // check if field is declared as enum
727
        $enum = '';
728
        if (count((array) $column->allowed)) {
729 120
            $enum = " check ({$column->name} in ('" . implode("', '", $column->allowed) . "'))";
730
        }
731 120
732 33
        $null = $column->nullable ? ' null' : ' not null';
733 22
        $null .= $enum;
734 120
735
        if (! is_null($column->default)) {
736
            return ' default ' . $this->getDefaultValue($column->default) . $null;
737
        }
738
739
        return $null;
740
    }
741
742 177
    /**
743
     * Get the SQL for a default column modifier.
744 177
     *
745 3
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
746
     * @param  \Illuminate\Support\Fluent $column
747
     * @return string
748 177
     */
749
    protected function modifyDefault(Blueprint $blueprint, Fluent $column)
750
    {
751
        // implemented @modifyNullable
752
        return '';
753
    }
754
755
    /**
756
     * Get the SQL for an auto-increment column modifier.
757
     *
758
     * @param  \Illuminate\Database\Schema\Blueprint $blueprint
759
     * @param  \Illuminate\Support\Fluent $column
760
     * @return string|null
761
     */
762
    protected function modifyIncrement(Blueprint $blueprint, Fluent $column)
763
    {
764
        if (in_array($column->type, $this->serials) && $column->autoIncrement) {
765
            $blueprint->primary($column->name);
766
        }
767
    }
768
769
    /**
770
     * Wrap a single string in keyword identifiers.
771
     *
772
     * @param  string $value
773
     * @return string
774
     */
775
    protected function wrapValue($value)
776
    {
777
        if ($this->isReserved($value)) {
778
            return Str::lower(parent::wrapValue($value));
779
        }
780
781
        return $value !== '*' ? sprintf($this->wrapper, $value) : $value;
782
    }
783
}
784