Bitrix-D7 23.9
 
Загрузка...
Поиск...
Не найдено
updater.php
1<?php
2namespace Bitrix\Perfmon\Sql;
3
6
7class Updater
8{
9 protected $dbType = '';
10 protected $delimiter = '';
12 protected $tableCheck = null;
13 protected $columns = [];
14
16 protected $statements = [];
17
28 public function setDbType($dbType = '')
29 {
30 $this->dbType = (string)$dbType;
31 return $this;
32 }
33
41 public function setDelimiter($delimiter = '')
42 {
43 $this->delimiter = (string)$delimiter;
44 return $this;
45 }
46
52 public function getStatements()
53 {
54 return $this->statements;
55 }
56
66 public function generate($sourceSql, $targetSql)
67 {
68 $source = new Schema;
69 $source->createFromString($sourceSql, $this->delimiter);
70
71 $target = new Schema;
72 $target->createFromString($targetSql, $this->delimiter);
73
74 $diff = Compare::diff($source ,$target);
75 if ($diff)
76 {
77 $sourceTables = $source->tables->getList();
78 if ($sourceTables)
79 {
80 $this->tableCheck = array_shift($sourceTables);
81 }
82 else
83 {
84 $targetTables = $target->tables->getList();
85 if ($targetTables)
86 {
87 $this->tableCheck = array_shift($targetTables);
88 }
89 else
90 {
91 $this->tableCheck = null;
92 }
93 }
94
95 if (!$this->tableCheck)
96 {
97 throw new NotSupportedException('no CHECK TABLE found.');
98 }
99
100 return $this->handle($diff);
101 }
102 else
103 {
104 return '';
105 }
106 }
107
113 protected function handle(array $diff)
114 {
115 $this->columns = [];
116 foreach ($diff as $pair)
117 {
118 if (!isset($pair[0]))
119 {
120 $this->handleCreate($pair[1]);
121 }
122 elseif (!isset($pair[1]))
123 {
124 $this->handleDrop($pair[0]);
125 }
126 else
127 {
128 $this->handleChange($pair[0], $pair[1]);
129 }
130 }
131
132 foreach ($this->columns as $columns)
133 {
134 $ddl = ''; $predicate2 = [];
135 foreach ($columns as $column)
136 {
137 $predicate2[] = $column[0];
138 if ($ddl)
139 {
140 $ddl .= ', ' . preg_replace('/^ALTER TABLE [^ ]+ /', '', $column[1]);
141 }
142 else
143 {
144 $ddl = $column[1];
145 }
146 }
147
148 $stmt = $this->createStatement('$DB->Query("', $ddl, '");');
149 $stmt->dependOn = $columns[0][2];
150 $stmt->addCondition('$updater->CanUpdateDatabase()');
151 $stmt->addCondition('$DB->type == "' . EscapePHPString($this->dbType) . '"');
152 $stmt->addCondition($columns[0][3]);
153 $stmt->addCondition($columns[0][0]);
154
155 $this->statements[] = $stmt;
156 }
157
158 $updaterSteps = $this->getStatements();
159 $codeTree = new \Bitrix\Perfmon\Php\CodeTree($updaterSteps);
160 $result = $codeTree->getCode(0);
161
162 return $result;
163 }
164
170 protected function handleCreate(BaseObject $object)
171 {
172 $stmt = null;
173
174 if ($object instanceof Sequence || $object instanceof Procedure)
175 {
176 $ddl = $object->getCreateDdl($this->dbType);
177
178 $stmt = $this->createStatement('$DB->Query("', $ddl, '", true);');
179 $stmt->dependOn = $this->tableCheck->getLowercasedName();
180 $stmt->addCondition('$updater->CanUpdateDatabase()');
181 $stmt->addCondition('$DB->type == "' . EscapePHPString($this->dbType) . '"');
182 $stmt->addCondition('$updater->TableExists("' . EscapePHPString($this->tableCheck->getLowercasedName()) . '")');
183 }
184 elseif ($object instanceof Table)
185 {
186 $ddl = $object->getCreateDdl($this->dbType);
187 $predicate = '!$updater->TableExists("' . EscapePHPString($object->name) . '")';
188 $cond = "\tif (${predicate})\n";
189
190 $stmt = $this->createStatement('$DB->Query("', $ddl, '", true);');
191 $stmt->tableName = $object->getLowercasedName();
192 $stmt->addCondition('$updater->CanUpdateDatabase()');
193 $stmt->addCondition('$DB->type == "' . EscapePHPString($this->dbType) . '"');
194 if ($this->tableCheck->getLowercasedName() !== $object->getLowercasedName())
195 {
196 $stmt->addCondition('$updater->TableExists("' . EscapePHPString($this->tableCheck->getLowercasedName()) . '")');
197 }
198 $stmt->addCondition('!$updater->TableExists("' . EscapePHPString($object->getLowercasedName()) . '")');
199 }
200 elseif ($object instanceof Column)
201 {
202 $ddl = $object->getCreateDdl($this->dbType);
203 $predicate = '$updater->TableExists("' . EscapePHPString($object->parent->getLowercasedName()) . '")';
204 $cond = "\t\tif (${predicate})\n";
205 $predicate2 = '!$DB->Query("SELECT ' . EscapePHPString($object->name) . ' FROM ' . EscapePHPString($object->parent->getLowercasedName()) . ' WHERE 1=0", true)';
206
207 $this->columns[$cond][] = [$predicate2, $ddl, $object->parent->getLowercasedName(), $predicate, $predicate2];
208 }
209 elseif ($object instanceof Index)
210 {
211 $ddl = $object->getCreateDdl($this->dbType);
212 $predicate = '$updater->TableExists("' . EscapePHPString($object->parent->getLowercasedName()) . '")';
213 $predicate2 = '!$DB->IndexExists("' . EscapePHPString($object->parent->getUnquotedName()) . '", array(' . $this->multiLinePhp('"', $object->getUnquotedName($object->columns), '", ') . '), true)';
214
215 $stmt = $this->createStatement('$DB->Query("', $ddl, '");');
216 $stmt->dependOn = $object->parent->getLowercasedName();
217 $stmt->addCondition('$updater->CanUpdateDatabase()');
218 $stmt->addCondition('$DB->type == "' . EscapePHPString($this->dbType) . '"');
219 $stmt->addCondition($predicate);
220 $stmt->addCondition($predicate2);
221 }
222 elseif ($object instanceof Trigger || $object instanceof Constraint)
223 {
224 $ddl = $object->getCreateDdl($this->dbType);
225 $predicate = '$updater->TableExists("' . EscapePHPString($object->parent->getLowercasedName()) . '")';
226
227 $stmt = $this->createStatement('$DB->Query("', $ddl, '", true);');
228 $stmt->dependOn = $object->parent->getLowercasedName();
229 $stmt->addCondition('$updater->CanUpdateDatabase()');
230 $stmt->addCondition('$DB->type == "' . EscapePHPString($this->dbType) . '"');
231 $stmt->addCondition($predicate);
232 }
233 else
234 {
235 $stmt = $this->createStatement('', '//create for ' . get_class($object) . ' not supported yet', '');
236 }
237
238 if ($stmt)
239 {
240 $this->statements[] = $stmt;
241 }
242 }
243
249 protected function handleDrop(BaseObject $object)
250 {
251 $stmt = false;
252
253 if ($object instanceof Sequence || $object instanceof Procedure)
254 {
255 $ddl = $object->getDropDdl($this->dbType);
256
257 $stmt = $this->createStatement('$DB->Query("', $ddl, '", true);');
258 $stmt->addCondition('$updater->CanUpdateDatabase()');
259 $stmt->addCondition('$DB->type == "' . EscapePHPString($this->dbType) . '"');
260 $stmt->addCondition('$updater->TableExists("' . EscapePHPString($this->tableCheck->getLowercasedName()) . '")');
261 }
262 elseif ($object instanceof Table)
263 {
264 $ddl = $object->getDropDdl($this->dbType);
265 $predicate = '$updater->TableExists("' . EscapePHPString($object->getLowercasedName()) . '")';
266
267 $stmt = $this->createStatement('$DB->Query("', $ddl, '");');
268 $stmt->addCondition('$updater->CanUpdateDatabase()');
269 $stmt->addCondition('$DB->type == "' . EscapePHPString($this->dbType) . '"');
270 $stmt->addCondition($predicate);
271 }
272 elseif ($object instanceof Column)
273 {
274 $ddl = $object->getDropDdl($this->dbType);
275 $predicate = '$updater->TableExists("' . EscapePHPString($object->parent->name) . '")';
276 $cond = "\t\tif (${predicate})\n";
277 $predicate2 = '$DB->Query("SELECT ' . EscapePHPString($object->name) . ' FROM ' . EscapePHPString($object->parent->getLowercasedName()) . ' WHERE 1=0", true)';
278
279 $this->columns[$cond][] = [$predicate2, $ddl, $object->parent->getLowercasedName(), $predicate, $predicate2];
280 }
281 elseif ($object instanceof Index)
282 {
283 $ddl = $object->getDropDdl($this->dbType);
284 $predicate = '$updater->TableExists("' . EscapePHPString($object->parent->getLowercasedName()) . '")';
285 $predicate2 = '$DB->IndexExists("' . EscapePHPString($object->parent->getUnquotedName()) . '", array(' . $this->multiLinePhp('"', $object->getUnquotedName($object->columns), '", ') . '), true)';
286
287 $stmt = $this->createStatement('$DB->Query("', $ddl, '");');
288 $stmt->addCondition('$updater->CanUpdateDatabase()');
289 $stmt->addCondition('$DB->type == "' . EscapePHPString($this->dbType) . '"');
290 $stmt->addCondition($predicate);
291 $stmt->addCondition($predicate2);
292 }
293 elseif ($object instanceof Trigger || $object instanceof Constraint)
294 {
295 $ddl = $object->getDropDdl($this->dbType);
296 $predicate = '$updater->TableExists("' . EscapePHPString($object->parent->getLowercasedName()) . '")';
297
298 $stmt = $this->createStatement('$DB->Query("', $ddl, '", true);');
299 $stmt->addCondition('$updater->CanUpdateDatabase()');
300 $stmt->addCondition('$DB->type == "' . EscapePHPString($this->dbType) . '"');
301 $stmt->addCondition($predicate);
302 }
303 else
304 {
305 $stmt = $this->createStatement('', '//drop for ' . get_class($object) . ' not supported yet', '');
306 }
307
308 if ($stmt)
309 {
310 $this->statements[] = $stmt;
311 }
312 }
313
320 protected function handleChange(BaseObject $source, BaseObject $target)
321 {
322 $stmt = null;
323
324 if ($source instanceof Sequence || $source instanceof Procedure)
325 {
326 $dropStmt = $this->createStatement('$DB->Query("', $source->getDropDdl($this->dbType), '", true);');
327 $createStmt = $this->createStatement('$DB->Query("', $target->getCreateDdl($this->dbType), '", true);');
328 $stmt = new Php\Statement;
329 $stmt->dependOn = $this->tableCheck->getLowercasedName();
330 $stmt->merge($dropStmt);
331 $stmt->merge($createStmt);
332 $stmt->addCondition('$updater->CanUpdateDatabase()');
333 $stmt->addCondition('$DB->type == "' . EscapePHPString($this->dbType) . '"');
334 $stmt->addCondition('$updater->TableExists("' . EscapePHPString($this->tableCheck->getLowercasedName()) . '")');
335 }
336 elseif ($target instanceof Column)
337 {
338 $ddl = $source->getModifyDdl($target, $this->dbType);
339 $predicate = '$updater->TableExists("' . EscapePHPString($source->parent->getLowercasedName()) . '")';
340 $cond = "\t\tif (${predicate})\n";
341 $predicate2 = '$DB->Query("SELECT ' . EscapePHPString($source->name) . ' FROM ' . EscapePHPString($source->parent->getLowercasedName()) . ' WHERE 1=0", true)';
342
343 $this->columns[$cond][] = [$predicate2, $ddl, $source->parent->getLowercasedName(), $predicate, $predicate2];
344 }
345 elseif ($source instanceof Index)
346 {
347 $predicate = '$updater->TableExists("' . EscapePHPString($source->parent->getLowercasedName()) . '")';
348 $predicate2 = '$DB->IndexExists("' . EscapePHPString($source->parent->getUnquotedName()) . '", array(' . $this->multiLinePhp('"', $source->getUnquotedName($source->columns), '", ') . '), true)';
349
350 $dropStmt = $this->createStatement('$DB->Query("', $source->getDropDdl($this->dbType), '", true);');
351 $createStmt = $this->createStatement('$DB->Query("', $target->getCreateDdl($this->dbType), '", true);');
352 $stmt = new Php\Statement;
353 $stmt->dependOn = $source->parent->getLowercasedName();
354 $stmt->merge($dropStmt);
355 $stmt->merge($createStmt);
356 $stmt->addCondition('$updater->CanUpdateDatabase()');
357 $stmt->addCondition('$DB->type == "' . EscapePHPString($this->dbType) . '"');
358 $stmt->addCondition($predicate);
359 $stmt->addCondition($predicate2);
360 $stmt->addCondition('!$DB->IndexExists("' . EscapePHPString($target->parent->getUnquotedName()) . '", array(' . $this->multiLinePhp('"', $source->getUnquotedName($source->columns), '", ') . '), true)');
361 }
362 elseif ($source instanceof Trigger || $source instanceof Constraint)
363 {
364 $ddl = $source->getModifyDdl($target, $this->dbType);
365 $predicate = '$updater->TableExists("' . EscapePHPString($source->parent->getLowercasedName()) . '")';
366
367 $stmt = $this->createStatement('$DB->Query("', $ddl, '", true);');
368 $stmt->dependOn = $source->parent->getLowercasedName();
369 $stmt->addCondition('$updater->CanUpdateDatabase()');
370 $stmt->addCondition('$DB->type == "' . EscapePHPString($this->dbType) . '"');
371 $stmt->addCondition($predicate);
372 }
373 else
374 {
375 $stmt = $this->createStatement('', '//change for ' . get_class($source) . ' not supported yet', '');
376 }
377
378 if ($stmt)
379 {
380 $this->statements[] = $stmt;
381 }
382 }
383
393 protected function multiLinePhp($prefix, $body, $suffix)
394 {
395 $result = [];
396 if (is_array($body))
397 {
398 foreach ($body as $line)
399 {
400 $result[] = $prefix . EscapePHPString($line) . $suffix;
401 }
402 }
403 else
404 {
405 $result[] = $prefix . EscapePHPString($body) . $suffix;
406 }
407 return implode('', $result);
408 }
409
419 protected function createStatement($prefix, $body, $suffix)
420 {
421 $result = new Php\Statement;
422 if (is_array($body))
423 {
424 foreach ($body as $line)
425 {
426 $result->addLine($prefix . EscapePHPString($line) . $suffix);
427 }
428 }
429 else
430 {
431 $result->addLine($prefix . EscapePHPString($body) . $suffix);
432 }
433 return $result;
434 }
435}
getModifyDdl(BaseObject $target, $dbType='')
static diff(Schema $source, Schema $target)
Definition compare.php:21
createFromString($str, $delimiter)
Definition schema.php:59
createStatement($prefix, $body, $suffix)
Definition updater.php:419
handleDrop(BaseObject $object)
Definition updater.php:249
handleCreate(BaseObject $object)
Definition updater.php:170
handleChange(BaseObject $source, BaseObject $target)
Definition updater.php:320
setDelimiter($delimiter='')
Definition updater.php:41
multiLinePhp($prefix, $body, $suffix)
Definition updater.php:393
generate($sourceSql, $targetSql)
Definition updater.php:66