Completed
Push — master ( fde6a1...7c16b9 )
by Nazar
04:03
created

SQLite::q_internal()   A

Complexity

Conditions 4
Paths 4

Size

Total Lines 15
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 10
CRAP Score 4.3731

Importance

Changes 0
Metric Value
cc 4
eloc 10
nc 4
nop 2
dl 0
loc 15
ccs 10
cts 14
cp 0.7143
crap 4.3731
rs 9.2
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
		// Hack to convert small subset of MySQL queries into SQLite-compatible syntax
45 24
		$query = str_replace('INSERT IGNORE', 'INSERT OR IGNORE', $query);
46 24
		return parent::q($query, ...$params);
47
	}
48
	/**
49
	 * @inheritdoc
50
	 *
51
	 * @return false|SQLite3Result
52
	 */
53 24
	protected function q_internal ($query, $parameters = []) {
54 24
		if (!$query) {
55 1
			return false;
56
		}
57 24
		if ($parameters) {
58 1
			$stmt = $this->instance->prepare($query);
59
			// Allows to provide more parameters for prepared statements than needed
60 1
			$local_parameters = array_slice($parameters, 0, substr_count($query, '?'));
61 1
			foreach ($local_parameters as $index => $parameter) {
62 1
				$stmt->bindValue($index + 1, $parameter);
63
			}
64 1
			return $stmt->execute();
65
		}
66 24
		return $this->instance->query($query);
67
	}
68
	/**
69
	 * @inheritdoc
70
	 *
71
	 * @param false|SQLite3Result $query_result
72
	 */
73 23
	public function f ($query_result, $single_column = false, $array = false, $indexed = false) {
74 23
		if (!($query_result instanceof SQLite3Result)) {
75 1
			return false;
76
		}
77 23
		$result_type = $single_column || $indexed ? SQLITE3_NUM : SQLITE3_ASSOC;
78 23
		if ($array) {
79 20
			$result = [];
80 20
			while ($current = $query_result->fetchArray($result_type)) {
81 20
				$result[] = $single_column ? $current[0] : $current;
82
			}
83 20
			$this->free($query_result);
84 20
			return $result;
85
		}
86 22
		$result = $query_result->fetchArray($result_type);
87 22
		return $single_column && $result ? $result[0] : $result;
88
	}
89
	/**
90
	 * @inheritdoc
91
	 */
92 17
	public function id () {
93 17
		return $this->instance->lastInsertRowID();
94
	}
95
	/**
96
	 * @inheritdoc
97
	 */
98 1
	public function affected () {
99 1
		return $this->instance->changes();
100
	}
101
	/**
102
	 * @inheritdoc
103
	 *
104
	 * @param false|SQLite3Result $query_result
105
	 */
106 20
	public function free ($query_result) {
107 20
		if ($query_result instanceof SQLite3Result) {
108 20
			return $query_result->finalize();
109
		}
110 1
		return true;
111
	}
112
	/**
113
	 * @inheritdoc
114
	 */
115 2
	public function columns ($table, $like = false) {
116 2
		if (!$table) {
117 1
			return false;
118
		}
119 2
		$columns = $this->qfa("PRAGMA table_info(`$table`)") ?: [];
120 2
		foreach ($columns as &$column) {
121 2
			$column = $column['name'];
122
		}
123
		/**
124
		 * Only support the most common cases
125
		 */
126 2
		if ($like) {
127 1
			if (substr($like, -1) == '%') {
128 1
				$like = substr($like, 0, -1);
129 1
				return array_values(
130
					array_filter(
131
						$columns,
132 1
						function ($column) use ($like) {
133 1
							return strpos($column, $like) === 0;
134 1
						}
135
					)
136
				);
137 1
			} elseif (strpos($like, '%') === false) {
138 1
				return in_array($like, $columns) ? [$like] : [];
139
			} else {
140 1
				trigger_error("Can't get columns like $like, SQLite engine doesn't support such conditions", E_USER_WARNING);
141 1
				return [];
142
			}
143
		}
144 2
		return $columns;
145
	}
146
	/**
147
	 * @inheritdoc
148
	 */
149 1
	public function tables ($like = false) {
150 1
		if ($like) {
151 1
			$like = $this->s($like);
152 1
			return $this->qfas(
153
				"SELECT `name`
154
				FROM `sqlite_master`
155
				WHERE
156
					`type` = 'table' AND
157
					`name` != 'sqlite_sequence' AND
158 1
					`name` LIKE $like
159 1
				ORDER BY `name` ASC"
160 1
			) ?: [];
161
		} else {
162 1
			return $this->qfas(
163
				"SELECT `name`
164
				FROM `sqlite_master`
165
				WHERE
166
					`type` = 'table' AND
167
					`name` != 'sqlite_sequence'
168 1
				ORDER BY `name` ASC"
169 1
			) ?: [];
170
		}
171
	}
172
	/**
173
	 * @inheritdoc
174
	 */
175 24
	protected function s_internal ($string, $single_quotes_around) {
176 24
		$return = \SQLite3::escapeString($string);
177 24
		return $single_quotes_around ? "'$return'" : $return;
178
	}
179
	/**
180
	 * @inheritdoc
181
	 */
182 1
	public function server () {
183 1
		return \SQLite3::version()['versionString'];
184
	}
185
	/**
186
	 * @inheritdoc
187
	 */
188 2
	public function __destruct () {
189 2
		if ($this->connected && is_object($this->instance)) {
190 2
			$this->instance->close();
191 2
			$this->connected = false;
192
		}
193 2
	}
194
}
195