Completed
Push — master ( 238e1f...47c7ce )
by Nazar
05:15
created

SQLite::convert_sql()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1.037

Importance

Changes 0
Metric Value
cc 1
eloc 2
nc 1
nop 1
dl 0
loc 3
ccs 2
cts 3
cp 0.6667
crap 1.037
rs 10
c 0
b 0
f 0
1
<?php
2
/**
3
 * @package   CleverStyle Framework
4
 * @author    Nazar Mokrynskyi <[email protected]>
5
 * @copyright Copyright (c) 2016, Nazar Mokrynskyi
6
 * @license   MIT License, see license.txt
7
 */
8
namespace cs\DB;
9
use
10
	SQLite3Result;
11
12
class SQLite extends _Abstract {
13
	/**
14
	 * @var \SQLite3 Instance of DB connection
15
	 */
16
	protected $instance;
17
	/**
18
	 * @param string $database Ignored for SQLite
19
	 * @param string $user     Ignored for SQLite
20
	 * @param string $password Ignored for SQLite
21
	 * @param string $host     Path to database file, relatively to website root or absolute
22
	 * @param string $prefix
23
	 */
24 24
	public function __construct ($database, $user = '', $password = '', $host = '', $prefix = '') {
25
		// Hack for HHVM: https://github.com/facebook/hhvm/issues/7225
26 24
		if (!$host) {
27 1
			return;
28
		}
29 24
		$start = microtime(true);
30
		try {
31 24
			$this->instance        = new \SQLite3($host);
32 24
			$this->database        = $database;
33 24
			$this->connected       = true;
34 24
			$this->connecting_time = microtime(true) - $start;
35 24
			$this->db_type         = 'sqlite';
36 24
			$this->prefix          = $prefix;
37
		} catch (\Exception $e) {
38
		}
39 24
	}
40
	/**
41
	 * @inheritdoc
42
	 */
43 24
	public function q ($query, ...$params) {
44 24
		return parent::q(
45 24
			$this->convert_sql($query),
46 24
			...$params
47
		);
48
	}
49
	/**
50
	 * Convert small subset of MySQL queries into SQLite-compatible syntax
51
	 *
52
	 * @param string $query
53
	 *
54
	 * @return string
55
	 */
56 24
	protected function convert_sql ($query) {
57 24
		return str_replace('INSERT IGNORE', 'INSERT OR IGNORE', $query);
58
	}
59
	/**
60
	 * @inheritdoc
61
	 *
62
	 * @return false|SQLite3Result
63
	 */
64 24
	protected function q_internal ($query, $parameters = []) {
65 24
		if (!$query) {
66 1
			return false;
67
		}
68 24
		if ($parameters) {
69 21
			$stmt = $this->instance->prepare($query);
70
			// Allows to provide more parameters for prepared statements than needed
71 21
			$local_parameters = array_slice($parameters, 0, substr_count($query, '?'));
72 21
			foreach ($local_parameters as $index => $parameter) {
73 21
				$stmt->bindValue($index + 1, $parameter);
74
			}
75 21
			return $stmt->execute();
76
		}
77 24
		return $this->instance->query($query);
78
	}
79
	/**
80
	 * @inheritdoc
81
	 *
82
	 * @param false|SQLite3Result $query_result
83
	 */
84 23
	public function f ($query_result, $single_column = false, $array = false, $indexed = false) {
85 23
		if (!($query_result instanceof SQLite3Result)) {
86 1
			return false;
87
		}
88 23
		$result_type = $single_column || $indexed ? SQLITE3_NUM : SQLITE3_ASSOC;
89 23
		if ($array) {
90 20
			$result = [];
91 20
			while ($current = $query_result->fetchArray($result_type)) {
92 20
				$result[] = $single_column ? $current[0] : $current;
93
			}
94 20
			$this->free($query_result);
95 20
			return $result;
96
		}
97 22
		$result = $query_result->fetchArray($result_type);
98 22
		return $single_column && $result ? $result[0] : $result;
99
	}
100
	/**
101
	 * @inheritdoc
102
	 */
103 17
	public function id () {
104 17
		return $this->instance->lastInsertRowID();
105
	}
106
	/**
107
	 * @inheritdoc
108
	 */
109 1
	public function affected () {
110 1
		return $this->instance->changes();
111
	}
112
	/**
113
	 * @inheritdoc
114
	 *
115
	 * @param false|SQLite3Result $query_result
116
	 */
117 20
	public function free ($query_result) {
118 20
		if ($query_result instanceof SQLite3Result) {
119 20
			return $query_result->finalize();
120
		}
121 1
		return true;
122
	}
123
	/**
124
	 * @inheritdoc
125
	 */
126 2
	public function columns ($table, $like = false) {
127 2
		if (!$table) {
128 1
			return false;
129
		}
130 2
		$columns = $this->qfa("PRAGMA table_info(`$table`)") ?: [];
131 2
		foreach ($columns as &$column) {
132 2
			$column = $column['name'];
133
		}
134
		/**
135
		 * Only support the most common cases
136
		 */
137 2
		if ($like) {
138 1
			if (substr($like, -1) == '%') {
139 1
				$like = substr($like, 0, -1);
140 1
				return array_values(
141
					array_filter(
142
						$columns,
143 1
						function ($column) use ($like) {
144 1
							return strpos($column, $like) === 0;
145 1
						}
146
					)
147
				);
148 1
			} elseif (strpos($like, '%') === false) {
149 1
				return in_array($like, $columns) ? [$like] : [];
150
			} else {
151 1
				trigger_error("Can't get columns like $like, SQLite engine doesn't support such conditions", E_USER_WARNING);
152 1
				return [];
153
			}
154
		}
155 2
		return $columns;
156
	}
157
	/**
158
	 * @inheritdoc
159
	 */
160 1
	public function tables ($like = false) {
161 1
		if ($like) {
162 1
			$like = $this->s($like);
163 1
			return $this->qfas(
164
				"SELECT `name`
165
				FROM `sqlite_master`
166
				WHERE
167
					`type` = 'table' AND
168
					`name` != 'sqlite_sequence' AND
169 1
					`name` LIKE $like
170 1
				ORDER BY `name` ASC"
171 1
			) ?: [];
172
		} else {
173 1
			return $this->qfas(
174
				"SELECT `name`
175
				FROM `sqlite_master`
176
				WHERE
177
					`type` = 'table' AND
178
					`name` != 'sqlite_sequence'
179 1
				ORDER BY `name` ASC"
180 1
			) ?: [];
181
		}
182
	}
183
	/**
184
	 * @inheritdoc
185
	 */
186 22
	protected function s_internal ($string, $single_quotes_around) {
187 22
		$return = \SQLite3::escapeString($string);
188 22
		return $single_quotes_around ? "'$return'" : $return;
189
	}
190
	/**
191
	 * @inheritdoc
192
	 */
193 1
	public function server () {
194 1
		return \SQLite3::version()['versionString'];
195
	}
196
	/**
197
	 * @inheritdoc
198
	 */
199 2
	public function __destruct () {
200 2
		if ($this->connected && is_object($this->instance)) {
201 2
			$this->instance->close();
202 2
			$this->connected = false;
203
		}
204 2
	}
205
}
206