1C-Bitrix 25.700.0
Загрузка...
Поиск...
Не найдено
mysqlcommonconnection.php
См. документацию.
1<?php
2
3namespace Bitrix\Main\DB;
4
5use Bitrix\Main\Application;
6use Bitrix\Main\ArgumentException;
7use Bitrix\Main\ORM\Fields\ScalarField;
8
9abstract class MysqlCommonConnection extends Connection
10{
11 protected $engine = "";
12 protected int $transactionLevel = 0;
13
18 {
19 parent::__construct($configuration);
20 $this->engine = $configuration['engine'] ?? '';
21 }
22
26 public function isTableExists($tableName)
27 {
28 $tableName = preg_replace("/[^a-z0-9%_]+/i", "", $tableName);
29 $tableName = trim($tableName);
30
31 if ($tableName == '')
32 {
33 return false;
34 }
35
36 $result = $this->query("SHOW TABLES LIKE '" . $this->getSqlHelper()->forSql($tableName) . "'");
37
38 return (bool)$result->fetch();
39 }
40
44 public function isIndexExists($tableName, array $columns)
45 {
46 return $this->getIndexName($tableName, $columns) !== null;
47 }
48
52 public function getIndexName($tableName, array $columns, $strict = false)
53 {
54 if (empty($columns))
55 {
56 return null;
57 }
58
59 $tableName = preg_replace("/[^a-z0-9_]+/i", "", $tableName);
60 $tableName = trim($tableName);
61
62 $rs = $this->query("SHOW INDEX FROM `" . $this->getSqlHelper()->forSql($tableName) . "`");
63 if (!$rs)
64 {
65 return null;
66 }
67
68 $indexes = [];
69 while ($ar = $rs->fetch())
70 {
71 $indexes[$ar["Key_name"]][$ar["Seq_in_index"] - 1] = $ar["Column_name"];
72 }
73
74 return static::findIndex($indexes, $columns, $strict);
75 }
76
80 public function getTableFields($tableName)
81 {
82 if (!isset($this->tableColumnsCache[$tableName]))
83 {
84 $this->connectInternal();
85
86 $sqlTableName = ($tableName[0] === '(')
87 ? $tableName . ' AS xyz' // subquery
88 : $this->getSqlHelper()->quote($tableName); // regular table name
89
90 $query = $this->queryInternal("SELECT * FROM {$sqlTableName} LIMIT 0");
91
92 $result = $this->createResult($query);
93
94 $this->tableColumnsCache[$tableName] = $result->getFields();
95 }
96 return $this->tableColumnsCache[$tableName];
97 }
98
102 public function createTable($tableName, $fields, $primary = [], $autoincrement = [])
103 {
104 $sql = 'CREATE TABLE IF NOT EXISTS ' . $this->getSqlHelper()->quote($tableName) . ' (';
105 $sqlFields = [];
106
107 foreach ($fields as $columnName => $field)
108 {
109 if (!($field instanceof ScalarField))
110 {
111 throw new ArgumentException(sprintf(
112 'Field `%s` should be an Entity\ScalarField instance', $columnName
113 ));
114 }
115
116 $realColumnName = $field->getColumnName();
117
118 $sqlFields[] = $this->getSqlHelper()->quote($realColumnName)
119 . ' ' . $this->getSqlHelper()->getColumnTypeByField($field)
120 . ($field->isNullable() ? '' : ' NOT NULL') // null for oracle if is not primary
121 . (in_array($columnName, $autoincrement, true) ? ' AUTO_INCREMENT' : '');
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 = [$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 try
191 {
192 $result = $this->query($sql);
193 }
194 catch (SqlQueryException $e)
195 {
196 // Duplicate key name
197 if ($this->getErrorCode() != 1061)
198 {
199 throw $e;
200 }
201 return false;
202 }
203
204 return $result;
205 }
206
210 public function renameTable($currentName, $newName)
211 {
212 $this->query('RENAME TABLE ' . $this->getSqlHelper()->quote($currentName) . ' TO ' . $this->getSqlHelper()->quote($newName));
213 }
214
218 public function dropTable($tableName)
219 {
220 $this->query('DROP TABLE ' . $this->getSqlHelper()->quote($tableName));
221 }
222
223 /*********************************************************
224 * Transactions
225 *********************************************************/
226
230 public function startTransaction()
231 {
232 if ($this->transactionLevel == 0)
233 {
234 $this->query("START TRANSACTION");
235 }
236 else
237 {
238 $this->query("SAVEPOINT TRANS{$this->transactionLevel}");
239 }
240
241 $this->transactionLevel++;
242 }
243
247 public function commitTransaction()
248 {
249 $this->transactionLevel--;
250
251 if ($this->transactionLevel < 0)
252 {
253 throw new TransactionException('Transaction was not started.');
254 }
255
256 if ($this->transactionLevel == 0)
257 {
258 // commits all nested transactions
259 $this->query("COMMIT");
260 }
261 }
262
267 public function rollbackTransaction()
268 {
269 $this->transactionLevel--;
270
271 if ($this->transactionLevel < 0)
272 {
273 throw new TransactionException('Transaction was not started.');
274 }
275
276 if ($this->transactionLevel == 0)
277 {
278 $this->query("ROLLBACK");
279 }
280 else
281 {
282 $this->query("ROLLBACK TO SAVEPOINT TRANS{$this->transactionLevel}");
283
284 throw new TransactionException('Nested rollbacks are unsupported.');
285 }
286 }
287
288 /*********************************************************
289 * Global named lock
290 *********************************************************/
291
295 public function lock($name, $timeout = 0)
296 {
297 $timeout = (int)$timeout;
298 $name = $this->getLockName($name);
299
300 $pool = Application::getInstance()->getConnectionPool();
301 $pool->useMasterOnly(true);
302
303 $lock = $this->query("SELECT GET_LOCK('{$name}', {$timeout}) as L")->fetch();
304
305 $pool->useMasterOnly(false);
306
307 return ($lock["L"] == "1");
308 }
309
313 public function unlock($name)
314 {
315 $name = $this->getLockName($name);
316
317 $pool = Application::getInstance()->getConnectionPool();
318 $pool->useMasterOnly(true);
319
320 $lock = $this->query("SELECT RELEASE_LOCK('{$name}') as L")->fetch();
321
322 $pool->useMasterOnly(false);
323
324 return ($lock["L"] == "1");
325 }
326
327 protected function getLockName($name)
328 {
329 $unique = \CMain::GetServerUniqID();
330
331 //64 characters max for mysql 5.7+
332 return md5($unique) . md5($name);
333 }
334
335 /*********************************************************
336 * Type, version, cache, etc.
337 *********************************************************/
338
342 public function getType()
343 {
344 return "mysql";
345 }
346
353 public function setStorageEngine()
354 {
355 if ($this->engine)
356 {
357 // TODO: remove try-catch when mysql 5.7 will be minimal system requirement
358 try
359 {
360 $this->query("SET default_storage_engine = '" . $this->engine . "'");
361 }
362 catch (SqlQueryException)
363 {
364 try
365 {
366 $this->query("SET storage_engine = '" . $this->engine . "'");
367 }
368 catch (SqlQueryException)
369 {
370 }
371 }
372 }
373 }
374
381 abstract public function selectDatabase($database);
382
388 public function getMaxAllowedPacket()
389 {
390 static $mtu;
391
392 if (is_null($mtu))
393 {
394 $mtu = 0;
395
396 $res = $this->query("SHOW VARIABLES LIKE 'max_allowed_packet'")->fetch();
397 if ($res['Variable_name'] == 'max_allowed_packet')
398 {
399 $mtu = intval($res['Value']);
400 }
401 }
402
403 return $mtu;
404 }
405
409 public function createQueryException($code = 0, $databaseMessage = '', $query = '')
410 {
411 if ($code == 1062)
412 {
413 return new DuplicateEntryException('Mysql query error', $databaseMessage, $query);
414 }
415 return new SqlQueryException('Mysql query error', $databaseMessage, $query);
416 }
417}
static getInstance()
Определения application.php:98
Определения duplicateentryexception.php:9
getIndexName($tableName, array $columns, $strict=false)
Определения mysqlcommonconnection.php:52
renameTable($currentName, $newName)
Определения mysqlcommonconnection.php:210
isIndexExists($tableName, array $columns)
Определения mysqlcommonconnection.php:44
createQueryException($code=0, $databaseMessage='', $query='')
Определения mysqlcommonconnection.php:409
createIndex($tableName, $indexName, $columnNames, $columnLengths=null, $indexType=null)
Определения mysqlcommonconnection.php:150
createTable($tableName, $fields, $primary=[], $autoincrement=[])
Определения mysqlcommonconnection.php:102
__construct(array $configuration)
Определения mysqlcommonconnection.php:17
</td ></tr ></table ></td ></tr >< tr >< td class="bx-popup-label bx-width30"><?=GetMessage("PAGE_NEW_TAGS")?> array( $site)
Определения file_new.php:804
$res
Определения filter_act.php:7
$result
Определения get_property_values.php:14
$query
Определения get_search.php:11
if(!is_null($config))($config as $configItem)(! $configItem->isVisible()) $code
Определения options.php:195
$name
Определения menu_edit.php:35
$ar
Определения options.php:199
$rs
Определения action.php:82
$fields
Определения yandex_run.php:501