Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
mysqlcommonconnection.php
1<?php
2
3namespace Bitrix\Main\DB;
4
7
8abstract class MysqlCommonConnection extends Connection
9{
10 protected $engine = "";
11 protected int $transactionLevel = 0;
12
16 public function __construct(array $configuration)
17 {
18 parent::__construct($configuration);
19 $this->engine = $configuration['engine'] ?? '';
20 }
21
25 public function isTableExists($tableName)
26 {
27 $tableName = preg_replace("/[^a-z0-9%_]+/i", "", $tableName);
28 $tableName = trim($tableName);
29
30 if ($tableName == '')
31 {
32 return false;
33 }
34
35 $result = $this->query("SHOW TABLES LIKE '".$this->getSqlHelper()->forSql($tableName)."'");
36
37 return (bool) $result->fetch();
38 }
39
43 public function isIndexExists($tableName, array $columns)
44 {
45 return $this->getIndexName($tableName, $columns) !== null;
46 }
47
51 public function getIndexName($tableName, array $columns, $strict = false)
52 {
53 if (empty($columns))
54 {
55 return null;
56 }
57
58 $tableName = preg_replace("/[^a-z0-9_]+/i", "", $tableName);
59 $tableName = trim($tableName);
60
61 $rs = $this->query("SHOW INDEX FROM `".$this->getSqlHelper()->forSql($tableName)."`");
62 if (!$rs)
63 {
64 return null;
65 }
66
67 $indexes = array();
68 while ($ar = $rs->fetch())
69 {
70 $indexes[$ar["Key_name"]][$ar["Seq_in_index"] - 1] = $ar["Column_name"];
71 }
72
73 return static::findIndex($indexes, $columns, $strict);
74 }
75
79 public function getTableFields($tableName)
80 {
81 if (!isset($this->tableColumnsCache[$tableName]))
82 {
83 $this->connectInternal();
84
85 $sqlTableName = ($tableName[0] === '(')
86 ? $tableName.' AS xyz' // subquery
87 : $this->getSqlHelper()->quote($tableName); // regular table name
88
89 $query = $this->queryInternal("SELECT * FROM {$sqlTableName} LIMIT 0");
90
91 $result = $this->createResult($query);
92
93 $this->tableColumnsCache[$tableName] = $result->getFields();
94 }
95 return $this->tableColumnsCache[$tableName];
96 }
97
101 public function createTable($tableName, $fields, $primary = array(), $autoincrement = array())
102 {
103 $sql = 'CREATE TABLE '.$this->getSqlHelper()->quote($tableName).' (';
104 $sqlFields = array();
105
106 foreach ($fields as $columnName => $field)
107 {
108 if (!($field instanceof ScalarField))
109 {
110 throw new ArgumentException(sprintf(
111 'Field `%s` should be an Entity\ScalarField instance', $columnName
112 ));
113 }
114
115 $realColumnName = $field->getColumnName();
116
117 $sqlFields[] = $this->getSqlHelper()->quote($realColumnName)
118 . ' ' . $this->getSqlHelper()->getColumnTypeByField($field)
119 . ($field->isNullable() ? '' : ' NOT NULL') // null for oracle if is not primary
120 . (in_array($columnName, $autoincrement, true) ? ' AUTO_INCREMENT' : '')
121 ;
122 }
123
124 $sql .= join(', ', $sqlFields);
125
126 if (!empty($primary))
127 {
128 foreach ($primary as &$primaryColumn)
129 {
130 $realColumnName = $fields[$primaryColumn]->getColumnName();
131 $primaryColumn = $this->getSqlHelper()->quote($realColumnName);
132 }
133
134 $sql .= ', PRIMARY KEY('.join(', ', $primary).')';
135 }
136
137 $sql .= ')';
138
139 if ($this->engine)
140 {
141 $sql .= ' Engine='.$this->engine;
142 }
143
144 $this->query($sql);
145 }
146
150 public function createIndex($tableName, $indexName, $columnNames, $columnLengths = null, $indexType = null)
151 {
152 if (!is_array($columnNames))
153 {
154 $columnNames = array($columnNames);
155 }
156
157 $sqlHelper = $this->getSqlHelper();
158
159 foreach ($columnNames as &$columnName)
160 {
161 if (is_array($columnLengths) && isset($columnLengths[$columnName]) && $columnLengths[$columnName] > 0)
162 {
163 $maxLength = intval($columnLengths[$columnName]);
164 }
165 else
166 {
167 $maxLength = 0;
168 }
169
170 $columnName = $sqlHelper->quote($columnName);
171 if ($maxLength > 0)
172 {
173 $columnName .= '('.$maxLength.')';
174 }
175 }
176 unset($columnName);
177
178 $indexTypeSql = '';
179
180 if ($indexType !== null
181 && in_array(strtoupper($indexType), [static::INDEX_UNIQUE, static::INDEX_FULLTEXT, static::INDEX_SPATIAL], true)
182 )
183 {
184 $indexTypeSql = strtoupper($indexType);
185 }
186
187 $sql = 'CREATE '.$indexTypeSql.' INDEX '.$sqlHelper->quote($indexName).' ON '.$sqlHelper->quote($tableName)
188 .' ('.join(', ', $columnNames).')';
189
190 return $this->query($sql);
191 }
192
196 public function renameTable($currentName, $newName)
197 {
198 $this->query('RENAME TABLE '.$this->getSqlHelper()->quote($currentName).' TO '.$this->getSqlHelper()->quote($newName));
199 }
200
204 public function dropTable($tableName)
205 {
206 $this->query('DROP TABLE '.$this->getSqlHelper()->quote($tableName));
207 }
208
209 /*********************************************************
210 * Transactions
211 *********************************************************/
212
216 public function startTransaction()
217 {
218 if ($this->transactionLevel == 0)
219 {
220 $this->query("START TRANSACTION");
221 }
222 else
223 {
224 $this->query("SAVEPOINT TRANS{$this->transactionLevel}");
225 }
226
227 $this->transactionLevel++;
228 }
229
233 public function commitTransaction()
234 {
235 $this->transactionLevel--;
236
237 if ($this->transactionLevel < 0)
238 {
239 throw new TransactionException('Transaction was not started.');
240 }
241
242 if ($this->transactionLevel == 0)
243 {
244 // commits all nested transactions
245 $this->query("COMMIT");
246 }
247 }
248
253 public function rollbackTransaction()
254 {
255 $this->transactionLevel--;
256
257 if ($this->transactionLevel < 0)
258 {
259 throw new TransactionException('Transaction was not started.');
260 }
261
262 if ($this->transactionLevel == 0)
263 {
264 $this->query("ROLLBACK");
265 }
266 else
267 {
268 $this->query("ROLLBACK TO SAVEPOINT TRANS{$this->transactionLevel}");
269
270 throw new TransactionException('Nested rollbacks are unsupported.');
271 }
272 }
273
274 /*********************************************************
275 * Global named lock
276 *********************************************************/
277
281 public function lock($name, $timeout = 0)
282 {
283 $timeout = (int)$timeout;
284 $name = $this->getLockName($name);
285
286 $lock = $this->query("SELECT GET_LOCK('{$name}', {$timeout}) as L")->fetch();
287
288 return ($lock["L"] == "1");
289 }
290
294 public function unlock($name)
295 {
296 $name = $this->getLockName($name);
297
298 $lock = $this->query("SELECT RELEASE_LOCK('{$name}') as L")->fetch();
299
300 return ($lock["L"] == "1");
301 }
302
303 protected function getLockName($name)
304 {
305 $unique = \CMain::GetServerUniqID();
306
307 //64 characters max for mysql 5.7+
308 return md5($unique).md5($name);
309 }
310
311 /*********************************************************
312 * Type, version, cache, etc.
313 *********************************************************/
314
318 public function getType()
319 {
320 return "mysql";
321 }
322
329 public function setStorageEngine()
330 {
331 if ($this->engine)
332 {
333 $this->query("SET storage_engine = '".$this->engine."'");
334 }
335 }
336
343 abstract public function selectDatabase($database);
344
350 public function getMaxAllowedPacket()
351 {
352 static $mtu;
353
354 if (is_null($mtu))
355 {
356 $mtu = 0;
357
358 $res = $this->query("SHOW VARIABLES LIKE 'max_allowed_packet'")->fetch();
359 if ($res['Variable_name'] == 'max_allowed_packet')
360 {
361 $mtu = intval($res['Value']);
362 }
363 }
364
365 return $mtu;
366 }
367}
getIndexName($tableName, array $columns, $strict=false)
isIndexExists($tableName, array $columns)
createIndex($tableName, $indexName, $columnNames, $columnLengths=null, $indexType=null)
createTable($tableName, $fields, $primary=array(), $autoincrement=array())