Passed
Push — main ( a6702e...fc777d )
by Thierry
03:45 queued 01:37
created

Driver::name()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 1
c 0
b 0
f 0
nc 1
nop 0
dl 0
loc 3
rs 10
1
<?php
2
3
namespace Lagdo\DbAdmin\Driver\PgSql;
4
5
use Lagdo\DbAdmin\Driver\Exception\AuthException;
6
use Lagdo\DbAdmin\Driver\Driver as AbstractDriver;
7
8
class Driver extends AbstractDriver
9
{
10
    /**
11
     * Driver features
12
     *
13
     * @var array
14
     */
15
    private $features = ['database', 'table', 'columns', 'sql', 'indexes', 'descidx',
16
        'comment', 'view', 'scheme', 'routine', 'processlist', 'sequence', 'trigger',
17
        'type', 'variables', 'drop_col', 'kill', 'dump', 'fkeys_sql'];
18
19
    /**
20
     * Data types
21
     *
22
     * @var array
23
     */
24
    private $types = [ //! arrays
25
        'Numbers' => ["smallint" => 5, "integer" => 10, "bigint" => 19, "boolean" => 1,
26
            "numeric" => 0, "real" => 7, "double precision" => 16, "money" => 20],
27
        'Date and time' => ["date" => 13, "time" => 17, "timestamp" => 20, "timestamptz" => 21, "interval" => 0],
28
        'Strings' => ["character" => 0, "character varying" => 0, "text" => 0,
29
            "tsquery" => 0, "tsvector" => 0, "uuid" => 0, "xml" => 0],
30
        'Binary' => ["bit" => 0, "bit varying" => 0, "bytea" => 0],
31
        'Network' => ["cidr" => 43, "inet" => 43, "macaddr" => 17, "txid_snapshot" => 0],
32
        'Geometry' => ["box" => 0, "circle" => 0, "line" => 0, "lseg" => 0,
33
            "path" => 0, "point" => 0, "polygon" => 0],
34
    ];
35
36
    /**
37
     * Number variants
38
     *
39
     * @var array
40
     */
41
    // private $unsigned = [];
42
43
    /**
44
     * Operators used in select
45
     *
46
     * @var array
47
     */
48
    private $operators = ["=", "<", ">", "<=", ">=", "!=", "~", "!~", "LIKE", "LIKE %%", "ILIKE",
49
        "ILIKE %%", "IN", "IS NULL", "NOT LIKE", "NOT IN", "IS NOT NULL"]; // no "SQL" to avoid CSRF
50
51
    /**
52
     * Functions used in select
53
     *
54
     * @var array
55
     */
56
    private $functions = ["char_length", "lower", "round", "to_hex", "to_timestamp", "upper"];
57
58
    /**
59
     * Grouping functions used in select
60
     *
61
     * @var array
62
     */
63
    private $grouping = ["avg", "count", "count distinct", "max", "min", "sum"];
64
65
    /**
66
     * Functions used to edit data
67
     *
68
     * @var array
69
     */
70
    private $editFunctions = [[
71
        "char" => "md5",
72
        "date|time" => "now",
73
    ],[
74
        // $this->numberRegex() => "+/-",
75
        "date|time" => "+ interval/- interval", //! escape
76
        "char|text" => "||",
77
    ]];
78
79
    /**
80
     * @inheritDoc
81
     */
82
    public function name()
83
    {
84
        return "PostgreSQL";
85
    }
86
87
    /**
88
     * @inheritDoc
89
     */
90
    public function createConnection()
91
    {
92
        if (extension_loaded("pgsql")) {
93
            $connection = new Db\PgSql\Connection($this, $this->util, $this->trans, 'PgSQL');
94
        }
95
        elseif (extension_loaded("pdo_pgsql")) {
96
            $connection = new Db\Pdo\Connection($this, $this->util, $this->trans, 'PDO_PgSQL');
97
        }
98
        else {
99
            throw new AuthException($this->trans->lang('No package installed to connect to a PostgreSQL server.'));
100
        }
101
102
        if ($this->connection === null) {
103
            $this->connection = $connection;
104
            $this->server = new Db\Server($this, $this->util, $this->trans, $connection);
105
            $this->database = new Db\Database($this, $this->util, $this->trans, $connection);
106
            $this->table = new Db\Table($this, $this->util, $this->trans, $connection);
107
            $this->query = new Db\Query($this, $this->util, $this->trans, $connection);
108
            $this->grammar = new Db\Grammar($this, $this->util, $this->trans, $connection);
109
        }
110
111
        return $connection;
112
    }
113
114
    /**
115
     * @inheritDoc
116
     */
117
    public function connect(string $database, string $schema)
118
    {
119
        parent::connect($database, $schema);
120
121
        if ($this->minVersion(9.3)) {
122
            $this->features[] = 'materializedview';
123
        }
124
125
        if ($this->minVersion(9.2)) {
126
            $this->config->structuredTypes[$this->trans->lang('Strings')][] = "json";
127
            $this->config->types["json"] = 4294967295;
128
            if ($this->minVersion(9.4)) {
129
                $this->config->structuredTypes[$this->trans->lang('Strings')][] = "jsonb";
130
                $this->config->types["jsonb"] = 4294967295;
131
            }
132
        }
133
134
        foreach ($this->userTypes() as $type) { //! get types from current_schemas('t')
135
            if (!isset($this->config->types[$type])) {
136
                $this->config->types[$type] = 0;
137
                $this->config->structuredTypes[$this->trans->lang('User types')][] = $type;
138
            }
139
        }
140
    }
141
142
    /**
143
     * @inheritDoc
144
     */
145
    public function support(string $feature)
146
    {
147
        return in_array($feature, $this->features);
148
    }
149
150
    /**
151
     * @inheritDoc
152
     */
153
    protected function initConfig()
154
    {
155
        $this->config->jush = 'pgsql';
156
        $this->config->drivers = ["PgSQL", "PDO_PgSQL"];
157
        $this->config->setTypes($this->types, $this->trans);
158
        // $this->config->unsigned = [];
159
        $this->config->operators = $this->operators;
160
        $this->config->functions = $this->functions;
161
        $this->config->grouping = $this->grouping;
162
        $this->config->editFunctions = $this->editFunctions;
163
        $this->config->editFunctions[1][$this->numberRegex()] = "+/-";
164
    }
165
166
    /**
167
     * @inheritDoc
168
     */
169
    public function error()
170
    {
171
        $message = parent::error();
172
        if (preg_match('~^(.*\n)?([^\n]*)\n( *)\^(\n.*)?$~s', $message, $match)) {
173
            $match1 = $match[1] ?? '';
174
            $match2 = $match[2] ?? '';
175
            $match3 = $match[3] ?? '';
176
            $match4 = $match[4] ?? '';
177
            $message = $match1 . preg_replace('~((?:[^&]|&[^;]*;){' .
178
                strlen($match3) . '})(.*)~', '\1<b>\2</b>', $match2) . $match4;
179
        }
180
        return $this->util->convertEolToHtml($message);
181
    }
182
}
183