|
@@ -29,6 +29,8 @@ class AclQueryBuilder {
|
|
|
public $_joinParams;
|
|
public $_joinParams;
|
|
|
public $isInstances;
|
|
public $isInstances;
|
|
|
public $isNotInstances;
|
|
public $isNotInstances;
|
|
|
|
|
+ public $_hasSelectRemoteFields;
|
|
|
|
|
+ public $_hasQueryRemoteFields;
|
|
|
|
|
|
|
|
public function __construct() {
|
|
public function __construct() {
|
|
|
$this->select = [];
|
|
$this->select = [];
|
|
@@ -43,6 +45,9 @@ class AclQueryBuilder {
|
|
|
$this->_joinParams = []; // prefx => params
|
|
$this->_joinParams = []; // prefx => params
|
|
|
$this->isInstances = [];
|
|
$this->isInstances = [];
|
|
|
$this->isNotInstances = [];
|
|
$this->isNotInstances = [];
|
|
|
|
|
+
|
|
|
|
|
+ $this->_hasSelectRemoteFields = false;
|
|
|
|
|
+ $this->_hasQueryRemoteFields = false;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
public function from($from, $prefix = 't') {
|
|
public function from($from, $prefix = 't') {
|
|
@@ -136,6 +141,33 @@ class AclQueryBuilder {
|
|
|
return $this;
|
|
return $this;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ public function _generateSelectMain($select, $key) {
|
|
|
|
|
+ if ('__rawSelect__' === $key) return $select;
|
|
|
|
|
+ $sqlPk = 'ID';
|
|
|
|
|
+ if ($this->from instanceof Core_AclBase) $sqlPk = $this->from->getSqlPrimaryKeyField();
|
|
|
|
|
+ if ('@instnces' === $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`
|
|
|
|
|
+ ";
|
|
|
|
|
+ }
|
|
|
|
|
+ if (is_array($select)) {
|
|
|
|
|
+ // TODO: [ '__backRef' => [ ... ] ]
|
|
|
|
|
+ DBG::log($select, 'array', "TODO: select array");
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // TODO: only real table field
|
|
|
|
|
+ // TODO: if geometry type then `AsWKT(t.`{$fieldName}`) as {$fieldName}`
|
|
|
|
|
+ return $this->parseSelectFieldValueToSql($select, $this->_fromPrefix);
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
public function join($join, $prefix, $params) {
|
|
public function join($join, $prefix, $params) {
|
|
|
if (array_key_exists($prefix, $this->_joinPrefix)) throw new Exception("Prefix already used!");
|
|
if (array_key_exists($prefix, $this->_joinPrefix)) throw new Exception("Prefix already used!");
|
|
|
$this->_joinPrefix[$prefix] = $join;
|
|
$this->_joinPrefix[$prefix] = $join;
|
|
@@ -223,7 +255,7 @@ class AclQueryBuilder {
|
|
|
|
|
|
|
|
public function fetchValue() {
|
|
public function fetchValue() {
|
|
|
$sql = $this->generateSql();
|
|
$sql = $this->generateSql();
|
|
|
- DBG::log((array)$this, 'array', "AclQueryBuilder::fetchValue");
|
|
|
|
|
|
|
+ DBG::log(['sql'=>$sql,'this'=>(array)$this], 'array', "AclQueryBuilder::fetchValue");
|
|
|
return DB::getPDO()->fetchValue($sql);
|
|
return DB::getPDO()->fetchValue($sql);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -291,27 +323,21 @@ class AclQueryBuilder {
|
|
|
$offset = ($this->offset < 0) ? 0 : $this->offset;
|
|
$offset = ($this->offset < 0) ? 0 : $this->offset;
|
|
|
$sqlLimit = ($limit > 0) ? "limit {$limit} offset {$offset}" : '';
|
|
$sqlLimit = ($limit > 0) ? "limit {$limit} offset {$offset}" : '';
|
|
|
|
|
|
|
|
- $sqlSelect = [];
|
|
|
|
|
- if (!empty($this->select['__rawSelect__'])) {
|
|
|
|
|
- $sqlSelect[] = $this->select['__rawSelect__'];
|
|
|
|
|
- } else {
|
|
|
|
|
- $sqlSelect[] = "{$this->_fromPrefix}.{$sqlPk}";
|
|
|
|
|
- if (in_array('*', $this->select)) $sqlSelect[] = "{$this->_fromPrefix}.*";
|
|
|
|
|
- }
|
|
|
|
|
- if (in_array('@instances', $this->select)) {
|
|
|
|
|
- if (!($this->from instanceof Core_AclBase)) throw new Exception("select @instances allowed only for Acl object");
|
|
|
|
|
- $instanceTable = ACL::getInstanceTable($this->from->getNamespace());
|
|
|
|
|
- $sqlSelect[] = "
|
|
|
|
|
- (
|
|
|
|
|
- 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: split select to local and remote (use field isLocal)
|
|
|
|
|
+ // TODO: $this->_hasSelectRemoteFields = false;
|
|
|
|
|
+ // TODO: $this->_hasQueryRemoteFields = false;
|
|
|
|
|
+
|
|
|
|
|
+ // TODO: select must contain primaryKey
|
|
|
|
|
+ $sqlSelect = array_filter(
|
|
|
|
|
+ array_map([$this, '_generateSelectMain'], $this->select, array_keys($this->select)),
|
|
|
|
|
+ 'is_string'
|
|
|
|
|
+ );
|
|
|
|
|
+ $sqlSelect = (!empty($sqlSelect))
|
|
|
|
|
+ ? implode("\n\t and ", $sqlSelect)
|
|
|
|
|
+ : "{$this->_fromPrefix}.*"
|
|
|
|
|
+ ;
|
|
|
|
|
+
|
|
|
$sqlOrderBy = $this->generateOrderBySql();
|
|
$sqlOrderBy = $this->generateOrderBySql();
|
|
|
- $sqlSelect = (!empty($sqlSelect)) ? implode(", ", $sqlSelect) : "{$this->_fromPrefix}.*";
|
|
|
|
|
return "
|
|
return "
|
|
|
select {$sqlSelect}
|
|
select {$sqlSelect}
|
|
|
from `{$tableName}` {$this->_fromPrefix}
|
|
from `{$tableName}` {$this->_fromPrefix}
|
|
@@ -322,4 +348,26 @@ class AclQueryBuilder {
|
|
|
";
|
|
";
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ public function parseSelectFieldValueToSql($fieldName, $prefix = 't') {
|
|
|
|
|
+ if (false !== strpos($fieldName, '/')) {
|
|
|
|
|
+ DBG::log($fieldName, 'string', "TODO: select by xpath");
|
|
|
|
|
+ throw new Exception("Not implemented select by xpath ('{$fieldName}')");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ $fieldType = $this->from->getXsdFieldType($fieldName);
|
|
|
|
|
+ if ('xsd:' === substr($fieldType, 0, 4)) {
|
|
|
|
|
+ return "{$prefix}.`{$fieldName}`";
|
|
|
|
|
+ }
|
|
|
|
|
+ switch ($fieldType) {
|
|
|
|
|
+ case 'gml:PolygonPropertyType':
|
|
|
|
|
+ case 'gml:PointPropertyType':
|
|
|
|
|
+ case 'gml:LineStringPropertyType':
|
|
|
|
|
+ case 'gml:GeometryPropertyType': return "AsWKT({$prefix}.`{$fieldName}`) as `{$fieldName}`";
|
|
|
|
|
+ case 'p5:enum': { // TODO: check if local or remote
|
|
|
|
|
+ return "{$prefix}.`{$fieldName}`";
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return null;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
}
|
|
}
|