瀏覽代碼

updated Instance table actions

Piotr Labudda 8 年之前
父節點
當前提交
bea87de54e

+ 2 - 8
SE/se-lib/ACL.php

@@ -471,20 +471,14 @@ class ACL {
 	static function generateSqlWhereFromFieldRestrictions($fields, $sqlTablePrefix = 't') {
 		return InstanceConfig::generateSqlWhereFromFieldRestrictions($fields, $sqlTablePrefix);
 	}
-	static function generateIsInstanceFunctionBody($namespace, $item = null) {
-		return InstanceConfig::generateIsInstanceFunctionBody($namespace, $item);
-	}
-	static function generateIsInstanceView($namespace, $item = null) {
-		return InstanceConfig::generateIsInstanceView($namespace, $item);
-	}
 
 	static function getInstanceId($namespace) {
 		return InstanceConfig::getInstanceId($namespace);
 	}
-	static function getInstanceConfig($namespace) { // @returns { id, namespace, rootNamespace, idInstanceBase, _createdAt }
+	static function getInstanceConfig($namespace) { // @return Type_InstanceConfig
 		return InstanceConfig::getInstanceConfig($namespace);
 	}
-	static function getInstanceTable($namespace) { // @returns tableName with struct { pk, idInstance, _createdAt }
+	static function getInstanceTable($namespace) { // @return tableName with struct { pk, idInstance, _createdAt }
 		return InstanceConfig::getInstanceTable($namespace);
 	}
 

+ 16 - 42
SE/se-lib/AclQueryBuilder.php

@@ -166,15 +166,12 @@ class AclQueryBuilder {
 		}
 		if ('@instances' === $select) {
 			if (!($this->from instanceof Core_AclBase)) throw new Exception("select @instances allowed only for Acl object");
-			$instanceTable = ACL::getInstanceTable($this->from->getNamespace());
-			return "
-				(
-					select GROUP_CONCAT(inst_conf.namespace)
-					from `{$instanceTable}` inst_tbl
-					join `CRM_INSTANCE_CONFIG` inst_conf on (inst_conf.id = inst_tbl.idInstance)
-					where inst_tbl.pk = {$this->_fromPrefix}.{$sqlPk}
-				) as `@instances`
-			";
+			// TODO: fetch list possible instances, get all instance table name
+			// group_concat(
+			// > foreach ($listInstanceConfig as $instanceConfig) {
+			//  IF( ( select 1 from `{$instanceTable}` where ID = {$this->_fromPrefix}.{$sqlPk} ) > 0, '{$instanceName},', ''),
+			// )
+			return " '' as `@instances` ";
 		}
 		if (is_array($select)) {
 			// TODO: [ '__backRef' => [ ... ] ]
@@ -324,44 +321,21 @@ class AclQueryBuilder {
 		$sqlJoin = [];
 		DBG::log($this, 'array', '$this');
 		foreach ($this->isInstances as $k => $ns) {
-			$idInstance = ACL::getInstanceId($ns);
-			$instanceTable = ACL::getInstanceTable($ns);
-			// ->join($instanceTable, 'i', [ 'rawJoin' => "i.pk = t.{$sqlPk} and i.idInstance = {$idInstance}" ])
-			$prefix = "is_inst_{$k}";
-			// $sqlJoin[] = " inner join `{$joinName}` {$prefix} on (
-			//	 {$prefix}.pk = {$this->_fromPrefix}.{$sqlPk}
-			//	 and {$prefix}.idInstance = {$idInstance}
-			// )";
-			$this->where[] = "{$this->_fromPrefix}.{$sqlPk} in (
-				select {$prefix}.pk
-				from `{$instanceTable}` {$prefix}
-				where {$prefix}.idInstance = {$idInstance}
-			)";
-			DBG::log("{$this->_fromPrefix}.{$sqlPk} in (
-				select {$prefix}.pk
-				from `{$instanceTable}` {$prefix}
-				where {$prefix}.idInstance = {$idInstance}
-			)", 'string', "\$this->where[] =");
+			$instanceConf = ACL::getInstanceConfig($ns);
+			$sqlInstPrefix = "inst_{$instanceConf->id}_is";
+			DBG::log($instanceConf, 'array', "DBG: \$instanceConf");
+			$sqlJoin[] = " join `{$instanceConf->tableName}` `{$sqlInstPrefix}` on(`{$sqlInstPrefix}`.ID = {$this->_fromPrefix}.{$sqlPk}) ";
 		}
 		foreach ($this->isNotInstances as $k => $ns) {
-			$idInstance = ACL::getInstanceId($ns);
-			$instanceTable = ACL::getInstanceTable($ns);
-			// ->join($instanceTable, 'i', [ 'rawJoin' => "i.pk = t.{$sqlPk} and i.idInstance = {$idInstance}" ])
-			$prefix = "is_inst_{$k}";
-			// $sqlJoin[] = " inner join `{$joinName}` {$prefix} on (
-			//	 {$prefix}.pk = {$this->_fromPrefix}.{$sqlPk}
-			//	 and {$prefix}.idInstance = {$idInstance}
-			// )";
-			$this->where[] = "{$this->_fromPrefix}.{$sqlPk} not in (
-				select {$prefix}.pk
-				from `{$instanceTable}` {$prefix}
-				where {$prefix}.idInstance = {$idInstance}
-			)";
+			$instanceConf = ACL::getInstanceConfig($ns);
+			$sqlInstPrefix = "inst_{$instanceConf->id}_is_not";
+			$sqlJoin[] = " left join `{$instanceConf->tableName}` `{$sqlInstPrefix}` on(`{$sqlInstPrefix}`.ID = {$this->_fromPrefix}.{$sqlPk}) ";
+			$this->where[] = " `{$sqlInstPrefix}`.ID IS NULL "; // TODO: use view
 		}
-		// join `{$instanceTable}` i on(i.pk = t.{$sqlPk} and i.idInstance = {$idInstance})
+
 		foreach ($this->_joinPrefix as $prefix => $join) {
 			$joinName = $this->_getTableName($join);
-			$sqlJoin[] = " join `{$joinName}` {$prefix} on(" . $this->_parseJoinParams($this->_joinParams[$prefix]) . ")";
+			$sqlJoin[] = " join `{$joinName}` {$prefix} on(" . $this->_parseJoinParams($this->_joinParams[$prefix]) . ") ";
 		}
 
 		$sqlJoin = (!empty($sqlJoin)) ? implode("\n\t", $sqlJoin) : "";

+ 2 - 41
SE/se-lib/AntAclBase.php

@@ -539,49 +539,10 @@ class AntAclBase extends Core_AclBase {
 	}
 
 	public function getTotal($params = []) {
-		DBG::log($params, 'array', "AntAclBase::getTotal params");
-		$idInstance = ACL::getInstanceId($this->_namespace);
-		$instanceTable = ACL::getInstanceTable($this->_namespace);
-		$sqlPrimaryKey = $this->getSqlPrimaryKeyField();
-		return DB::getPDO()->fetchValue(" -- getTotal({$this->_namespace})
-			select count(1)
-			from `{$this->_rootTableName}` t
-			join `{$instanceTable}` i on(i.pk = t.{$sqlPrimaryKey} and i.idInstance = {$idInstance})
-		");
+		return $this->buildQuery($params)->getTotal();
 	}
 	public function getItems($params = []) {
-		DBG::log($params, 'array', "AntAclBase::getItems params");
-
-		// $sql->limit = V::get('limit', 10, $params, 'int');
-		// $sql->offset = V::get('limitstart', 0, $params, 'int');
-		$limit = V::get('limit', 0, $params, 'int');
-		$limit = ($limit < 0) ? 0 : $limit;
-		$offset = V::get('limitstart', 0, $params, 'int');
-		$offset = ($offset < 0) ? 0 : $offset;
-		$sqlLimit = ($limit > 0)
-			? "limit {$limit} offset {$offset}"
-			: '';
-
-		$idInstance = ACL::getInstanceId($this->_namespace);
-		$instanceTable = ACL::getInstanceTable($this->_namespace);
-		$sqlPrimaryKey = $this->getSqlPrimaryKeyField();
-
-		{
-			$filtrIsInstance = [$this->_namespace];
-			$filtrIsNotInstance = [];
-			if (!empty($params['f_is_instance'])) $filtrIsInstance = $params['f_is_instance'];
-			if (!empty($params['f_is_not_instance'])) $filtrIsNotInstance = $params['f_is_not_instance'];
-		}
-
-		return ACL::query($this)
-			->isInstance($filtrIsInstance)
-			->isNotInstance($filtrIsNotInstance)
-			->select('*') // TODO: fields
-			->select(!empty($params['@instances']) ? '@instances' : '')
-			// ->join($instanceTable, 'i', [ 'rawJoin' => "i.pk = t.{$sqlPrimaryKey} and i.idInstance = {$idInstance}" ])
-			->limit($limit)
-			->offset($offset)
-			->execute();
+		return $this->buildQuery($params)->getItems();
 	}
 
 	public function getItem($primaryKey, $params = []) {

+ 0 - 1
SE/se-lib/Api/WfsServerBase.php

@@ -762,7 +762,6 @@ if($DBG){echo 'L.' . __LINE__ . ' $validateConvertedTransactionXsdString:';print
 		$xmlWriter->writeAttribute("xmlns:{$wfsNs}", $wfsNsUri);
 		if (!$simple) $xmlWriter->writeAttribute("xmlns:{$rootWfsNs}", $rootWfsNsUri);
 		$xmlWriter->writeAttribute('xsi:schemaLocation', "{$wfsNsUri} {$featureTypeUri}");
-		$xmlWriter->writeComment("INSTANCE TABLE: " . Core_AclHelper::getInstanceTable($acl->getRootTableName()));
 		//     <gml:featureMember>
 		//         <p5_objects:TestPerms fid="TestPerms.64" p5:web_link="https://biuro.biall-net.pl/dev-pl/se-master/index.php?_route=ViewTableAjax&amp;namespace=default_objects/TestPerms#EDIT/64">
 		//             <p5_objects:ID p5:allow_write="true">64</p5_objects:ID>

+ 0 - 42
SE/se-lib/Core/AclHelper.php

@@ -505,48 +505,6 @@ class Core_AclHelper {// Helper class for Acl
 		return $refTable;
 	}
 
-	public static function getInstanceTable($rootTableName) {
-		static $cacheInstanceTables = array();
-		$instanceTable = "{$rootTableName}__#INSTANCE";
-		if (in_array($instanceTable, $cacheInstanceTables)) return $instanceTable;
-		DB::getPDO()->execSql("
-			CREATE TABLE IF NOT EXISTS `{$instanceTable}` (
-				`PRIMARY_KEY` int(11) NOT NULL,
-				`A_RECORD_UPDATE_DATE` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-				`INSTANCE_NAME` varchar(255) NOT NULL,
-				UNIQUE KEY `PRIMARY_KEY` (`PRIMARY_KEY`),
-				KEY `INSTANCE_NAME` (`INSTANCE_NAME`)
-				-- TODO `A_TRANACTION_ID` int(11) NOT NULL DEFAULT 0
-			) ENGINE=MyISAM DEFAULT CHARSET=latin2;
-		");
-		DB::getPDO()->execSql("
-			CREATE TABLE IF NOT EXISTS `{$instanceTable}_HIST` (
-				`ID` int(11) NOT NULL AUTO_INCREMENT,
-				`PRIMARY_KEY` int(11) NOT NULL,
-				`A_TRANACTION_ID` int(11) NOT NULL DEFAULT 0,
-				`A_RECORD_UPDATE_DATE` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
-				`INSTANCE_NAME` varchar(255) NOT NULL,
-				PRIMARY KEY (`ID`),
-				KEY `PRIMARY_KEY` (`PRIMARY_KEY`)
-			) ENGINE=MyISAM DEFAULT CHARSET=latin2;
-		");
-		$cacheInstanceTables[] = $instanceTable;
-		return $instanceTable;
-	}
-	public static function setInstance($rootTableName, $pk, $instanceName, $idTransaction = 0) {
-		$instanceTable = self::getInstanceTable($rootTableName);
-		$pk = intval($pk);
-		// TODO: if $pk < 0 throw new Exception("...");
-		$sql = [
-			'instanceName' => DB::getPDO()->quote($instanceName, PDO::PARAM_STR),
-			'idTransaction' => intval($idTransaction)
-		];
-		DB::getPDO()->exec("
-			insert into `{$instanceTable}_HIST` (`PRIMARY_KEY`, `INSTANCE_NAME`, `A_TRANACTION_ID`)
-				values({$pk}, {$sql['instanceName']}, {$idTransaction})
-		");
-	}
-
 	public static function getChildHistTable($rootTableName, $childName, $schema) {
 		// $childName(id) => Array:
 		//		 [@type] => xsd:integer

+ 11 - 9
SE/se-lib/Core/AclSimpleSchemaBase.php

@@ -427,15 +427,17 @@ class Core_AclSimpleSchemaBase extends Core_AclBase {
     $filterCols = $this->getParamCols($params);
     // $object['_raw'] = $row;
     if (in_array('@instance', $filterCols)) {
-      $instanceTable = Core_AclHelper::getInstanceTable($this->getRootTableName());
-      $sqlPkFieldName = $this->getSqlPrimaryKeyField();
-      if (empty($row[$sqlPkFieldName])) throw new Exception("Missing primary key in ({$this->_namespace})");
-      $sqlPk = DB::getPDO()->quote($row[$sqlPkFieldName], PDO::PARAM_STR);
-      $object['@instance'] = DB::getPDO()->fetchValue("
-        select i.INSTANCE_NAME
-        from `{$instanceTable}` i
-        where i.PRIMARY_KEY = {$sqlPk}
-      ");// TODO: where i.`INSTANCE_TYPE` = 'instance' -- (i.`INSTANCE_TYPE` != 'derived')
+      $object['@instance'] = '';
+      // TODO: fetch instance names - InstanceConfig::???
+      // $instanceTable = Core_AclHelper::getInstanceTable($this->getRootTableName());
+      // $sqlPkFieldName = $this->getSqlPrimaryKeyField();
+      // if (empty($row[$sqlPkFieldName])) throw new Exception("Missing primary key in ({$this->_namespace})");
+      // $sqlPk = DB::getPDO()->quote($row[$sqlPkFieldName], PDO::PARAM_STR);
+      // $object['@instance'] = DB::getPDO()->fetchValue("
+      //   select i.INSTANCE_NAME
+      //   from `{$instanceTable}` i
+      //   where i.PRIMARY_KEY = {$sqlPk}
+      // ");// TODO: where i.`INSTANCE_TYPE` = 'instance' -- (i.`INSTANCE_TYPE` != 'derived')
     }
 
     foreach ($this->_simpleSchema['root'] as $fieldName => $field) {

+ 79 - 59
SE/se-lib/InstanceConfig.php

@@ -1,68 +1,22 @@
 <?php
 
 Lib::loadClass('SchemaVersionUpgrade');
+Lib::loadClass('Type_InstanceConfig');
+Lib::loadClass('SchemaFactory');
 
 class InstanceConfig {
 
-	static function createInstanceConfigTable() {
-		DB::getPDO()->execSql("
-			create table if not exists `CRM_INSTANCE_CONFIG` (
-				`id` int(11) not null AUTO_INCREMENT,
-				`namespace` varchar(255) NOT NULL DEFAULT '',
-				`rootNamespace` varchar(255) NOT NULL DEFAULT '',
-				`idInstanceBase` int(11) NOT NULL DEFAULT 0,
-				`_createdAt` datetime NOT NULL,
-				UNIQUE KEY `namespace` (`namespace`),
-				KEY `rootNamespace` (`rootNamespace`),
-				PRIMARY KEY (`id`)
-			) ENGINE=MyISAM  DEFAULT CHARSET=latin2
-		");
-	}
-
-	static function getInstanceTable($namespace) { // @returns tableName with struct { pk, idInstance, _createdAt }
-		$conf = self::getInstanceConfig($namespace);
-		if (!empty($conf['idInstanceBase'])) return "CRM__#INSTANCE_TABLE__{$conf['idInstanceBase']}";
-
-		$rootNs = $conf['rootNamespace'];
-		$rootConf = self::getInstanceConfig($rootNs);
-		$instanceTableName = "CRM__#INSTANCE_TABLE__{$rootConf['id']}";
-		if (!empty($rootConf['idInstance'])) {
-			$affected = DB::getPDO()->update("CRM_INSTANCE_CONFIG", 'rootNamespace', $rootNs, [
-				'idInstanceBase' => $rootConf['id']
-			]);
-			return $instanceTableName;
-		}
-
-		// TODO: fetch primaryKeyType - TODO: store primaryKey and primaryKeyType in SystemObject item
-		$pkType = 'int';
-		DB::getPDO()->exec("
-			CREATE TABLE IF NOT EXISTS `{$instanceTableName}` (
-				`pk` int(11) NOT NULL COMMENT 'primary key'
-				, `idInstance` int(11) NOT NULL
-				, `_createdAt` datetime NOT NULL
-				, KEY `pk` (`pk`)
-				, KEY `idInstance` (`idInstance`)
-			) ENGINE=MyISAM DEFAULT CHARSET=latin2 COMMENT='{$rootNs} #INSTANCE';
-		");
-		$affected = DB::getPDO()->update("CRM_INSTANCE_CONFIG", 'rootNamespace', $rootNs, [
-			'idInstanceBase' => $rootConf['id']
-		]);
-		return $instanceTableName;
+	static function getInstanceTable($namespace) { // @return string - tableName with struct { pk, idInstance, _createdAt }
+		return self::getInstanceConfig($namespace)->tableName;
 	}
 
-	static function getInstanceId($namespace) {
-		return self::getInstanceConfig($namespace)['id'];
+	static function getInstanceId($namespace) { // @return int
+		return self::getInstanceConfig($namespace)->id;
 	}
 
-	static function getInstanceConfig($namespace) { // @returns { id, namespace, rootNamespace, idInstanceBase, _createdAt }
+	static function getInstanceConfig($namespace) { // @return Type_InstanceConfig or throw Exception
 		SchemaVersionUpgrade::upgradeSchema();
-		try {
-			$conf = self::fetchInstanceConfig($namespace);
-		} catch (Exception $e) {
-			self::createInstanceConfigTable();
-			// TODO:?: `_tableInstalled` tinyint(1) not null default 0,
-			$conf = self::fetchInstanceConfig($namespace);
-		}
+		$conf = self::fetchInstanceConfig($namespace);
 		if (!$conf) {
 			$id = DB::getPDO()->insert("CRM_INSTANCE_CONFIG", [
 				'namespace' => $namespace,
@@ -72,17 +26,83 @@ class InstanceConfig {
 			$conf = self::fetchInstanceConfig($namespace);
 		}
 		if (!$conf) throw new Exception("Instance not found in config table '{$namespace}'");
+
+		if ('NORMAL' !== $conf->status) {
+			try {
+				$objectItem = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]);
+			} catch (Exception $e) {
+				throw new Exception("Object not installed '{$namespace}'");
+			}
+			$conf = self::createInstanceTable($conf, $objectItem);
+		}
+
 		return $conf;
 	}
 
-	static function fetchInstanceConfig($namespace) {
-		return DB::getPDO()->fetchFirst("
+	static function fetchInstanceConfig($namespace) { // @return Type_InstanceConfig | null
+		$instanceRow = DB::getPDO()->fetchFirst("
 			select c.*
 			from `CRM_INSTANCE_CONFIG` c
 			where c.namespace = :namespace
 		", [
 			':namespace' => $namespace
 		]);
+		return ($instanceRow) ? Type_InstanceConfig::build($instanceRow) : null;
+	}
+
+	static function createInstanceTable(Type_InstanceConfig $conf, $objectItem) {
+		switch ($objectItem['instanceTableSource']) {
+			case 'table': {
+				self::_createInstanceTable($conf, $objectItem);
+				DB::getPDO()->update('CRM_INSTANCE_CONFIG', 'ID', $conf->id, [
+					'A_STATUS' => "NORMAL",
+					'version' => 1,
+					'source' => "table"
+				]);
+				return self::fetchInstanceConfig($conf->namespace);
+			}
+			case 'view': {
+				self::_createInstanceView($conf, $objectItem);
+				DB::getPDO()->update('CRM_INSTANCE_CONFIG', 'ID', $conf->id, [
+					'A_STATUS' => "NORMAL",
+					'version' => 1,
+					'source' => "view"
+				]);
+				return self::fetchInstanceConfig($conf->namespace);
+			}
+			default: {
+				DBG::log(['$objectItem'=>$objectItem, '$conf'=>$conf], 'array', "Not implemented instance table source type '{$objectItem['instanceTableSource']}'");
+				throw new Exception("Not implemented instance table source type '{$objectItem['instanceTableSource']}'");
+			}
+		}
+		return self::fetchInstanceConfig($conf->namespace);
+	}
+	static function _createInstanceTable(Type_InstanceConfig $conf, $objectItem) {
+		$instanceTableName = "CRM__#INSTANCE_TABLE__{$conf->id}";
+		// // TODO: fetch primaryKeyType - TODO: store primaryKey and primaryKeyType in SystemObject item
+		// $pkType = 'int';
+		DB::getPDO()->exec("
+			CREATE TABLE IF NOT EXISTS `{$instanceTableName}` (
+				`pk` int(11) NOT NULL COMMENT 'primary key'
+				, `idInstance` int(11) NOT NULL
+				, `_createdAt` datetime NOT NULL
+				, KEY `pk` (`pk`)
+				, KEY `idInstance` (`idInstance`)
+			) ENGINE=MyISAM DEFAULT CHARSET=latin2 COMMENT='{$conf->namespace} #INSTANCE';
+		");
+		// TODO: add author, idTransaction?, convert to EventSourcing
+		$affected = DB::getPDO()->update("CRM_INSTANCE_CONFIG", 'rootNamespace', $rootNs, [
+			'SOURCE' => 'table',
+			'VERSION' => 1,
+		]);
+		// return $instanceTableName;
+	}
+	static function _createInstanceView(Type_InstanceConfig $conf, $objectItem) {
+		$idInstance = $conf->id;
+		$dbName = DB::getPDO()->getDatabaseName();
+		$sqlIsInstanceView = self::generateIsInstanceView($objectItem['namespace'], $objectItem, $conf);
+		DB::getPDO()->execSql(" DROP VIEW IF EXISTS `{$dbName}`.`CRM__#INSTANCE_TABLE__{$idInstance}_VIEW` ");
+		DB::getPDO()->execSql(" CREATE VIEW `{$dbName}`.`CRM__#INSTANCE_TABLE__{$idInstance}_VIEW` AS {$sqlIsInstanceView} ");
 	}
 
 	static function getRootNamespace($namespace) { // TODO: works only for relative urls! - mv to Acl->getRootNamespace
@@ -181,7 +201,7 @@ class InstanceConfig {
 		;
 	}
 
-	static function generateIsInstanceFunctionBody($namespace, $item = null) {
+	static function generateIsInstanceFunctionBody($namespace, $item = null) { // TODO: NOT USED
 		if (!$item) $item = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]);
 		if (!in_array( $item['_type'], [ 'AntAcl' ] )) return null;
 		$localFieldsWithRestrictions = array_filter($item['field'], function ($field) {
@@ -207,10 +227,10 @@ class InstanceConfig {
 		return $sqlFunBody;
 	}
 
-	static function generateIsInstanceView($namespace, $item = null) {
+	static function generateIsInstanceView($namespace, $item = null, Type_InstanceConfig $conf = null) {
 		if (!$item) $item = SchemaFactory::loadDefaultObject('SystemObject')->getItem($namespace, [ 'propertyName' => '*,field' ]);
 		if (!in_array( $item['_type'], [ 'AntAcl' ] )) return null;
-		$idInstance = self::getInstanceId($namespace);
+		$idInstance = ($conf) ? $conf->id : self::getInstanceId($namespace);
 
 		$localFieldsWithRestrictions = array_filter($item['field'], function ($field) {
 			if (!$field['isLocal']) return false;

+ 3 - 7
SE/se-lib/Route/Storage/AclReinstall.php

@@ -279,7 +279,6 @@ class Route_Storage_AclReinstall extends RouteBase {
 				'idInstance' => ACL::getInstanceId($namespace),
 				// 'rootInstance' => InstanceConfig::getRootNamespace($namespace),
 				// 'conf' => InstanceConfig::fetchInstanceConfig($namespace),
-				// 'table' => ACL::getInstanceTable($namespace), // Object structure not installed 'default_db/{tableName}'
 			];
 			DBG::nicePrint($dbgInfo, "dbg");
 		} catch (Exception $e) {
@@ -345,17 +344,14 @@ class Route_Storage_AclReinstall extends RouteBase {
 		{ // TODO: RMME? function is too slow for join query
 			if ('AntAcl' === $item['_type']) {
 				$idInstance = ACL::getInstanceId($namespace);
+				$dbName = DB::getPDO()->getDatabaseName();
 				DB::getPDO()->execSql(" DROP FUNCTION IF EXISTS `{$dbName}`.`isInstance_{$idInstance}` ");
 			}
 		}
 		{ // TODO: mv to updateCache
 			if ('AntAcl' === $item['_type']) {
-				$idInstance = ACL::getInstanceId($namespace);
-				$dbName = DB::getPDO()->getDatabaseName();
-				$sqlIsInstanceView = ACL::generateIsInstanceView($namespace, $item); // TODO: generate instance view for every object (namespace)
-				DBG::nicePrint($sqlIsInstanceView, "\$sqlIsInstanceView idInstance({$idInstance})");
-				DB::getPDO()->execSql(" DROP VIEW IF EXISTS `{$dbName}`.`CRM__#INSTANCE_TABLE__{$idInstance}_VIEW` ");
-				DB::getPDO()->execSql(" CREATE VIEW `{$dbName}`.`CRM__#INSTANCE_TABLE__{$idInstance}_VIEW` AS {$sqlIsInstanceView} ");
+				$instConf = InstanceConfig::getInstanceConfig($namespace);
+				InstanceConfig::createInstanceTable($instConf, $item); // force create instance table event if A_STATUS is NORMAL
 			}
 		}
 	}

+ 32 - 31
SE/se-lib/Route/ViewTableAjax.php

@@ -402,37 +402,38 @@ class Route_ViewTableAjax extends RouteBase {
 		if (empty($args['toConnect'])) throw new Exception("Missing toConnect");
 		if (!in_array($args['toConnect'], ['yes', 'no'])) throw new Exception("Wrong param toConnect");
 		$idInstance = ACL::getInstanceId($args['instance']);
-		$instanceTable = ACL::getInstanceTable($args['namespace']);
-		switch ($args['toConnect']) {
-			case 'yes': {
-				// TODO: _HIST info - waiting
-				$ret = DB::getPDO()->execSql("
-					insert into `{$instanceTable}` (`pk`, `idInstance`)
-						values ( :pk , :idInstance )
-				", [
-					'pk' => $args['primaryKey'],
-					'idInstance' => $idInstance,
-				]);
-				// TODO: _HIST info - mark as done
-			} break;
-			case 'no': {
-				// TODO: _HIST info - waiting
-				$ret = DB::getPDO()->execSql("
-					delete from `{$instanceTable}`
-					where `pk` = :pk
-						and `idInstance` = :idInstance
-				", [
-					'pk' => $args['primaryKey'],
-					'idInstance' => $idInstance,
-				]);
-				// TODO: _HIST info - mark as done
-			} break;
-		}
-		return [
-			'type' => 'success',
-			'msg' => "Wprowadzono zmiany ({$ret})",
-			// TODO: 'data' => all instances for pk
-		];
+		throw new Exception("TODO: check instance config"); // if 'view' then set instance is not allowed
+		// $instanceTable = ACL::getInstanceTable($args['namespace']);
+		// switch ($args['toConnect']) {
+		// 	case 'yes': {
+		// 		// TODO: _HIST info - waiting
+		// 		$ret = DB::getPDO()->execSql("
+		// 			insert into `{$instanceTable}` (`pk`, `idInstance`)
+		// 				values ( :pk , :idInstance )
+		// 		", [
+		// 			'pk' => $args['primaryKey'],
+		// 			'idInstance' => $idInstance,
+		// 		]);
+		// 		// TODO: _HIST info - mark as done
+		// 	} break;
+		// 	case 'no': {
+		// 		// TODO: _HIST info - waiting
+		// 		$ret = DB::getPDO()->execSql("
+		// 			delete from `{$instanceTable}`
+		// 			where `pk` = :pk
+		// 				and `idInstance` = :idInstance
+		// 		", [
+		// 			'pk' => $args['primaryKey'],
+		// 			'idInstance' => $idInstance,
+		// 		]);
+		// 		// TODO: _HIST info - mark as done
+		// 	} break;
+		// }
+		// return [
+		// 	'type' => 'success',
+		// 	'msg' => "Wprowadzono zmiany ({$ret})",
+		// 	// TODO: 'data' => all instances for pk
+		// ];
 	}
 
 	public function rmUserTableFilterAjaxAction() {

+ 22 - 1
SE/se-lib/Schema/DefaultDb/zaliczka/ZaliczkaStorageAcl.php

@@ -489,7 +489,28 @@ class Schema_DefaultDb_zaliczka_ZaliczkaStorageAcl extends Core_AclSimpleSchemaB
 		// ACL::getRefTable('default_db/ZALICZKA_POZYCJA/ZaliczkaPozycja', 'projekt');
 		// ACL::getRefTable('default_db/ZALICZKA_POZYCJA/ZaliczkaPozycja', 'korespondencja');
 
-		Core_AclHelper::getInstanceTable('ZALICZKA');// `ZALICZKA__#INSTANCE`
+		DB::getPDO()->execSql("
+			CREATE TABLE IF NOT EXISTS `ZALICZKA__#INSTANCE` (
+				`PRIMARY_KEY` int(11) NOT NULL,
+				`A_RECORD_UPDATE_DATE` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+				`INSTANCE_NAME` varchar(255) NOT NULL,
+				UNIQUE KEY `PRIMARY_KEY` (`PRIMARY_KEY`),
+				KEY `INSTANCE_NAME` (`INSTANCE_NAME`)
+				-- TODO `A_TRANACTION_ID` int(11) NOT NULL DEFAULT 0
+			) ENGINE=MyISAM DEFAULT CHARSET=latin2;
+		");
+		DB::getPDO()->execSql("
+			CREATE TABLE IF NOT EXISTS `ZALICZKA__#INSTANCE_HIST` (
+				`ID` int(11) NOT NULL AUTO_INCREMENT,
+				`PRIMARY_KEY` int(11) NOT NULL,
+				`A_TRANACTION_ID` int(11) NOT NULL DEFAULT 0,
+				`A_RECORD_UPDATE_DATE` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
+				`INSTANCE_NAME` varchar(255) NOT NULL,
+				PRIMARY KEY (`ID`),
+				KEY `PRIMARY_KEY` (`PRIMARY_KEY`)
+			) ENGINE=MyISAM DEFAULT CHARSET=latin2;
+		");
+
 		// TODO: ZaliczkaOczekujaca	 A_STATUS = WAITING	-- dodane przez pracownika
 		// TODO: ZaliczkaAktywna			A_STATUS = NORMAL	 -- zakceptowane / wyplacone przez ...
 			// TODO: pole na dane wypłacającego zaliczkę

+ 1 - 0
SE/se-lib/Schema/SystemObjectStorageAcl.php

@@ -24,6 +24,7 @@ class Schema_SystemObjectStorageAcl extends Core_AclSimpleSchemaBase {
 			'typeName' => [ '@type' => 'p5:string' ],
 			'nsPrefix' => [ '@type' => 'p5:string' ],
 			'reinstallLink' => [ '@type' => 'p5:www_link' ],
+			'instanceTableSource' => [ '@type' => 'xsd:string' ], // enum('table', 'view') default 'view'
 			// 'A_RECORD_CREATE_AUTHOR' => [ '@type' => 'xsd:string' , '@label' => 'autor' ],
 			// 'A_RECORD_CREATE_DATE' => [ '@type' => 'xsd:date' , '@label' => 'utworzono' ],
 			// 'A_RECORD_UPDATE_AUTHOR' => [ '@type' => 'xsd:string' , '@label' => 'zaktualizował' ],

+ 48 - 16
SE/se-lib/SchemaVersionUpgrade.php

@@ -10,6 +10,9 @@
 // SystemObject - `CRM_#CACHE_ACL_OBJECT`
 // SystemObjectField - `CRM_#CACHE_ACL_OBJECT_FIELD`, `CRM_#CACHE_ACL_OBJECT_FIELD_enum`
 
+// TODO: remove `CRM_INSTANCE_CONFIG`.`idInstanceBase`
+// TODO: DROP FUNCTION IF EXISTS `{$dbName}`.`isInstance_{$idInstance}` // for every instance
+
 class SchemaVersionUpgrade {
 
 	static $REF_DB_SCHEMA_VERSION = 2;
@@ -33,6 +36,7 @@ class SchemaVersionUpgrade {
 			self::_fixRefConfigDatabaseSchema();
 			self::_fixSystemObjectDatabaseSchema();
 			self::_fixSystemObjectFieldDatabaseSchema();
+			self::_createInstanceConfigTable();
 			$_DB_SCHEMA_VERSION = 4;
 			$_SESSION['_DB_SCHEMA_VERSION'] = 4;
 			self::_updateDBVersion(4);
@@ -43,18 +47,18 @@ class SchemaVersionUpgrade {
 			$_SESSION['_DB_SCHEMA_VERSION'] = 5;
 			self::_updateDBVersion(5);
 		}
-		// if ($_DB_SCHEMA_VERSION < 6) {
-		// 	self::_upgradeFrom5To6();
-		// 	$_DB_SCHEMA_VERSION = 6;
-		// 	$_SESSION['_DB_SCHEMA_VERSION'] = 6;
-		// 	self::_updateDBVersion(6);
-		// }
-		// if ($_DB_SCHEMA_VERSION < 7) {
-		// 	self::_upgradeFrom6To7();
-		// 	$_DB_SCHEMA_VERSION = 7;
-		// 	$_SESSION['_DB_SCHEMA_VERSION'] = 7;
-		// 	self::_updateDBVersion(7);
-		// }
+		if ($_DB_SCHEMA_VERSION < 6) {
+			self::_upgradeFrom5To6();
+			$_DB_SCHEMA_VERSION = 6;
+			$_SESSION['_DB_SCHEMA_VERSION'] = 6;
+			self::_updateDBVersion(6);
+		}
+		if ($_DB_SCHEMA_VERSION < 7) { // set 'view' as default instance table
+			self::_upgradeFrom6To7();
+			$_DB_SCHEMA_VERSION = 7;
+			$_SESSION['_DB_SCHEMA_VERSION'] = 7;
+			self::_updateDBVersion(7);
+		}
 		// if ($_DB_SCHEMA_VERSION < 8) {
 		// 	self::_upgradeFrom7To8();
 		// 	$_DB_SCHEMA_VERSION = 8;
@@ -311,6 +315,22 @@ class SchemaVersionUpgrade {
 		// }
 	}
 
+	static function _createInstanceConfigTable() {
+		DB::getPDO()->execSql("
+			create table if not exists `CRM_INSTANCE_CONFIG` (
+				`id` int(11) not null AUTO_INCREMENT,
+				`namespace` varchar(255) NOT NULL DEFAULT '',
+				`rootNamespace` varchar(255) NOT NULL DEFAULT '',
+				`idInstanceBase` int(11) NOT NULL DEFAULT 0,
+				`_createdAt` datetime NOT NULL,
+				`SOURCE` enum('table', 'view') not null default 'table',
+				`VERSION` int(11) not null default 0,
+				UNIQUE KEY `namespace` (`namespace`),
+				KEY `rootNamespace` (`rootNamespace`),
+				PRIMARY KEY (`id`)
+			) ENGINE=MyISAM  DEFAULT CHARSET=latin2
+		");
+	}
 	static function _upgradeFrom4To5() {
 		try {
 			DB::getPDO()->execSql(" ALTER TABLE `CRM_INSTANCE_CONFIG` ADD `SOURCE` enum('table', 'view') not null default 'table' ");
@@ -324,10 +344,22 @@ class SchemaVersionUpgrade {
 		}
 	}
 
-	// static function _upgradeFrom5To6() {
-	// }
-	// static function _upgradeFrom6To7() {
-	// }
+	static function _upgradeFrom5To6() {
+		try {
+			DB::getPDO()->execSql(" ALTER TABLE `CRM_INSTANCE_CONFIG` ADD `A_STATUS` enum('WAITING', 'NORMAL', 'DELETED') NOT NULL DEFAULT 'WAITING' ");
+		} catch (Exception $e) {
+			DBG::log($e);
+		}
+	}
+
+	static function _upgradeFrom6To7() {
+		try {
+			DB::getPDO()->execSql(" ALTER TABLE `CRM_#CACHE_ACL_OBJECT` ADD `instanceTableSource` enum('table', 'view') not null default 'view' ");
+		} catch (Exception $e) {
+			DBG::log($e);
+		}
+	}
+
 	// static function _upgradeFrom7To8() {
 	// }
 

+ 54 - 0
SE/se-lib/Type/InstanceConfig.php

@@ -0,0 +1,54 @@
+<?php
+
+class Type_InstanceConfig {
+
+	var $_data = []; // { id, namespace, rootNamespace, _createdAt, SOURCE, VERSION, A_STATUS, tableName }
+
+	static function build($instanceRow = []) {
+		if (!$instanceRow) throw new Exception("Missing data in build Type InstanceConfig");
+		// if (!$instanceRow['ID']) throw new Exception("Missing ID in Type RefConfig build"); // TODO: allow missing ID?
+		$instanceConfig = new Type_InstanceConfig();
+		$instanceConfig->id = (int)$instanceRow['id'];
+		$instanceConfig->namespace = $instanceRow['namespace'];
+		$instanceConfig->rootNamespace = $instanceRow['rootNamespace'];
+		$instanceConfig->source = $instanceRow['SOURCE'];
+		$instanceConfig->status = $instanceRow['A_STATUS'];
+		$instanceConfig->version = $instanceRow['VERSION'];
+		$instanceConfig->tableName = self::generateTableName($instanceConfig->id, $instanceConfig->source);
+
+		return $instanceConfig;
+	}
+	static function generateTableName($id, $source) { // @return string | null
+		switch ($source) {
+			case 'table': return "CRM__#INSTANCE_TABLE__{$id}";
+			case 'view': return "CRM__#INSTANCE_TABLE__{$id}_VIEW";
+			default: return null;
+		}
+	}
+
+	function __isset($name) {
+		return (array_key_exists($name, $this->_data));
+	}
+
+	function __get($name) {
+		if (array_key_exists($name, $this->_data)) {
+			return $this->_data[$name];
+		}
+		return null;
+	}
+
+	function __set($name, $value) {
+		$this->_data[$name] = $value;
+	}
+
+	function toArray() {
+		return $this->_data;
+	}
+
+	function __toString() {
+		return str_replace('"', '',
+			str_replace([ '{', '}', '":', ',"' ], [ '{ ', ' }', ': ', ', ' ], json_encode($this->_data))
+		);
+	}
+
+}