summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwei <>2006-07-26 01:44:57 +0000
committerwei <>2006-07-26 01:44:57 +0000
commit5c1132f6da292a689bc52bd7f20a83ff8d733fbd (patch)
tree3b61f33aff5aac63bc192564602c2ff482913cf5
parentcbb7a11179b9c1c46e35f04d07d6386a44e400b2 (diff)
Allow nested GroupBy result maps
-rw-r--r--demos/time-tracker/protected/App_Code/UserReport.php6
-rw-r--r--demos/time-tracker/protected/App_Code/UserReportsDao.php5
-rw-r--r--demos/time-tracker/protected/application.xml3
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.php4
-rw-r--r--demos/time-tracker/protected/pages/TimeTracker/ReportProject.page6
-rw-r--r--framework/DataAccess/SQLMap/DataMapper/TPropertyAccess.php8
-rw-r--r--framework/DataAccess/SQLMap/DataMapper/messages.txt4
-rw-r--r--framework/DataAccess/SQLMap/Statements/TMappedStatement.php223
8 files changed, 194 insertions, 65 deletions
diff --git a/demos/time-tracker/protected/App_Code/UserReport.php b/demos/time-tracker/protected/App_Code/UserReport.php
index e7529120..d37de934 100644
--- a/demos/time-tracker/protected/App_Code/UserReport.php
+++ b/demos/time-tracker/protected/App_Code/UserReport.php
@@ -2,9 +2,9 @@
class UserReport
{
- public $Username = '';
- public $CategoryID = 0;
- public $ActualDuration = 0.0;
+ public $CategoryName = '';
+ public $users = array();
+ public $ProjectName = '';
}
?> \ No newline at end of file
diff --git a/demos/time-tracker/protected/App_Code/UserReportsDao.php b/demos/time-tracker/protected/App_Code/UserReportsDao.php
index 3cf943af..c6eab660 100644
--- a/demos/time-tracker/protected/App_Code/UserReportsDao.php
+++ b/demos/time-tracker/protected/App_Code/UserReportsDao.php
@@ -14,10 +14,11 @@ class UserReportsDao extends BaseDao
return $sqlmap->queryForList('GetTimeReportByCategoryID', $categoryID);
}
- public function getTimeReportsByProjectID($projectID)
+ public function getTimeReportsByProjectIDs($projects)
{
+ $ids = implode(',', array_map('intval', $projects));
$sqlmap = $this->getConnection();
- return $sqlmap->queryForList('GetTimeReportByProjectID', $projectID);
+ return $sqlmap->queryForList('GetTimeReportByProjectIDs', $ids);
}
}
diff --git a/demos/time-tracker/protected/application.xml b/demos/time-tracker/protected/application.xml
index 02be327b..97e26ae8 100644
--- a/demos/time-tracker/protected/application.xml
+++ b/demos/time-tracker/protected/application.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
-<application id="Database" Mode="Debug">
+<application id="Database" Mode="Performance">
<!-- configure to use Quickstart theme directory -->
<paths>
@@ -10,6 +10,7 @@
<using namespace="Application.App_Code.*" />
</paths>
<modules>
+ <module id="cache" class="System.Caching.TMemCache" />
<module id="sqlmap" class="TSQLMap"
configFile="Application.App_Data.mysql-sqlmap" />
<module id="daos" class="DaoManager" Connection="sqlmap">
diff --git a/demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.php b/demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.php
index cc27c93c..a134289c 100644
--- a/demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.php
+++ b/demos/time-tracker/protected/pages/TimeTracker/LogTimeEntry.php
@@ -50,8 +50,10 @@ class LogTimeEntry extends TPage
$this->projectMembers->DataSource = $users;
$this->projectMembers->dataBind();
if(is_int($index = array_search($this->User->Name, $users)))
+ {
$this->projectMembers->SelectedIndex = $index;
- $this->showTimeSheet();
+ $this->showTimeSheet();
+ }
}
public function showTimeSheet()
diff --git a/demos/time-tracker/protected/pages/TimeTracker/ReportProject.page b/demos/time-tracker/protected/pages/TimeTracker/ReportProject.page
index 065b6b17..50345afa 100644
--- a/demos/time-tracker/protected/pages/TimeTracker/ReportProject.page
+++ b/demos/time-tracker/protected/pages/TimeTracker/ReportProject.page
@@ -5,10 +5,10 @@
<legend>Project Report</legend>
<com:TMultiView ID="views" ActiveViewIndex="0">
<com:TView>
- <com:TLabel ForControl="projects"
+ <com:TLabel ForControl="projectList"
Text="Select a project. Use ctrl+click to select multiple resources at once: "/>
- <com:TListBox ID="projects" CssClass="projects" />
- <com:TButton Text="Generate Report" />
+ <com:TListBox ID="projectList" CssClass="projects" SelectionMode="Multiple" />
+ <com:TButton Text="Generate Report" OnClick="generateReport_Clicked"/>
</com:TView>
</com:TMultiView>
diff --git a/framework/DataAccess/SQLMap/DataMapper/TPropertyAccess.php b/framework/DataAccess/SQLMap/DataMapper/TPropertyAccess.php
index e4f5c1fa..dbd4d6e7 100644
--- a/framework/DataAccess/SQLMap/DataMapper/TPropertyAccess.php
+++ b/framework/DataAccess/SQLMap/DataMapper/TPropertyAccess.php
@@ -96,13 +96,17 @@ class TPropertyAccess
return true;
}
- public static function set($object, $path, $value)
+ public static function set(&$object, $path, $value)
{
$properties = explode('.', $path);
$prop = array_pop($properties);
if(count($properties) > 0)
$object = self::get($object, implode('.',$properties));
- if(is_object($object))
+ if(is_array($object) || $object instanceof ArrayAccess)
+ {
+ $object[$prop] = $value;
+ }
+ else if(is_object($object))
{
$setter = 'set'.$prop;
if(is_callable(array($object, $setter)))
diff --git a/framework/DataAccess/SQLMap/DataMapper/messages.txt b/framework/DataAccess/SQLMap/DataMapper/messages.txt
index 16be9c2b..47bb06e7 100644
--- a/framework/DataAccess/SQLMap/DataMapper/messages.txt
+++ b/framework/DataAccess/SQLMap/DataMapper/messages.txt
@@ -62,4 +62,6 @@ sqlmap_unable_to_find_resource = 'Unable to find SQLMap configuration file '{0
sqlmap_query_execution_error = Error in executing SQLMap statement '{0}' : '{1}'.
sqlmap_undefined_discriminator = The discriminator is null, but somehow a subMap was reached in ResultMap '{0}' in file '{1}'.
sqlmap_invalid_delegate = Invalid callback row delegate '{1}' in mapped statement '{0}'.
-sqlmap_invalid_prado_cache = Unable to find Prado cache module for SQLMap cache '{0}'. \ No newline at end of file
+sqlmap_invalid_prado_cache = Unable to find Prado cache module for SQLMap cache '{0}'.
+
+sqlmap_non_groupby_array_list_type = Expecting GroupBy property in result map '{0}' since {1}::{2} is an array or TList type. \ No newline at end of file
diff --git a/framework/DataAccess/SQLMap/Statements/TMappedStatement.php b/framework/DataAccess/SQLMap/Statements/TMappedStatement.php
index 9bc1143f..5c111c22 100644
--- a/framework/DataAccess/SQLMap/Statements/TMappedStatement.php
+++ b/framework/DataAccess/SQLMap/Statements/TMappedStatement.php
@@ -49,9 +49,9 @@ class TMappedStatement extends TComponent implements IMappedStatement
private $_IsRowDataFound = false;
/**
- * @var array group by result data cache.
+ * @var TSQLMapGroupByTree group by result data cache.
*/
- private $_groupBy=array();
+ private $_groupBy;
/**
* @var Post select is to query for list.
@@ -114,7 +114,7 @@ class TMappedStatement extends TComponent implements IMappedStatement
*/
protected function clearGroupByResults()
{
- $this->_groupBy = array();
+ $this->_groupBy = new TSQLMapGroupByTree();
}
/**
@@ -127,6 +127,7 @@ class TMappedStatement extends TComponent implements IMappedStatement
$this->_sqlMap = $sqlMap;
$this->_statement = $statement;
$this->_command = new TPreparedCommand();
+ $this->clearGroupByResults();
}
/**
@@ -232,17 +233,18 @@ class TMappedStatement extends TComponent implements IMappedStatement
else
{
while($row = $recordSet->fetchRow())
- {
- $obj = $this->applyResultMap($row);
- if(!is_null($obj))
- $list[] = $obj;
- }
+ $list[] = $this->applyResultMap($row);
}
+// var_dump($list);
+ //var_dump($this->_groupBy);
//get the groupings
- foreach($this->getGroupbyResults() as $group)
+ /*foreach($this->getGroupbyResults() as $group)
$list[] = $group->updateProperties();
$this->clearGroupByResults();
+*/
+ if(!$this->_groupBy->isEmpty())
+ $list = $this->_groupBy->collect();
$this->executePostSelect($connection);
$this->onExecuteQuery($sql);
@@ -383,8 +385,8 @@ class TMappedStatement extends TComponent implements IMappedStatement
while($row = $recordSet->fetchRow())
$object = $this->applyResultMap($row, $result);
- foreach($this->getGroupbyResults() as $group)
- $object = $group->updateProperties();
+// foreach($this->getGroupbyResults() as $group)
+ // $object = $group->updateProperties();
$this->clearGroupByResults();
@@ -537,7 +539,7 @@ class TMappedStatement extends TComponent implements IMappedStatement
$resultClass = $this->_statement->getResultClass();
if($this->_sqlMap->getResultMaps()->contains($resultMapName))
- return $this->fillResultMap($resultMapName, $row, $resultObject);
+ return $this->fillResultMap($resultMapName, $row, null, $resultObject);
else if(strlen($resultClass) > 0)
return $this->fillResultClass($resultClass, $row, $resultObject);
else
@@ -612,7 +614,7 @@ class TMappedStatement extends TComponent implements IMappedStatement
* @param object result object to fill, will create new instances if required.
* @return object result object filled with data.
*/
- protected function fillResultMap($resultMapName, $row, &$resultObject)
+ protected function fillResultMap($resultMapName, $row, $parentGroup=null, &$resultObject=null)
{
$resultMap = $this->_sqlMap->getResultMap($resultMapName);
$resultMap = $resultMap->resolveSubMap($row);
@@ -622,7 +624,7 @@ class TMappedStatement extends TComponent implements IMappedStatement
if(is_object($resultObject))
{
if(strlen($resultMap->getGroupBy()) > 0)
- return $this->addResultMapGroupBy($resultMap, $row, $resultObject);
+ return $this->addResultMapGroupBy($resultMap, $row, $parentGroup, $resultObject);
else
foreach($resultMap->getColumns() as $property)
$this->setObjectProperty($resultMap, $property, $row, $resultObject);
@@ -644,23 +646,32 @@ class TMappedStatement extends TComponent implements IMappedStatement
* @see getGroupByResults()
* @see runQueryForList()
*/
- protected function addResultMapGroupBy($resultMap, $row, &$resultObject)
+ protected function addResultMapGroupBy($resultMap, $row, $parent, &$resultObject)
{
$group = $this->getResultMapGroupKey($resultMap, $row, $resultObject);
-
+
+ if(empty($parent))
+ {
+ $root= new TResultMapGroupBy(null, $resultObject);
+ $this->_groupBy->add('root#'.$group, $group, $root);
+ }
+
foreach($resultMap->getColumns() as $property)
{
$scalar = $this->setObjectProperty($resultMap, $property, $row, $resultObject);
- if(strlen($property->getResultMapping()) > 0)
+ $key = $property->getProperty();
+ if(strlen($nested = $property->getResultMapping()) > 0)
{
- $key = $property->getProperty();
- $value = $this->extractGroupByValue($property, $resultObject);
- if(!empty($value))
- $this->_groupBy[$group]->addValue($key, $value);
+ if($this->_sqlMap->getResultMaps()->contains($nested))
+ $value = $this->fillResultMap($nested, $row, $group);
+ else
+ $value = $this->extractGroupByValue($property, $resultObject);
+
+ $groupby = new TResultMapGroupBy($key, $value);
+ $this->_groupBy->add($parent, $group, $groupby);
}
}
-
- return null;
+ return $resultObject;
}
/**
@@ -693,10 +704,7 @@ class TMappedStatement extends TComponent implements IMappedStatement
$groupBy = $resultMap->getGroupBy();
if(isset($row[$groupBy]))
{
- $group = $row[$groupBy];
- if(!isset($this->_groupBy[$group]))
- $this->_groupBy[$group] = new TResultMapGroupBy($group, $resultObject);
- return $group;
+ return $resultMap->getID().':'.$row[$groupBy];
}
else
{
@@ -788,10 +796,20 @@ class TMappedStatement extends TComponent implements IMappedStatement
}
else if(!is_null($nested))
{
- $obj = $nested->createInstanceOfResult();
- if($this->fillPropertyWithResultMap($nested, $row, $obj) == false)
- $obj = null;
- TPropertyAccess::set($resultObject, $key, $obj);
+ if($property->isListType($resultObject) || $property->isArrayType($resultObject))
+ {
+ if(strlen($resultMap->getGroupBy()) <= 0)
+ throw new TSqlMapExecutionException(
+ 'sqlmap_non_groupby_array_list_type', $resultMap->getID(),
+ get_class($resultObject), $key);
+ }
+ else
+ {
+ $obj = $nested->createInstanceOfResult();
+ if($this->fillPropertyWithResultMap($nested, $row, $obj) == false)
+ $obj = null;
+ TPropertyAccess::set($resultObject, $key, $obj);
+ }
}
else //'select' ResultProperty
{
@@ -911,39 +929,140 @@ class TPostSelectBinding
class TResultMapGroupBy
{
- private $_ID='';
private $_object='';
- private $_values = array();
+ private $_property='';
- public function __construct($id, $object)
+ public function __construct($property, $object)
{
- $this->setID($id);
- $this->setObject($object);
+ $this->_property = $property;
+ $this->_object = $object;
}
-
- public function getID(){ return $this->_ID; }
- public function setID($value){ $this->_ID = $value; }
-
- public function getObject(){ return $this->_object; }
- public function setObject($value){ $this->_object = $value; }
-
- public function addValue($property, $value)
+
+ public function getObject()
{
- $this->_values[$property][] = $value;
+ return $this->_object;
}
-
- public function getProperties()
+
+ public function getProperty()
{
- return array_keys($this->_values);
+ return $this->_property;
}
+}
- public function updateProperties()
+class TSQLMapGroupByTree
+{
+ private $_tree = array();
+
+ private $_entries = array();
+
+ private $_list = array();
+
+ public function isEmpty()
+ {
+ return count($this->_entries) == 0;
+ }
+
+ public function add($parent, $node, $object='')
+ {
+ if(isset($this->_entries[$parent]) && isset($this->_entries[$node]))
+ return;
+ $this->_entries[$node] = $object;
+ if(empty($parent))
+ {
+ if(isset($this->_entries[$node]))
+ return;
+ $this->_tree[$node] = array();
+ }
+ $found = $this->addNode($this->_tree, $parent, $node);
+ if(!$found && !empty($parent))
+ {
+ $this->_tree[$parent] = array();
+ $this->_entries[$parent] = $object;
+ $this->addNode($this->_tree, $parent, $node);
+ }
+ }
+
+ protected function addNode(&$childs, $parent, $node)
+ {
+ $found = false;
+ reset($childs);
+ for($i = 0, $k = count($childs); $i < $k; $i++)
+ {
+ $key = key($childs);
+ next($childs);
+ if($key == $parent)
+ {
+ $found = true;
+ $childs[$key][$node] = array();
+ }
+ else
+ {
+ $found = $found || $this->addNode($childs[$key], $parent, $node);
+ }
+ }
+ return $found;
+ }
+
+ public function collect()
{
- foreach($this->_values as $property => $value)
+ while(count($this->_tree) > 0)
+ $this->findAndCollectChilds(null, $this->_tree);
+ return $this->getList();
+ }
+
+ protected function isChild(&$nodes)
+ {
+ $isChild = true;
+ foreach($nodes as $node)
{
- TPropertyAccess::set($this->getObject(), $property, $value);
+ if(count($node) != 0)
+ {
+ $isChild = false;
+ break;
+ }
}
- return $this->getObject();
+ return $isChild;
+ }
+
+ protected function findAndCollectChilds($parent, &$nodes)
+ {
+ $isChild = $this->isChild($nodes);
+ reset($nodes);
+
+ $childs = array();
+ for($i = 0, $k = count($nodes); $i < $k; $i++)
+ {
+ $key = key($nodes);
+ next($nodes);
+ if($isChild)
+ {
+ $childs[] = $key;
+ unset($nodes[$key]);
+ }
+ else
+ $this->findAndCollectChilds($key, $nodes[$key]);
+ }
+ if(count($childs) > 0)
+ $this->onChildNodesVisited($parent, $childs);
+ }
+
+ protected function onChildNodesVisited($parent, $nodes)
+ {
+ if(empty($parent))
+ return;
+ $parentObject = $this->_entries[$parent]->getObject();
+ foreach($nodes as $node)
+ {
+ $property= $this->_entries[$node]->getProperty();
+ $parentObject->{$property}[] = $this->_entries[$node]->getObject();
+ }
+ if($this->_entries[$parent]->getProperty() === null)
+ $this->_list[] = $parentObject;
+ }
+
+ public function getList()
+ {
+ return $this->_list;
}
}