|
|
@@ -220,21 +220,160 @@ SQL;
|
|
|
default: throw new Exception("Expected ref type for field '{$childName}' in object '{$rootObjectNamespace}'");
|
|
|
}
|
|
|
|
|
|
+ $refInfo = self::getRefConfig($rootObjectNamespace, $childName, $childNamespace);
|
|
|
+
|
|
|
+ if ('view' === $refInfo['SOURCE']) {
|
|
|
+ $refTableName = "CRM__#REF_TABLE__{$refInfo['ID']}_VIEW"; // view created by ACL::generateRefSelectSqlByFlatRelationCache
|
|
|
+ } else {
|
|
|
+ $refTableName = "CRM__#REF_TABLE__{$refInfo['ID']}";
|
|
|
+ if ('WAITING' == $refInfo['A_STATUS']) {
|
|
|
+ DB::getPDO()->execSql("
|
|
|
+ CREATE TABLE IF NOT EXISTS `{$refTableName}` (
|
|
|
+ `PRIMARY_KEY` int(11) NOT NULL
|
|
|
+ , `REMOTE_PRIMARY_KEY` int(11) NOT NULL
|
|
|
+ , `REMOTE_TYPENAME` varchar(255) NOT NULL DEFAULT ''
|
|
|
+ , `A_STATUS` enum('WAITING', 'NORMAL', 'DELETED') NOT NULL DEFAULT 'WAITING'
|
|
|
+ , `TRANSACTION_ID` int(11) NOT NULL
|
|
|
+ , `A_LAST_ACTION_DATE` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
|
+ , KEY `PRIMARY_KEY` (`PRIMARY_KEY`)
|
|
|
+ , KEY `REMOTE_PRIMARY_KEY` (`REMOTE_PRIMARY_KEY`)
|
|
|
+ ) ENGINE=MyISAM DEFAULT CHARSET=latin2 COMMENT='{$rootObjectNamespace} #REF $childName ({$childNamespace})';
|
|
|
+ ");
|
|
|
+ $refInfo['A_STATUS'] = "NORMAL";
|
|
|
+ $refInfo['VERSION'] = self::$REF_TABLE_VERSION;
|
|
|
+ $affected = DB::getPDO()->update("CRM_REF_CONFIG", 'ID', $refInfo['ID'], [
|
|
|
+ 'A_STATUS' => $refInfo['A_STATUS'],
|
|
|
+ 'VERSION' => $refInfo['VERSION']
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($refInfo['VERSION'] < self::$REF_TABLE_VERSION) throw new Exception("TODO: ref table {$refInfo['ID']} require upgrade - field '{$childName}' in object '{$rootObjectNamespace}'");
|
|
|
+
|
|
|
+ $cacheRefTables[$cacheKey] = $refTableName;
|
|
|
+ return $refTableName;
|
|
|
+ }
|
|
|
+ public static function getRefSource($rootObjectNamespace, $childName) { // CRM_REF_CONFIG
|
|
|
+ $refInfo = self::getRefConfig($rootObjectNamespace, $childName);
|
|
|
+ return V::get('SOURCE', 'table', $refInfo);
|
|
|
+ }
|
|
|
+ public static function generateRefSelectSqlByFlatRelationCache($rootObjectNamespace, $childName) { // CRM_REF_CONFIG
|
|
|
+ $appInfo = DB::getPDO()->fetchValue("
|
|
|
+ select f.appInfo
|
|
|
+ from `CRM_#CACHE_ACL_OBJECT_FIELD` f
|
|
|
+ where f.objectNamespace = '{$rootObjectNamespace}'
|
|
|
+ and f.fieldNamespace = '{$childName}'
|
|
|
+ ");
|
|
|
+ if (!$appInfo) throw new Exception("Missing app:info for field '{$rootObjectNamespace}/{$childName}'");
|
|
|
+ $appInfo = @json_decode($appInfo, $assoc = true);
|
|
|
+ if (empty($appInfo)) throw new Exception("Empty app:info for field '{$rootObjectNamespace}/{$childName}'");
|
|
|
+
|
|
|
+ DBG::log(['$appInfo'=>$appInfo, '$rootObjectNamespace'=>$rootObjectNamespace, '$childName'=>$childName], 'array', "\$appInfo");
|
|
|
+ $rootAcl = self::getAclByNamespace($rootObjectNamespace);
|
|
|
+ $childXsdType = $rootAcl->getXsdFieldType($childName);
|
|
|
+ list($typePrefix, $childNamespace) = explode(':', $childXsdType, 2);
|
|
|
+ switch ($typePrefix) {
|
|
|
+ case 'ref_uri': $childAcl = self::getAclByNamespace($childNamespace); break;
|
|
|
+ case 'ref': $childAcl = self::getAclByTypeName($childNamespace); break;
|
|
|
+ default: throw new Exception("Expected ref type for field '{$childName}' in object '{$rootObjectNamespace}'");
|
|
|
+ }
|
|
|
+
|
|
|
+ $lastActionDateField = "NULL"; // , IF(l.A_RECORD_UPDATE_DATE > r.A_RECORD_UPDATE_DATE, l.A_RECORD_UPDATE_DATE, r.A_RECORD_UPDATE_DATE) as A_LAST_ACTION_DATE
|
|
|
+ $rootPrimaryKeyField = $rootAcl->getPrimaryKeyField();
|
|
|
+ $childPrimaryKeyField = $childAcl->getPrimaryKeyField();
|
|
|
+ $rootTableName = $rootAcl->getRootTableName();
|
|
|
+ $childTableName = $childAcl->getRootTableName();
|
|
|
+ // '$appInfo' => [
|
|
|
+ // 'flat_relation_cache' => [
|
|
|
+ // 'source' => [
|
|
|
+ // '@name' => 'ID',
|
|
|
+ // '@xpath' => 'default_db__x3A__CRM_WSKAZNIK:CRM_WSKAZNIK/ID_PROCES',
|
|
|
+ // ),
|
|
|
+ // ),
|
|
|
+ // ),
|
|
|
+ // '$rootObjectNamespace' => 'default_db/CRM_PROCES/PROCES',
|
|
|
+ // '$childName' => 'default_db__x3A__CRM_WSKAZNIK:CRM_WSKAZNIK',
|
|
|
+
|
|
|
+ // '$appInfo' => [
|
|
|
+ // 'flat_relation_cache' => [
|
|
|
+ // 'source' => [
|
|
|
+ // '@name' => 'ID',
|
|
|
+ // '@xpath' => 'default_db__x3A__CRM_PROCES:PROCES/PARENT_ID',
|
|
|
+ // ),
|
|
|
+ // ),
|
|
|
+ // ),
|
|
|
+ // '$rootObjectNamespace' => 'default_db/CRM_PROCES/PROCES',
|
|
|
+ // '$childName' => 'default_db__x3A__CRM_PROCES:PROCES',
|
|
|
+ $appInfoRootFieldName = null;
|
|
|
+ $appInfoChildFieldName = null;
|
|
|
+ {
|
|
|
+ if (empty($appInfo['flat_relation_cache']['source']['@name'])) throw new Exception("Missing flat_relation_cache/source/@name");
|
|
|
+ if (empty($appInfo['flat_relation_cache']['source']['@xpath'])) throw new Exception("Missing flat_relation_cache/source/@xpath");
|
|
|
+ $appInfoName = $appInfo['flat_relation_cache']['source']['@name'];
|
|
|
+ $appInfoXpath = $appInfo['flat_relation_cache']['source']['@xpath'];
|
|
|
+ // $rootNs = $rootAcl->getNamespace()
|
|
|
+ if ("{$childName}/" === substr($appInfoXpath, 0, strlen("{$childName}/"))) {
|
|
|
+ $appInfoRootFieldName = substr($appInfoXpath, strlen("{$childName}/"));
|
|
|
+ $appInfoChildFieldName = $appInfoName;
|
|
|
+ } else {
|
|
|
+ throw new Exception("TODO parse flat_relation_cache");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (!$appInfoRootFieldName || !$appInfoChildFieldName) throw new Exception("Error Processing flat_relation_cache");
|
|
|
+ $sql = "
|
|
|
+ select l.{$rootPrimaryKeyField} as PRIMARY_KEY
|
|
|
+ , r.{$childPrimaryKeyField} as REMOTE_PRIMARY_KEY
|
|
|
+ , '' as REMOTE_TYPENAME
|
|
|
+ , 'WAITING' as A_STATUS
|
|
|
+ , 0 as TRANSACTION_ID
|
|
|
+ , {$lastActionDateField} as A_LAST_ACTION_DATE
|
|
|
+ from `{$rootTableName}` l
|
|
|
+ join `{$childTableName}` r on(r.{$appInfoRootFieldName} = l.{$appInfoChildFieldName})
|
|
|
+ ";
|
|
|
+ DBG::log($sql, 'sql', "generateRefSelectSqlByFlatRelationCache");
|
|
|
+ return $sql;
|
|
|
+ }
|
|
|
+ public static function setRefSource($rootObjectNamespace, $childName, $source, $viewSelectSql = null) { // CRM_REF_CONFIG
|
|
|
+ if (!in_array($source, ['view', 'table'])) throw new Exception("Wrong param source - expected 'table' or 'view'");
|
|
|
+ if ('view' === $source && !$viewSelectSql) throw new Exception("Missing create view sql");
|
|
|
+ $refInfo = self::getRefConfig($rootObjectNamespace, $childName);
|
|
|
+ if ($source != $refInfo['SOURCE']) {
|
|
|
+ if ('view' === $source) {
|
|
|
+ $refTableName = "CRM__#REF_TABLE__{$refInfo['ID']}_VIEW";
|
|
|
+ DB::getPDO()->execSql(" CREATE OR REPLACE DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `{$refTableName}` AS {$viewSelectSql} ");
|
|
|
+ }
|
|
|
+ $affected = DB::getPDO()->update("CRM_REF_CONFIG", 'ID', $refInfo['ID'], [
|
|
|
+ 'SOURCE' => $source,
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ public static function getRefConfig($rootObjectNamespace, $childName, $childNamespace = null) { // CRM_REF_CONFIG
|
|
|
+ if (!$childNamespace) {
|
|
|
+ $rootAcl = self::getAclByNamespace($rootObjectNamespace);
|
|
|
+ $childXsdType = $rootAcl->getXsdFieldType($childName);
|
|
|
+ list($typePrefix, $childNamespace) = explode(':', $childXsdType, 2);
|
|
|
+ DBG::log(['$childXsdType' => $childXsdType, '$typePrefix' => $typePrefix, '$childNamespace' => $childNamespace], 'array', "DBG get ref table ...");
|
|
|
+ switch ($typePrefix) {
|
|
|
+ case 'ref_uri': $childAcl = self::getAclByNamespace($childNamespace); break;
|
|
|
+ case 'ref': $childAcl = self::getAclByTypeName($childNamespace); break;
|
|
|
+ default: throw new Exception("Expected ref type for field '{$childName}' in object '{$rootObjectNamespace}'");
|
|
|
+ }
|
|
|
+ }
|
|
|
$refInfo = [];// define $refInfo = [ ID, A_STATUS, VERSION ]
|
|
|
try {// check that ref config table exists
|
|
|
$sqlRootTableNs = DB::getPDO()->quote($rootObjectNamespace, PDO::PARAM_STR);
|
|
|
$sqlChildName = DB::getPDO()->quote($childName, PDO::PARAM_STR);
|
|
|
$sqlChildNamespace = DB::getPDO()->quote($childNamespace, PDO::PARAM_STR);
|
|
|
$refInfo = DB::getPDO()->fetchFirst("
|
|
|
- select c.ID, c.A_STATUS, c.VERSION
|
|
|
+ select c.ID, c.A_STATUS, c.VERSION, c.SOURCE
|
|
|
from `CRM_REF_CONFIG` c
|
|
|
where c.ROOT_OBJECT_NS = {$sqlRootTableNs}
|
|
|
and c.CHILD_NAME = {$sqlChildName}
|
|
|
and c.CHILD_NS = {$sqlChildNamespace}
|
|
|
");
|
|
|
} catch (Exception $e) {
|
|
|
- DB::getPDO()->exec("
|
|
|
- CREATE TABLE `CRM_REF_CONFIG` (
|
|
|
+ DB::getPDO()->execSql("
|
|
|
+ CREATE TABLE IF NOT EXISTS `CRM_REF_CONFIG` (
|
|
|
`ID` INT NOT NULL AUTO_INCREMENT
|
|
|
, `ROOT_OBJECT_NS` VARCHAR(255) NOT NULL
|
|
|
, `CHILD_NAME` VARCHAR(255) NOT NULL
|
|
|
@@ -245,9 +384,14 @@ SQL;
|
|
|
, PRIMARY KEY (`ID`)
|
|
|
) ENGINE = MyISAM DEFAULT CHARSET=latin2;
|
|
|
");
|
|
|
+ try {
|
|
|
+ DB::getPDO()->execSql(" ALTER TABLE `CRM_REF_CONFIG` ADD `SOURCE` enum('table', 'view') not null default 'table' ");
|
|
|
+ } catch (Exception $e) {
|
|
|
+ DBG::log($e);
|
|
|
+ }
|
|
|
}
|
|
|
if (empty($refInfo)) {
|
|
|
- $refInfo = [ 'ID' => 0, 'A_STATUS' => 'WAITING', 'VERSION' => 0 ];
|
|
|
+ $refInfo = [ 'ID' => 0, 'A_STATUS' => 'WAITING', 'VERSION' => 0, 'SOURCE' => 'table' ];
|
|
|
$refInfo['ID'] = DB::getPDO()->insert("CRM_REF_CONFIG", [
|
|
|
'ROOT_OBJECT_NS' => $rootObjectNamespace,
|
|
|
'CHILD_NAME' => $childName,
|
|
|
@@ -255,33 +399,7 @@ SQL;
|
|
|
]);
|
|
|
}
|
|
|
if (!$refInfo['ID']) throw new Exception("Ref table not found in ref config table for field '{$childName}' in object '{$rootObjectNamespace}'");
|
|
|
-
|
|
|
- $refTableName = "CRM__#REF_TABLE__{$refInfo['ID']}";
|
|
|
- if ('WAITING' == $refInfo['A_STATUS']) {
|
|
|
- DB::getPDO()->exec("
|
|
|
- CREATE TABLE IF NOT EXISTS `{$refTableName}` (
|
|
|
- `PRIMARY_KEY` int(11) NOT NULL
|
|
|
- , `REMOTE_PRIMARY_KEY` int(11) NOT NULL
|
|
|
- , `REMOTE_TYPENAME` varchar(255) NOT NULL DEFAULT ''
|
|
|
- , `A_STATUS` enum('WAITING', 'NORMAL', 'DELETED') NOT NULL DEFAULT 'WAITING'
|
|
|
- , `TRANACTION_ID` int(11) NOT NULL
|
|
|
- , `A_LAST_ACTION_DATE` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
|
|
- , KEY `PRIMARY_KEY` (`PRIMARY_KEY`)
|
|
|
- , KEY `REMOTE_PRIMARY_KEY` (`REMOTE_PRIMARY_KEY`)
|
|
|
- ) ENGINE=MyISAM DEFAULT CHARSET=latin2 COMMENT='{$rootObjectNamespace} #REF $childName ({$childNamespace})';
|
|
|
- ");
|
|
|
- $refInfo['A_STATUS'] = "NORMAL";
|
|
|
- $refInfo['VERSION'] = self::$REF_TABLE_VERSION;
|
|
|
- $affected = DB::getPDO()->update("CRM_REF_CONFIG", 'ID', $refInfo['ID'], [
|
|
|
- 'A_STATUS' => $refInfo['A_STATUS'],
|
|
|
- 'VERSION' => $refInfo['VERSION']
|
|
|
- ]);
|
|
|
- }
|
|
|
-
|
|
|
- if ($refInfo['VERSION'] < self::$REF_TABLE_VERSION) throw new Exception("TODO: ref table {$refInfo['ID']} require upgrade - field '{$childName}' in object '{$rootObjectNamespace}'");
|
|
|
-
|
|
|
- $cacheRefTables[$cacheKey] = $refTableName;
|
|
|
- return $refTableName;
|
|
|
+ return $refInfo;
|
|
|
}
|
|
|
|
|
|
public static function getInstanceId($namespace) { // CRM_INSTANCE_CONFIG
|