Passed
Pull Request — next (#179)
by Bas
06:33 queued 01:29
created

Grammar::compileHasColumn()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 24
Code Lines 16

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 16
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 24
ccs 18
cts 18
cp 1
crap 2
rs 9.7333
1
<?php
2
3
declare(strict_types=1);
4
5
namespace LaravelFreelancerNL\Aranguent\Schema;
6
7
use Illuminate\Database\Schema\Grammars\Grammar as IlluminateGrammar;
8
use Illuminate\Support\Fluent;
9
use LaravelFreelancerNL\FluentAQL\QueryBuilder;
10
11
class Grammar extends IlluminateGrammar
12
{
13
    /**
14
     * ArangoDB handles transactions itself. However most schema actions
15
     * are not done through queries but rather through commands.
16
     * So we just run schema actions sequentially.
17
     *
18
     * @var bool
19
     */
20
    protected $transactions = false;
21
22
    /**
23
     * Compile AQL to check if an attribute is in use within a document in the collection.
24
     * If multiple attributes are set then all must be set in one document.
25
     *
26
     * @param string $table
27
     * @return Fluent
28
     * @throws BindException
29
     */
30 4
    public function compileColumns($table, Fluent $command)
31
    {
32 4
        $command->bindings = [
33 4
            '@collection' => $table,
34 4
        ];
35
36 4
        $command->aqb = sprintf(
37 4
            'LET rawColumns = MERGE_RECURSIVE(
38
  (
39
	FOR doc IN @@collection
40
		LET fields = ATTRIBUTES(doc, true, true)
41
		FOR field IN fields
42
		  RETURN {
43
				[field]: {
44
				  [TYPENAME(doc[field])]: true
45
				}
46
		  }
47
  )
48
)
49
FOR column IN ATTRIBUTES(rawColumns)
50
  RETURN {
51
    name: column,
52
    types: ATTRIBUTES(rawColumns[column])
53 4
  }',
54 4
            $table,
55 4
        );
56
57 4
        return $command;
58
    }
59
    /**
60
     * Compile AQL to check if an attribute is in use within a document in the collection.
61
     * If multiple attributes are set then all must be set in one document.
62
     *
63
     * @param string $table
64
     * @return Fluent
65
     * @throws BindException
66
     */
67 7
    public function compileHasColumn($table, Fluent $command)
68
    {
69 7
        $attributes = $command->getAttributes();
70
71 7
        $aqb = new QueryBuilder();
72
73 7
        $filter = [];
74 7
        foreach ($attributes['columns'] as $column) {
75 7
            $filter[] = [$aqb->rawExpression('HAS(doc, \'' . $column . '\')')];
76
        }
77
78 7
        $command->aqb =
79 7
            $aqb->let(
80 7
                'columnFound',
81 7
                $aqb->first(
82 7
                    (new QueryBuilder())->for('doc', $table)
83 7
                        ->filter($filter)
84 7
                        ->limit(1)
85 7
                        ->return('true'),
86 7
                ),
87 7
            )->return($aqb->rawExpression('columnFound == true'))
88 7
                ->get();
89
90 7
        return $command;
91
    }
92
93
    /**
94
     * Compile AQL to rename an attribute, if the new name isn't already in use.
95
     *
96
     * @param string $table
97
     * @param Fluent $command
98
     * @return Fluent
99
     */
100 1
    public function compileRenameAttribute($table, Fluent $command)
101
    {
102 1
        $attributes = $command->getAttributes();
103
104 1
        $filter = [
105 1
            ['doc.' . $attributes['from'], '!=', null],
106 1
            ['doc.' . $attributes['to'], '==', null],
107 1
        ];
108
109 1
        $aqb = (new QueryBuilder())->for('doc', $table)
110 1
            ->filter($filter)
111 1
            ->update(
112 1
                'doc',
113 1
                [
114 1
                    $attributes['from'] => null,
115 1
                    $attributes['to'] => 'doc.' . $command->from,
116 1
                ],
117 1
                $table,
118 1
            )
119 1
            ->options(['keepNull' => false])
120 1
            ->get();
121
122 1
        $command->aqb = $aqb;
123
124 1
        return $command;
125
    }
126
127
    /**
128
     * Compile AQL to drop one or more attributes.
129
     *
130
     * @param string $table
131
     * @param Fluent $command
132
     * @return Fluent
133
     */
134 2
    public function compileDropColumn($table, Fluent $command)
135
    {
136 2
        $filter = [];
137 2
        $attributes = $command->getAttributes();
138
139 2
        $data = [];
140 2
        foreach ($attributes['attributes'] as $attribute) {
141 2
            $filter[] = ['doc.' . $attribute, '!=', null, 'OR'];
142 2
            $data[$attribute] = null;
143
        }
144 2
        $aqb = (new QueryBuilder())->for('doc', $table)
145 2
            ->filter($filter)
146 2
            ->update('doc', $data, $table)
147 2
            ->options(['keepNull' => false])
148 2
            ->get();
149
150 2
        $command->aqb = $aqb;
151
152 2
        return $command;
153
    }
154
155
    /**
156
     * Prepare a bindVar for inclusion in an AQL query.
157
     */
158 1
    public function wrapBindVar(string $attribute): string
159
    {
160 1
        $attribute = trim($attribute);
161 1
        if (strpos($attribute, '@') === 0) {
162 1
            $attribute = "`$attribute`";
163
        }
164
165 1
        return $attribute;
166
    }
167
}
168