Completed
Branch feature/pre-split (1fb89d)
by Anton
03:12
created

PostgresDriver::hasTable()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 1
dl 0
loc 6
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * Spiral Framework.
4
 *
5
 * @license   MIT
6
 * @author    Anton Titov (Wolfy-J)
7
 */
8
9
namespace Spiral\Database\Drivers\Postgres;
10
11
use Spiral\Database\Builders\InsertQuery;
12
use Spiral\Database\DatabaseInterface;
13
use Spiral\Database\Entities\Driver;
14
use Spiral\Database\Exceptions\DriverException;
15
16
/**
17
 * Talks to postgres databases.
18
 */
19
class PostgresDriver extends Driver
20
{
21
    /**
22
     * Driver type.
23
     */
24
    const TYPE = DatabaseInterface::POSTGRES;
25
26
    /**
27
     * Driver schemas.
28
     */
29
    //const SCHEMA_TABLE = TableSchema::class;
30
31
    /**
32
     * Query compiler class.
33
     */
34
    const QUERY_COMPILER = QueryCompiler::class;
35
36
    /**
37
     * Default timestamp expression.
38
     */
39
    const DATETIME_NOW = 'now()';
40
41
    /**
42
     * Cached list of primary keys associated with their table names. Used by InsertBuilder to
43
     * emulate last insert id.
44
     *
45
     * @var array
46
     */
47
    private $primaryKeys = [];
48
49
    /**
50
     * {@inheritdoc}
51
     */
52
    public function hasTable(string $name): bool
53
    {
54
        $query = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \'public\' AND "table_type" = \'BASE TABLE\' AND "table_name" = ?';
55
56
        return (bool)$this->query($query, [$name])->fetchColumn();
57
    }
58
59
    /**
60
     * {@inheritdoc}
61
     */
62
    public function truncateData(string $table)
63
    {
64
        $this->statement("TRUNCATE TABLE {$this->identifier($table)}");
65
    }
66
67
    /**
68
     * {@inheritdoc}
69
     */
70
    public function tableNames(): array
71
    {
72
        $query = 'SELECT "table_name" FROM "information_schema"."tables" WHERE "table_schema" = \'public\' AND "table_type" = \'BASE TABLE\'';
73
74
        $tables = [];
75
        foreach ($this->query($query) as $row) {
76
            $tables[] = $row['table_name'];
77
        }
78
79
        return $tables;
80
    }
81
82
    /**
83
     * Get singular primary key associated with desired table. Used to emulate last insert id.
84
     *
85
     * @param string $prefix Database prefix if any.
86
     * @param string $table  Fully specified table name, including postfix.
87
     *
88
     * @return string|null
89
     *
90
     * @throws DriverException
91
     */
92
    public function getPrimary(string $prefix, string $table): string
93
    {
94
        if (!empty($this->cacheStore) && empty($this->primaryKeys)) {
95
            $this->primaryKeys = (array)$this->cacheStore->get($this->getSource() . '/keys');
96
        }
97
98
        if (!empty($this->primaryKeys) && array_key_exists($table, $this->primaryKeys)) {
99
            return $this->primaryKeys[$table];
100
        }
101
102
        if (!$this->hasTable($prefix . $table)) {
103
            throw new DriverException(
104
                "Unable to fetch table primary key, no such table '{$prefix}{$table}' exists"
0 ignored issues
show
Unused Code introduced by
The call to DriverException::__construct() has too many arguments starting with "Unable to fetch table p...refix}{$table}' exists".

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress.

In this case you can add the @ignore PhpDoc annotation to the duplicate definition and it will be ignored.

Loading history...
105
            );
106
        }
107
108
        $this->primaryKeys[$table] = $this->tableSchema($table, $prefix)->getPrimaryKeys();
109
        if (count($this->primaryKeys[$table]) === 1) {
110
            //We do support only single primary key
111
            $this->primaryKeys[$table] = $this->primaryKeys[$table][0];
112
        } else {
113
            $this->primaryKeys[$table] = null;
114
        }
115
116
        //Caching
117
        if (!empty($this->memory)) {
0 ignored issues
show
Bug introduced by
The property memory does not exist. Did you maybe forget to declare it?

In PHP it is possible to write to properties without declaring them. For example, the following is perfectly valid PHP code:

class MyClass { }

$x = new MyClass();
$x->foo = true;

Generally, it is a good practice to explictly declare properties to avoid accidental typos and provide IDE auto-completion:

class MyClass {
    public $foo;
}

$x = new MyClass();
$x->foo = true;
Loading history...
118
            $this->cacheStore->forever($this->getSource() . '/keys', $this->primaryKeys);
119
        }
120
121
        return $this->primaryKeys[$table];
122
    }
123
124
    /**
125
     * {@inheritdoc}
126
     *
127
     * Postgres uses custom insert query builder in order to return value of inserted row.
128
     */
129 View Code Duplication
    public function insertBuilder(string $prefix, array $parameters = []): InsertQuery
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...
130
    {
131
        return $this->factory->make(
132
            PostgresQuery::class,
133
            ['driver' => $this, 'compiler' => $this->queryCompiler($prefix),] + $parameters
134
        );
135
    }
136
137
    /**
138
     * {@inheritdoc}
139
     */
140
    protected function createPDO(): \PDO
141
    {
142
        //Spiral is purely UTF-8
143
        $pdo = parent::createPDO();
144
        $pdo->exec("SET NAMES 'UTF-8'");
145
146
        return $pdo;
147
    }
148
}
149