403Webshell
Server IP : 80.87.202.40  /  Your IP : 216.73.216.169
Web Server : Apache
System : Linux rospirotorg.ru 5.14.0-539.el9.x86_64 #1 SMP PREEMPT_DYNAMIC Thu Dec 5 22:26:13 UTC 2024 x86_64
User : bitrix ( 600)
PHP Version : 8.2.27
Disable Function : NONE
MySQL : OFF |  cURL : ON |  WGET : ON |  Perl : ON |  Python : OFF |  Sudo : ON |  Pkexec : ON
Directory :  /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/perfmon/lib/sql/

Upload File :
current_dir [ Writeable] document_root [ Writeable]

 

Command :


[ Back ]     

Current File : /home/bitrix/ext_www/rospirotorg.ru/bitrix/modules/perfmon/lib/sql/updater.php
<?php
namespace Bitrix\Perfmon\Sql;

use Bitrix\Main\NotSupportedException;
use Bitrix\Perfmon\Php;

class Updater
{
	protected $dbType = '';
	protected $delimiter = '';
	/** @var \Bitrix\Perfmon\Sql\Table */
	protected $tableCheck = null;
	protected $columns = [];

	/** @var \Bitrix\Perfmon\Php\Statement[]*/
	protected $statements = [];

	/**
	 * Sets database type. Currently supported:
	 * - MYSQL
	 * - ORACLE
	 * - MSSQL
	 *
	 * @param string $dbType Database type.
	 *
	 * @return Updater
	 */
	public function setDbType($dbType = '')
	{
		$this->dbType = (string)$dbType;
		return $this;
	}

	/**
	 * Sets DDL delimiter for parsing.
	 *
	 * @param string $delimiter DDL statements delimiter.
	 *
	 * @return Updater
	 */
	public function setDelimiter($delimiter = '')
	{
		$this->delimiter = (string)$delimiter;
		return $this;
	}

	/**
	 * Returns array of generated statements.
	 *
	 * @return \Bitrix\Perfmon\Php\Statement[]
	 */
	public function getStatements()
	{
		return $this->statements;
	}

	/**
	 * Produces updater code.
	 *
	 * @param string $sourceSql Source DDL statements.
	 * @param string $targetSql Target DDL statements.
	 *
	 * @return string
	 * @throws NotSupportedException
	 */
	public function generate($sourceSql, $targetSql)
	{
		$source = new Schema;
		$source->createFromString($sourceSql, $this->delimiter);

		$target = new Schema;
		$target->createFromString($targetSql, $this->delimiter);

		$diff = Compare::diff($source ,$target);
		if ($diff)
		{
			$sourceTables = $source->tables->getList();
			if ($sourceTables)
			{
				$this->tableCheck = array_shift($sourceTables);
			}
			else
			{
				$targetTables = $target->tables->getList();
				if ($targetTables)
				{
					$this->tableCheck = array_shift($targetTables);
				}
				else
				{
					$this->tableCheck = null;
				}
			}

			if (!$this->tableCheck)
			{
				throw new NotSupportedException('no CHECK TABLE found.');
			}

			return $this->handle($diff);
		}
		else
		{
			return '';
		}
	}

	/**
	 * @param array $diff Difference pairs.
	 *
	 * @return string
	 */
	protected function handle(array $diff)
	{
		$this->columns = [];
		foreach ($diff as $pair)
		{
			if (!isset($pair[0]))
			{
				$this->handleCreate($pair[1]);
			}
			elseif (!isset($pair[1]))
			{
				$this->handleDrop($pair[0]);
			}
			else
			{
				$this->handleChange($pair[0], $pair[1]);
			}
		}

		foreach ($this->columns as $columns)
		{
			$ddl = ''; $predicate2 = [];
			foreach ($columns as $column)
			{
				$predicate2[] = $column[0];
				if ($ddl)
				{
					$ddl .= ', ' . preg_replace('/^ALTER TABLE [^ ]+ /', '', $column[1]);
				}
				else
				{
					$ddl = $column[1];
				}
			}

			$stmt = $this->createStatement('$DB->Query(\'', $ddl, '\');');
			$stmt->dependOn = $columns[0][2];
			$stmt->addCondition('$updater->CanUpdateDatabase()');
			$stmt->addCondition('$DB->type == \'' . EscapePHPString($this->dbType, '\'') . '\'');
			$stmt->addCondition($columns[0][3]);
			$stmt->addCondition($columns[0][0]);

			$this->statements[] = $stmt;
		}

		$updaterSteps = $this->getStatements();
		$codeTree = new \Bitrix\Perfmon\Php\CodeTree($updaterSteps);
		$result = $codeTree->getCode(0);

		return $result;
	}

	/**
	 * @param BaseObject $object Database schema object.
	 *
	 * @return void
	 */
	protected function handleCreate(BaseObject $object)
	{
		$stmt = null;

		if ($object instanceof Sequence || $object instanceof Procedure)
		{
			$ddl = $object->getCreateDdl($this->dbType);

			$stmt = $this->createStatement('$DB->Query(\'', $ddl, '\', true);');
			$stmt->dependOn = $this->tableCheck->getUnquotedName();
			$stmt->addCondition('$updater->CanUpdateDatabase()');
			$stmt->addCondition('$DB->type == \'' . EscapePHPString($this->dbType, '\'') . '\'');
			$stmt->addCondition('$updater->TableExists(\'' . EscapePHPString($this->tableCheck->getUnquotedName(), '\'') . '\')');
		}
		elseif ($object instanceof Table)
		{
			$ddl = $object->getCreateDdl($this->dbType);
			$predicate = '!$updater->TableExists(\'' . EscapePHPString($object->name, '\'') . '\')';
			$cond = "\tif (${predicate})\n";

			$stmt = $this->createStatement('$DB->Query(\'', $ddl, '\', true);');
			$stmt->tableName = $object->getUnquotedName();
			$stmt->addCondition('$updater->CanUpdateDatabase()');
			$stmt->addCondition('$DB->type == \'' . EscapePHPString($this->dbType, '\'') . '\'');
			if ($this->tableCheck->getUnquotedName() !== $object->getUnquotedName())
			{
				$stmt->addCondition('$updater->TableExists(\'' . EscapePHPString($this->tableCheck->getUnquotedName(), '\'') . '\')');
			}
			$stmt->addCondition('!$updater->TableExists(\'' . EscapePHPString($object->getUnquotedName(), '\'') . '\')');
		}
		elseif ($object instanceof Column)
		{
			$ddl = $object->getCreateDdl($this->dbType);
			$predicate = '$updater->TableExists(\'' . EscapePHPString($object->parent->getUnquotedName(), '\'') . '\')';
			$cond = "\t\tif (${predicate})\n";
			$predicate2 = '!$DB->Query(\'SELECT ' . EscapePHPString($object->name, '\'') . ' FROM ' . EscapePHPString($object->parent->getUnquotedName(), '\'') . ' WHERE 1=0\', true)';

			$this->columns[$cond][] = [$predicate2, $ddl, $object->parent->getUnquotedName(), $predicate, $predicate2];
		}
		elseif ($object instanceof Index)
		{
			$ddl = $object->getCreateDdl($this->dbType);
			$predicate = '$updater->TableExists(\'' . EscapePHPString($object->parent->getUnquotedName(), '\'') . '\')';
			$predicate2 = '!$DB->IndexExists(\'' . EscapePHPString($object->parent->getUnquotedName(), '\'') . '\', [' . $this->multiLinePhp('\'', $object->getUnquotedName($object->columns), '\', ') . '], true)';

			$stmt = $this->createStatement('$DB->Query(\'', $ddl, '\');');
			$stmt->dependOn = $object->parent->getUnquotedName();
			$stmt->addCondition('$updater->CanUpdateDatabase()');
			$stmt->addCondition('$DB->type == \'' . EscapePHPString($this->dbType, '\'') . '\'');
			$stmt->addCondition($predicate);
			$stmt->addCondition($predicate2);
		}
		elseif ($object instanceof Trigger || $object instanceof Constraint)
		{
			$ddl = $object->getCreateDdl($this->dbType);
			$predicate = '$updater->TableExists(\'' . EscapePHPString($object->parent->getUnquotedName(), '\'') . '\')';

			$stmt = $this->createStatement('$DB->Query(\'', $ddl, '\', true);');
			$stmt->dependOn = $object->parent->getUnquotedName();
			$stmt->addCondition('$updater->CanUpdateDatabase()');
			$stmt->addCondition('$DB->type == \'' . EscapePHPString($this->dbType, '\'') . '\'');
			$stmt->addCondition($predicate);
		}
		else
		{
			$stmt = $this->createStatement('', '//create for ' . get_class($object) . ' not supported yet', '');
		}

		if ($stmt)
		{
			$this->statements[] = $stmt;
		}
	}

	/**
	 * @param BaseObject $object Database schema object.
	 *
	 * @return void
	 */
	protected function handleDrop(BaseObject $object)
	{
		$stmt = false;

		if ($object instanceof Sequence || $object instanceof Procedure)
		{
			$ddl = $object->getDropDdl($this->dbType);

			$stmt = $this->createStatement('$DB->Query(\'', $ddl, '\', true);');
			$stmt->addCondition('$updater->CanUpdateDatabase()');
			$stmt->addCondition('$DB->type == \'' . EscapePHPString($this->dbType, '\'') . '\'');
			$stmt->addCondition('$updater->TableExists(\'' . EscapePHPString($this->tableCheck->getUnquotedName(), '\'') . '\')');
		}
		elseif ($object instanceof Table)
		{
			$ddl = $object->getDropDdl($this->dbType);
			$predicate = '$updater->TableExists(\'' . EscapePHPString($object->getUnquotedName(), '\'') . '\')';

			$stmt = $this->createStatement('$DB->Query(\'', $ddl, '\');');
			$stmt->addCondition('$updater->CanUpdateDatabase()');
			$stmt->addCondition('$DB->type == \'' . EscapePHPString($this->dbType, '\'') . '\'');
			$stmt->addCondition($predicate);
		}
		elseif ($object instanceof Column)
		{
			$ddl = $object->getDropDdl($this->dbType);
			$predicate = '$updater->TableExists(\'' . EscapePHPString($object->parent->name, '\'') . '\')';
			$cond = "\t\tif (${predicate})\n";
			$predicate2 = '$DB->Query(\'SELECT ' . EscapePHPString($object->name, '\'') . ' FROM ' . EscapePHPString($object->parent->getUnquotedName(), '\'') . ' WHERE 1=0\', true)';

			$this->columns[$cond][] = [$predicate2, $ddl, $object->parent->getUnquotedName(), $predicate, $predicate2];
		}
		elseif ($object instanceof Index)
		{
			$ddl = $object->getDropDdl($this->dbType);
			$predicate = '$updater->TableExists(\'' . EscapePHPString($object->parent->getUnquotedName(), '\'') . '\')';
			$predicate2 = '$DB->IndexExists(\'' . EscapePHPString($object->parent->getUnquotedName(), '\'') . '\', [' . $this->multiLinePhp('\'', $object->getUnquotedName($object->columns), '\', ') . '], true)';

			$stmt = $this->createStatement('$DB->Query(\'', $ddl, '\');');
			$stmt->addCondition('$updater->CanUpdateDatabase()');
			$stmt->addCondition('$DB->type == \'' . EscapePHPString($this->dbType, '\'') . '\'');
			$stmt->addCondition($predicate);
			$stmt->addCondition($predicate2);
		}
		elseif ($object instanceof Trigger || $object instanceof Constraint)
		{
			$ddl = $object->getDropDdl($this->dbType);
			$predicate = '$updater->TableExists(\'' . EscapePHPString($object->parent->getUnquotedName(), '\'') . '\')';

			$stmt = $this->createStatement('$DB->Query(\'', $ddl, '\', true);');
			$stmt->addCondition('$updater->CanUpdateDatabase()');
			$stmt->addCondition('$DB->type == \'' . EscapePHPString($this->dbType, '\'') . '\'');
			$stmt->addCondition($predicate);
		}
		else
		{
			$stmt = $this->createStatement('', '//drop for ' . get_class($object) . ' not supported yet', '');
		}

		if ($stmt)
		{
			$this->statements[] = $stmt;
		}
	}

	/**
	 * @param BaseObject $source Source object.
	 * @param BaseObject $target Target object.
	 *
	 * @return void
	 */
	protected function handleChange(BaseObject $source, BaseObject $target)
	{
		$stmt = null;

		if ($source instanceof Sequence || $source instanceof Procedure)
		{
			$dropStmt = $this->createStatement('$DB->Query(\'', $source->getDropDdl($this->dbType), '\', true);');
			$createStmt = $this->createStatement('$DB->Query(\'', $target->getCreateDdl($this->dbType), '\', true);');
			$stmt = new Php\Statement;
			$stmt->dependOn = $this->tableCheck->getUnquotedName();
			$stmt->merge($dropStmt);
			$stmt->merge($createStmt);
			$stmt->addCondition('$updater->CanUpdateDatabase()');
			$stmt->addCondition('$DB->type == \'' . EscapePHPString($this->dbType, '\'') . '\'');
			$stmt->addCondition('$updater->TableExists(\'' . EscapePHPString($this->tableCheck->getUnquotedName(), '\'') . '\')');
		}
		elseif ($target instanceof Column)
		{
			$ddl = $source->getModifyDdl($target, $this->dbType);
			$predicate = '$updater->TableExists(\'' . EscapePHPString($source->parent->getUnquotedName(), '\'') . '\')';
			$cond = "\t\tif (${predicate})\n";
			$predicate2 = '$DB->Query(\'SELECT ' . EscapePHPString($source->name, '\'') . ' FROM ' . EscapePHPString($source->parent->getUnquotedName(), '\'') . ' WHERE 1=0\', true)';

			$this->columns[$cond][] = [$predicate2, $ddl, $source->parent->getUnquotedName(), $predicate, $predicate2];
		}
		elseif ($source instanceof Index)
		{
			$predicate = '$updater->TableExists(\'' . EscapePHPString($source->parent->getUnquotedName(), '\'') . '\')';
			$predicate2 = '$DB->IndexExists(\'' . EscapePHPString($source->parent->getUnquotedName(), '\'') . '\', [' . $this->multiLinePhp('\'', $source->getUnquotedName($source->columns), '\', ') . '], true)';

			$dropStmt = $this->createStatement('$DB->Query(\'', $source->getDropDdl($this->dbType), '\', true);');
			$createStmt = $this->createStatement('$DB->Query(\'', $target->getCreateDdl($this->dbType), '\', true);');
			$stmt = new Php\Statement;
			$stmt->dependOn = $source->parent->getUnquotedName();
			$stmt->merge($dropStmt);
			$stmt->merge($createStmt);
			$stmt->addCondition('$updater->CanUpdateDatabase()');
			$stmt->addCondition('$DB->type == \'' . EscapePHPString($this->dbType, '\'') . '\'');
			$stmt->addCondition($predicate);
			$stmt->addCondition($predicate2);
			$stmt->addCondition('!$DB->IndexExists(\'' . EscapePHPString($target->parent->getUnquotedName(), '\'') . '\', [' . $this->multiLinePhp('\'', $source->getUnquotedName($source->columns), '\', ') . '], true)');
		}
		elseif ($source instanceof Trigger || $source instanceof Constraint)
		{
			$ddl = $source->getModifyDdl($target, $this->dbType);
			$predicate = '$updater->TableExists(\'' . EscapePHPString($source->parent->getUnquotedName(), '\'') . '\')';

			$stmt = $this->createStatement('$DB->Query(\'', $ddl, '\', true);');
			$stmt->dependOn = $source->parent->getUnquotedName();
			$stmt->addCondition('$updater->CanUpdateDatabase()');
			$stmt->addCondition('$DB->type == \'' . EscapePHPString($this->dbType, '\'') . '\'');
			$stmt->addCondition($predicate);
		}
		else
		{
			$stmt = $this->createStatement('', '//change for ' . get_class($source) . ' not supported yet', '');
		}

		if ($stmt)
		{
			$this->statements[] = $stmt;
		}
	}

	/**
	 * Returns escaped php code repeated for body? prefixed with $prefix and suffixed with $suffix.
	 *
	 * @param string $prefix Prefix string for each from body.
	 * @param array|string $body Strings to be escaped.
	 * @param string $suffix Suffix string for each from body.
	 *
	 * @return string
	 */
	protected function multiLinePhp($prefix, $body, $suffix)
	{
		$result = [];
		if (is_array($body))
		{
			foreach ($body as $line)
			{
				$result[] = $prefix . EscapePHPString($line) . $suffix;
			}
		}
		else
		{
			$result[] = $prefix . EscapePHPString($body) . $suffix;
		}
		return implode('', $result);
	}

	/**
	 * Returns Php\Statement object with escaped php code repeated for body? prefixed with $prefix and suffixed with $suffix.
	 *
	 * @param string $prefix Prefix string for each from body.
	 * @param array|string $body Strings to be escaped.
	 * @param string $suffix Suffix string for each from body.
	 *
	 * @return \Bitrix\Perfmon\Php\Statement
	 */
	protected function createStatement($prefix, $body, $suffix)
	{
		$result = new Php\Statement;
		if (is_array($body))
		{
			foreach ($body as $line)
			{
				$result->addLine($prefix . EscapePHPString($line, '\'') . $suffix);
			}
		}
		else
		{
			$result->addLine($prefix . EscapePHPString($body, '\'') . $suffix);
		}
		return $result;
	}
}

Youez - 2016 - github.com/yon3zu
LinuXploit