SqliteDriver::escapeIdentifier()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 1
eloc 1
c 1
b 0
f 0
nc 1
nop 1
dl 0
loc 3
rs 10
1
<?php declare(strict_types=1);
2
3
/** 
4
 *  ___      _        _
5
 * | _ \__ _| |_ __ _| |__  __ _ ___ ___
6
 * |  _/ _` |  _/ _` | '_ \/ _` (_-</ -_)
7
 * |_| \__,_|\__\__,_|_.__/\__,_/__/\___|
8
 * 
9
 * This file is part of Kristuff\Patabase.
10
 * (c) Kristuff <[email protected]>
11
 *
12
 * For the full copyright and license information, please view the LICENSE
13
 * file that was distributed with this source code.
14
 *
15
 * @version    1.0.1
16
 * @copyright  2017-2022 Christophe Buliard
17
 */
18
19
namespace Kristuff\Patabase\Driver\Sqlite;
20
21
use Kristuff\Patabase\Driver\DatabaseDriver;
22
23
/**
24
 * Class SqliteDriver
25
 *
26
 * SQLite 3 Driver
27
 *
28
 * Data types
29
 *  INT, INTEGER, TINYINT, SMALLINT, MEDIUMINT, BIGINT, UNSIGNED BIG INT, INT2, INT8 	=> INTEGER 
30
 *  CHARACTER(20), VARCHAR(255), VARYING CHARACTER(255), NCHAR(55), 
31
 *      NATIVE CHARACTER(70), NVARCHAR(100), CLOB, TEXT                                 => TEXT
32
 *  BLOB, no datatype specified 	                                                    => BLOB
33
 *  REAL, DOUBLE, DOUBLE PRECISION, FLOAT 	                                            => REAL
34
 *  NUMERIC, DECIMAL(10,5), BOOLEAN, DATE, DATETIME 	                                => NUMERIC
35
 */
36
class SqliteDriver extends DatabaseDriver
37
{
38
39
    /**
40
     * List of DSN attributes
41
     * 
42
     * In Sqlite, the database attribute represent the full path to the database
43
     * To create a database in memory, define the database to :memory: 
44
     *
45
     * @access protected
46
     * @var array
47
     */
48
    protected $dsnAttributes = array(
49
        'database'
50
    );
51
52
    /**
53
     * Create a new PDO connection
54
     *
55
     * @access public
56
     * @param array   $settings
57
     *
58
     * @return void
59
     */
60
    public function createConnection(array $settings): void
61
    {
62
        $this->pdo = new \PDO('sqlite:'.$settings['database']); 
63
64
        //$this->pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
65
        //$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
66
67
        // Foreign key constraints are disabled by default (for backwards compatibility), 
68
        // so must be enabled separately for each database connection.
69
        // @see https://www.sqlite.org/foreignkeys.html
70
        $this->enableForeignKeys();
71
    }
72
73
    /**
74
     * Escape an identifier
75
     *
76
     * @access public
77
     * @param string  $identifier
78
     *
79
     * @return string
80
     */
81
    public function escapeIdentifier(string $identifier): string
82
    {
83
        return '"'.$identifier.'"';
84
    }
85
       
86
    /**
87
     * Escape a value
88
     *
89
     * @access public
90
     * @param string  $value
91
     *
92
     * @return string
93
     */
94
    public function escapeValue(string $value): string
95
    {
96
        return '"'.$value.'"';
97
    }
98
99
    /**
100
     * Get last inserted id
101
     *
102
     * @access public
103
     * @return string
104
     */
105
    public function lastInsertedId(): string
106
    {
107
        return $this->pdo->lastInsertId();
108
    }
109
110
    /**
111
     * Get whether foreign keys are enabled or not
112
     *
113
     * https://www.sqlite.org/foreignkeys.html
114
     *  Foreign key constraints are disabled by default (for backwards compatibility), so must be enabled separately for 
115
     *  each database connection. (Note, however, that future releases of SQLite might change so that foreign key constraints 
116
     *  enabled by default. Careful developers will not make any assumptions about whether or not foreign keys are enabled by 
117
     *  default but will instead enable or disable them as necessary.) The application can also use a PRAGMA foreign_keys 
118
     *  statement to determine if foreign keys are currently enabled. 
119
     * @access public
120
     * @return bool True if foreign keys are enabled, otherwise false
121
     */
122
    public function isForeignKeyEnabled(): bool
123
    {
124
        $query = $this->pdo->prepare('PRAGMA foreign_keys');
125
        return  $query->execute() && (int) $query->fetchColumn() === 1;
126
    }
127
128
    /**
129
     * Enable foreign keys
130
     *
131
     * @access public
132
     * @return void
133
     */
134
    public function enableForeignKeys(): void
135
    {
136
        $this->pdo->exec('PRAGMA foreign_keys = ON');
137
    }
138
139
    /**
140
     * Disable foreign keys
141
     *
142
     * @access public
143
     * @return void
144
     */
145
    public function disableForeignKeys(): void
146
    {
147
        $this->pdo->exec('PRAGMA foreign_keys = OFF');
148
    }
149
150
    /**
151
     * Add a foreign key
152
     *
153
     * This is not supported on sqlite and returns false.
154
     * 
155
     * @access public
156
     * @param string   $fkName         The constraint name
157
     * @param string   $srcTable       The source table
158
     * @param string   $srcColumn      The source column 
159
     * @param string   $refTable       The referenced table
160
     * @param string   $refColumn      The referenced column
161
     *
162
     * @return bool    True if the foreign key has been created, otherwise false
163
     */
164
    public function addForeignKey(string $fkName, string $srcTable, string $srcColumn, string $refTable, string $refColumn): bool
165
    {
166
        return false;
167
    }
168
169
    /**
170
     * Drop a foreign key
171
     *
172
     * This is not supported on sqlite and returns false.
173
     * 
174
     * @access public
175
     * @param string  $fkName          The constraint name
176
     * @param string  $tableName       The source table
177
     *
178
     * @return bool    True if the foreign key has been dropped, otherwise false
179
     */
180
    public function dropForeignKey(string $fkName, string $tableName): bool
181
    {
182
        return false;
183
    }
184
    
185
    /**
186
     * Get the SQL for show tables
187
     *
188
     * @access public
189
     * @return string
190
     */
191
    public function sqlShowTables(): string
192
    {
193
        return 'SELECT name FROM sqlite_master WHERE type = "table";';
194
    }
195
196
    /**
197
     * Get the SQL for random function 
198
     *
199
     * @access public
200
     * @param  mixed    $seed    Random seed. Default is null.
201
     *
202
     * @return string         
203
     */
204
    public function sqlRandom($seed = null): string
205
    {
206
        $seed = !empty($seed) ? $seed : '';  
207
        return sprintf('random(%s)', $seed);   
208
    }
209
210
    /**
211
     * Get the SQL for auto increment column
212
     *
213
     * @access public
214
     * @param string   $type   The sql column type
215
     * 
216
     * @return string
217
     */
218
    public function sqlColumnAutoIncrement(string $type): string
219
    {
220
        // http://www.sqlite.org/datatypes.html
221
        //  One exception to the typelessness of SQLite is a column whose type is INTEGER PRIMARY KEY. (And you 
222
        //  must use "INTEGER" not "INT". A column of type INT PRIMARY KEY is typeless just like any other.) 
223
        //  INTEGER PRIMARY KEY columns must contain a 32-bit signed integer. Any attempt to insert non-integer data 
224
        //  will result in an error. INTEGER PRIMARY KEY columns can be used to implement the equivalent of AUTOINCREMENT.
225
        // 
226
        // https://sqlite.org/autoinc.html
227
        //  If the AUTOINCREMENT keyword appears after INTEGER PRIMARY KEY, that changes the automatic ROWID assignment 
228
        //  algorithm to prevent the reuse of ROWIDs over the lifetime of the database. In other words, the purpose 
229
        //  of AUTOINCREMENT is to prevent the reuse of ROWIDs from previously deleted rows. 
230
        return 'INTEGER';
231
    }
232
}