Completed
Push — master ( 8512ea...2b9498 )
by Arjay
02:00
created

OracleGrammar::addPrimaryKeys()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 12
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

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

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
722
    {
723
        if ($this->isReserved($value)) {
724
            return parent::wrapValue($value);
725
        }
726
727
        return $value !== '*' ? sprintf($this->wrapper, $value) : $value;
728
    }
729
}
730