(Experimental) Export a DBSearch as an array/JSON structure.

This commit is contained in:
Denis Flaven
2019-11-13 18:03:37 +01:00
parent 30430bb7dc
commit 36584092e5
4 changed files with 279 additions and 2 deletions

View File

@@ -1524,6 +1524,80 @@ class DBObjectSearch extends DBSearch
} }
} }
/**
* {@inheritDoc}
* @see DBSearch::ToJSON()
*/
public function ToJSON()
{
$aRet = array('selects' => array(), 'joins' => array(), 'where' => array());
$aParams = array_merge($this->m_aParams);
$aParams = MetaModel::PrepareQueryArguments($aParams);
foreach ($this->m_aSelectedClasses as $sAlias => $sClass)
{
$aRet['selects'][] = array('class' => $sClass, 'alias' => $sAlias);
}
$this->JoinsToJSON($aRet);
$aRet['condition'] = $this->m_oSearchCondition->ToJSON($aParams, true);
return $aRet;
}
/**
* Export the JOIN operations to a structure (array of arrays) suitable for JSON export
*
* @internal
*
* @param mixed[string] $aRet
* @return void
*/
protected function JoinsToJSON(&$aRet)
{
foreach($this->m_aPointingTo as $sExtKey => $aPointingTo)
{
foreach($aPointingTo as $iOperatorCode => $aFilter)
{
$sOperator = $this->OperatorCodeToOQL($iOperatorCode);
foreach($aFilter as $oFilter)
{
$aRet['joins'][] = array(
'src' => $this->GetFirstJoinedClass(),
'src_alias' => $this->GetFirstJoinedClassAlias(),
'target' => $oFilter->GetFirstJoinedClass(),
'target_alias' => $oFilter->GetFirstJoinedClassAlias(),
'foreign_key' => $sExtKey,
'operator' => $sOperator,
);
$oFilter->JoinsToJSON($aRet);
}
}
}
foreach($this->m_aReferencedBy as $aReferences)
{
foreach($aReferences as $sForeignExtKeyAttCode => $aFiltersByOperator)
{
foreach ($aFiltersByOperator as $iOperatorCode => $aFilters)
{
$sOperator = $this->OperatorCodeToOQL($iOperatorCode);
foreach ($aFilters as $oForeignFilter)
{
$aRet['joins'][] = array(
'src' => $oForeignFilter->GetFirstJoinedClass(),
'src_alias' => $oForeignFilter->GetFirstJoinedClassAlias(),
'target' => $this->GetFirstJoinedClass(),
'target_alias' => $this->GetFirstJoinedClassAlias(),
'foreign_key' => $sForeignExtKeyAttCode,
'operator' => $sOperator,
);
$oForeignFilter->JoinsToJSON($aRet);
}
}
}
}
}
public function InitFromOqlQuery(OqlQuery $oOqlQuery, $sQuery) public function InitFromOqlQuery(OqlQuery $oOqlQuery, $sQuery)
{ {
$oModelReflection = new ModelReflectionRuntime(); $oModelReflection = new ModelReflectionRuntime();

View File

@@ -699,6 +699,15 @@ abstract class DBSearch
*/ */
abstract public function ToOQL($bDevelopParams = false, $aContextParams = null, $bWithAllowAllFlag = false); abstract public function ToOQL($bDevelopParams = false, $aContextParams = null, $bWithAllowAllFlag = false);
/**
* Export the DBSearch as a structure (array of arrays...) suitable for a conversion to JSON
*
* @internal
*
* @return mixed[string]
*/
abstract public function ToJSON();
static protected $m_aOQLQueries = array(); static protected $m_aOQLQueries = array();
/** /**
@@ -734,12 +743,13 @@ abstract class DBSearch
* *
* @param string $sQuery The OQL to convert to a DBSearch * @param string $sQuery The OQL to convert to a DBSearch
* @param mixed[string] $aParams array of <mixed> params index by <string> name * @param mixed[string] $aParams array of <mixed> params index by <string> name
* @param ModelReflection|null $oMetaModel The MetaModel to use when checking the consistency of the OQL
* *
* @return DBObjectSearch|DBUnionSearch * @return DBObjectSearch|DBUnionSearch
* *
* @throws OQLException * @throws OQLException
*/ */
static public function FromOQL($sQuery, $aParams = null) static public function FromOQL($sQuery, $aParams = null, ModelReflection $oMetaModel=null)
{ {
if (empty($sQuery)) if (empty($sQuery))
{ {
@@ -781,7 +791,10 @@ abstract class DBSearch
$oOql = new OqlInterpreter($sQuery); $oOql = new OqlInterpreter($sQuery);
$oOqlQuery = $oOql->ParseQuery(); $oOqlQuery = $oOql->ParseQuery();
$oMetaModel = new ModelReflectionRuntime(); if ($oMetaModel === null)
{
$oMetaModel = new ModelReflectionRuntime();
}
$oOqlQuery->Check($oMetaModel, $sQuery); // Exceptions thrown in case of issue $oOqlQuery->Check($oMetaModel, $sQuery); // Exceptions thrown in case of issue
$oResultFilter = $oOqlQuery->ToDBSearch($sQuery); $oResultFilter = $oOqlQuery->ToDBSearch($sQuery);

View File

@@ -463,6 +463,20 @@ class DBUnionSearch extends DBSearch
return $sRet; return $sRet;
} }
/**
* {@inheritDoc}
* @see DBSearch::ToJSON()
*/
public function ToJSON()
{
$sRet = array('unions' => array());
foreach ($this->aSearches as $oSearch)
{
$sRet['unions'][] = $oSearch->ToJSON();
}
return $sRet;
}
/** /**
* Returns a new DBUnionSearch object where duplicates queries have been removed based on their OQLs * Returns a new DBUnionSearch object where duplicates queries have been removed based on their OQLs
* *

View File

@@ -27,6 +27,17 @@ class MissingQueryArgument extends CoreException
*/ */
abstract class Expression abstract class Expression
{ {
public const OPERATOR_BINARY = 'binary';
public const OPERATOR_BOOLEAN = 'boolean_binary';
public const OPERATOR_FIELD = 'field';
public const OPERATOR_FUNCTION = 'function';
public const OPERATOR_INTERVAL = 'interval';
public const OPERATOR_LIST = 'list';
public const OPERATOR_SCALAR = 'scalar';
public const OPERATOR_UNARY = 'unary';
public const OPERATOR_VARIABLE = 'variable';
/** /**
* Perform a deep clone (as opposed to "clone" which does copy a reference to the underlying objects) * Perform a deep clone (as opposed to "clone" which does copy a reference to the underlying objects)
**/ **/
@@ -98,6 +109,15 @@ abstract class Expression
*/ */
abstract public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false); abstract public function RenderExpression($bForSQL = false, &$aArgs = null, $bRetrofitParams = false);
/**
* Recursively renders the expression as a structure (array) suitable for a JSON export
*
* @param mixed[string] $aArgs
* @param boolean $bRetrofitParams
* @return mixed[string]
*/
abstract public function ToJSON(&$aArgs = null, $bRetrofitParams = false);
/** /**
* @param DBObjectSearch $oSearch * @param DBObjectSearch $oSearch
* @param array $aArgs * @param array $aArgs
@@ -277,6 +297,12 @@ class SQLExpression extends Expression
return $this->m_sSQL; return $this->m_sSQL;
} }
// recursive rendering
public function toJSON(&$aArgs = null, $bRetrofitParams = false)
{
return null; // TODO should we throw an Exception ??
}
public function Browse(Closure $callback) public function Browse(Closure $callback)
{ {
$callback($this); $callback($this);
@@ -413,6 +439,31 @@ class BinaryExpression extends Expression
return "($sLeft $sOperator $sRight)"; return "($sLeft $sOperator $sRight)";
} }
/**
* {@inheritDoc}
* @see Expression::ToJSON()
*/
public function ToJSON(&$aArgs = null, $bRetrofitParams = false)
{
if (($this->GetOperator() == 'AND') || ($this->GetOperator() == 'OR'))
{
return array(
'type' => static::OPERATOR_BOOLEAN,
'operator' => $this->GetOperator(),
'left' => $this->GetLeftExpr()->ToJSON($aArgs, $bRetrofitParams),
'right' => $this->GetRightExpr()->ToJSON($aArgs, $bRetrofitParams),
'oql' => $this->RenderExpression(false, $aArgs, $bRetrofitParams),
);
}
return array(
'type' => static::OPERATOR_BINARY,
'operator' => $this->GetOperator(),
'left' => $this->GetLeftExpr()->ToJSON($aArgs, $bRetrofitParams),
'right' => $this->GetRightExpr()->ToJSON($aArgs, $bRetrofitParams),
'oql' => $this->RenderExpression(false, $aArgs, $bRetrofitParams),
);
}
public function Browse(Closure $callback) public function Browse(Closure $callback)
{ {
$callback($this); $callback($this);
@@ -789,6 +840,19 @@ class UnaryExpression extends Expression
return CMDBSource::Quote($this->m_value); return CMDBSource::Quote($this->m_value);
} }
/**
* {@inheritDoc}
* @see Expression::ToJSON()
*/
public function ToJSON(&$aArgs = null, $bRetrofitParams = false)
{
return array(
'type' => static::OPERATOR_UNARY,
'value' => $this->m_value,
'oql' => $this->RenderExpression(false, $aArgs, $bRetrofitParams),
);
}
public function Browse(Closure $callback) public function Browse(Closure $callback)
{ {
$callback($this); $callback($this);
@@ -909,6 +973,19 @@ class ScalarExpression extends UnaryExpression
return $sRet; return $sRet;
} }
/**
* {@inheritDoc}
* @see Expression::ToJSON()
*/
public function ToJSON(&$aArgs = null, $bRetrofitParams = false)
{
return array(
'type' => static::OPERATOR_SCALAR,
'value' => $this->m_value,
'oql' => $this->RenderExpression(false, $aArgs, $bRetrofitParams),
);
}
public function GetAsScalar($aArgs) public function GetAsScalar($aArgs)
{ {
return clone $this; return clone $this;
@@ -1157,6 +1234,21 @@ class FieldExpression extends UnaryExpression
return "`{$this->m_sParent}`.`{$this->m_sName}`"; return "`{$this->m_sParent}`.`{$this->m_sName}`";
} }
/**
* {@inheritDoc}
* @see Expression::ToJSON()
*/
public function ToJSON(&$aArgs = null, $bRetrofitParams = false)
{
return array(
'type' => static::OPERATOR_FIELD,
'value' => $this->m_value,
'alias' => $this->m_sParent,
'field' => $this->m_sName,
'oql' => $this->RenderExpression(false, $aArgs, $bRetrofitParams),
);
}
public function GetAttDef($aClasses = array()) public function GetAttDef($aClasses = array())
{ {
if (!empty($this->m_sParent)) if (!empty($this->m_sParent))
@@ -1546,6 +1638,19 @@ class VariableExpression extends UnaryExpression
} }
} }
/**
* {@inheritDoc}
* @see Expression::ToJSON()
*/
public function ToJSON(&$aArgs = null, $bRetrofitParams = false)
{
return array(
'type' => static::OPERATOR_VARIABLE,
'value' => $this->m_value,
'oql' => $this->RenderExpression(false, $aArgs, $bRetrofitParams),
);
}
public function RenameParam($sOldName, $sNewName) public function RenameParam($sOldName, $sNewName)
{ {
if ($this->m_sName == $sOldName) if ($this->m_sName == $sOldName)
@@ -1645,6 +1750,24 @@ class ListExpression extends Expression
return '('.implode(', ', $aRes).')'; return '('.implode(', ', $aRes).')';
} }
/**
* {@inheritDoc}
* @see Expression::ToJSON()
*/
public function ToJSON(&$aArgs = null, $bRetrofitParams = false)
{
$aFields = array();
foreach ($this->m_aExpressions as $oExpr)
{
$aFields[] = $oExpr->ToJSON($aArgs, $bRetrofitParams);
}
return array(
'type' => static::OPERATOR_LIST,
'fields' => $aFields,
'oql' => $this->RenderExpression(false, $aArgs, $bRetrofitParams),
);
}
public function Browse(Closure $callback) public function Browse(Closure $callback)
{ {
$callback($this); $callback($this);
@@ -1798,6 +1921,26 @@ class FunctionExpression extends Expression
return $this->m_sVerb.'('.implode(', ', $aRes).')'; return $this->m_sVerb.'('.implode(', ', $aRes).')';
} }
/**
* {@inheritDoc}
* @see Expression::ToJSON()
*/
public function ToJSON(&$aArgs = null, $bRetrofitParams = false)
{
$aFields = array();
foreach ($this->m_aArgs as $oExpr)
{
$aFields[] = $oExpr->ToJSON($aArgs, $bRetrofitParams);
}
return array(
'type' => static::OPERATOR_FUNCTION,
'operator' => $this->m_sVerb,
'fields' => $aFields,
'oql' => $this->RenderExpression(false, $aArgs, $bRetrofitParams),
);
}
public function Browse(Closure $callback) public function Browse(Closure $callback)
{ {
$callback($this); $callback($this);
@@ -2093,6 +2236,20 @@ class IntervalExpression extends Expression
return 'INTERVAL '.$this->m_oValue->RenderExpression($bForSQL, $aArgs, $bRetrofitParams).' '.$this->m_sUnit; return 'INTERVAL '.$this->m_oValue->RenderExpression($bForSQL, $aArgs, $bRetrofitParams).' '.$this->m_sUnit;
} }
/**
* {@inheritDoc}
* @see Expression::ToJSON()
*/
public function ToJSON(&$aArgs = null, $bRetrofitParams = false)
{
return array(
'type' => static::OPERATOR_INTERVAL,
'unit' => $this->m_sUnit,
'expression' => $this->m_oValue->ToJSON($aArgs, $bRetrofitParams),
'oql' => $this->RenderExpression(false, $aArgs, $bRetrofitParams),
);
}
public function Browse(Closure $callback) public function Browse(Closure $callback)
{ {
$callback($this); $callback($this);
@@ -2192,6 +2349,25 @@ class CharConcatExpression extends Expression
return "CAST(CONCAT(".implode(', ', $aRes).") AS CHAR)"; return "CAST(CONCAT(".implode(', ', $aRes).") AS CHAR)";
} }
/**
* {@inheritDoc}
* @see Expression::ToJSON()
*/
public function ToJSON(&$aArgs = null, $bRetrofitParams = false)
{
$aFields = array();
foreach ($this->m_aExpressions as $oExpr)
{
$aFields[] = $oExpr->RenderExpression($aArgs, $bRetrofitParams);
}
return array(
'type' => static::OPERATOR_FUNCTION,
'operator' => 'concat',
'fields' => $aFields,
);
}
public function Browse(Closure $callback) public function Browse(Closure $callback)
{ {
$callback($this); $callback($this);