浏览代码

Fix Tree Performance - Procesy, Zasoby

Piotr Labudda 11 年之前
父节点
当前提交
074f14ed38
共有 7 个文件被更改,包括 214 次插入46 次删除
  1. 1 1
      SE/VERSION
  2. 16 25
      SE/procesy/proces.php
  3. 14 0
      SE/procesy/zasob.php
  4. 29 7
      SE/procesy5.php
  5. 94 0
      SE/se-lib/DebugExecutionTime.php
  6. 24 0
      SE/se-lib/ProcesHelper.php
  7. 36 13
      SE/se-lib/Tree.php

+ 1 - 1
SE/VERSION

@@ -1 +1 @@
-3.9.9-17
+3.9.9-18

+ 16 - 25
SE/procesy/proces.php

@@ -1,6 +1,7 @@
 <?php
 <?php
 
 
 Lib::loadClass('ProcesHelper');
 Lib::loadClass('ProcesHelper');
+Lib::loadClass('DebugExecutionTime');
 
 
 /**
 /**
  * @param $_GET['EDIT'] - ID rekordu do edycji (inline)
  * @param $_GET['EDIT'] - ID rekordu do edycji (inline)
@@ -16,11 +17,17 @@ function task_CRM_PROCES() {
 	}
 	}
 	$tbl = 'CRM_PROCES';
 	$tbl = 'CRM_PROCES';
 
 
+	$DBG_TIME = ('1' == V::get('DBG_TIME', '', $_GET));
+	$dbgExecTime = new DebugExecutionTime();
+	if ($DBG_TIME) $dbgExecTime->activate();
+	$dbgExecTime->log('start');
+
 	$tbl_conf = Column::getInstance($tbl);
 	$tbl_conf = Column::getInstance($tbl);
 	if (!$tbl_conf) {
 	if (!$tbl_conf) {
 		echo'<p class="red">'."Brak konfiguracji dla ".$tbl."!".'</p>';
 		echo'<p class="red">'."Brak konfiguracji dla ".$tbl."!".'</p>';
 		return;
 		return;
 	}
 	}
+	$dbgExecTime->log('Column::getInstance');
 	$visible_cols = $tbl_conf->getVisibleFieldList();
 	$visible_cols = $tbl_conf->getVisibleFieldList();
 
 
 	// form decorators:
 	// form decorators:
@@ -144,9 +151,7 @@ $TREE = array();
 echo'<div id="tree"></div>';
 echo'<div id="tree"></div>';
 
 
 
 
-$DBG_TIME = 0;
-if($DBG_TIME) $time_arr = array();// [ [time, desc], [time, desc], ... ]
-if($DBG_TIME) $time_arr []= array(microtime(true), 'before Tree');
+	$dbgExecTime->log('show...');
 
 
 	if ($tree_procesy_filter->get_arg('filtr_view') == 'NOWY') {
 	if ($tree_procesy_filter->get_arg('filtr_view') == 'NOWY') {
 		$filter_last->show_filters();
 		$filter_last->show_filters();
@@ -181,6 +186,7 @@ if($DBG_TIME) $time_arr []= array(microtime(true), 'before Tree');
 		}
 		}
 
 
 		$tree = new Tree( $tbl );
 		$tree = new Tree( $tbl );
+		$tree->setProfiler($dbgExecTime);
 		$clbk = 'tree_callback__show_item_from_'.$tbl;
 		$clbk = 'tree_callback__show_item_from_'.$tbl;
 		$tree->set_param('show_item_callback', $clbk);
 		$tree->set_param('show_item_callback', $clbk);
 
 
@@ -217,10 +223,13 @@ if($DBG_TIME) $time_arr []= array(microtime(true), 'before Tree');
 		}
 		}
 		if ($tree_procesy_filter->get_arg('filtr_id') != 0) {
 		if ($tree_procesy_filter->get_arg('filtr_id') != 0) {
 			$tree->showSubTree( $tree_procesy_filter->get_arg('filtr_id') );
 			$tree->showSubTree( $tree_procesy_filter->get_arg('filtr_id') );
+			$dbgExecTime->log('done tree->showSubTree()');
 		} else if ($tree_procesy_filter->get_arg('filtr_search_id') > 0) {
 		} else if ($tree_procesy_filter->get_arg('filtr_search_id') > 0) {
 			$tree->showSearchNode( $tree_procesy_filter->get_arg('filtr_search_id') );
 			$tree->showSearchNode( $tree_procesy_filter->get_arg('filtr_search_id') );
+			$dbgExecTime->log('done tree->showSearchNode()');
 		} else {
 		} else {
 			$tree->show();
 			$tree->show();
+			$dbgExecTime->log('done tree->show()');
 		}
 		}
 	}
 	}
 	else {
 	else {
@@ -312,28 +321,10 @@ if($DBG_TIME) $time_arr []= array(microtime(true), 'before Tree');
 		echo'</pre>';
 		echo'</pre>';
 	}
 	}
 
 
-if($DBG_TIME) $time_arr []= array(microtime(true), 'after Tree...');
-if($DBG_TIME){
-	$time_arr []= array(microtime(true), 'end');
-	$last_time = 0;
-	echo'<table style="color:#e0e0e0; text-align:left;">';
-	foreach ($time_arr as $t) {
-		echo'<tr>';
-			echo'<td> </td>';
-			echo'<td> </td>';
-			echo'<td style="text-align:left;">'.number_format(($t[0] - $last_time), 6).'</td>';
-		echo'</tr>';
-		echo'<tr>';
-			echo'<td>'.$t[0].'</td>';
-			echo'<td>'.$t[1].'</td>';
-			echo'<td> </td>';
-		echo'</tr>';
-		$last_time = $t[0];
-	}//end foreach
-	echo'</table>';
-	//echo'<pre style="text-align:left;">';print_r($db);echo'</pre>';
-	//echo'<pre style="text-align:left;">';print_r($_SERVER);echo'</pre>';
-}
+	if($DBG_TIME){
+		$dbgExecTime->log('end');
+		$dbgExecTime->printDebug();
+	}
 
 
 }
 }
 
 

+ 14 - 0
SE/procesy/zasob.php

@@ -15,6 +15,11 @@ function task_CRM_LISTA_ZASOBOW() {
 	}
 	}
 	$tbl = 'CRM_LISTA_ZASOBOW';
 	$tbl = 'CRM_LISTA_ZASOBOW';
 
 
+	$DBG_TIME = ('1' == V::get('DBG_TIME', '', $_GET));
+	$dbgExecTime = new DebugExecutionTime();
+	if ($DBG_TIME) $dbgExecTime->activate();
+	$dbgExecTime->log('start');
+
 	//Column::init($tbl, true);// $tbl, force = true
 	//Column::init($tbl, true);// $tbl, force = true
 
 
 	$tbl_conf = Column::getInstance($tbl);
 	$tbl_conf = Column::getInstance($tbl);
@@ -22,6 +27,7 @@ function task_CRM_LISTA_ZASOBOW() {
 		echo'<p class="red">'."Brak konfiguracji dla ".$tbl."!".'</p>';
 		echo'<p class="red">'."Brak konfiguracji dla ".$tbl."!".'</p>';
 		return;
 		return;
 	}
 	}
+	$dbgExecTime->log('Column::getInstance');
 	$visible_cols = $tbl_conf->getVisibleFieldList();
 	$visible_cols = $tbl_conf->getVisibleFieldList();
 
 
 	// form decorators:
 	// form decorators:
@@ -428,6 +434,8 @@ echo'<br />';
 
 
 	echo'<div id="tree"></div>';
 	echo'<div id="tree"></div>';
 
 
+	$dbgExecTime->log('show...');
+
 	//if (isset($_SESSION['USER_PARAMS']['ZASOBY_TREE_TYPE_HTML']) && $_SESSION['USER_PARAMS']['ZASOBY_TREE_TYPE_HTML']) {
 	//if (isset($_SESSION['USER_PARAMS']['ZASOBY_TREE_TYPE_HTML']) && $_SESSION['USER_PARAMS']['ZASOBY_TREE_TYPE_HTML']) {
 	if ($tree_zasoby_filter->get_arg('filtr_view') == 'NOWY') {
 	if ($tree_zasoby_filter->get_arg('filtr_view') == 'NOWY') {
 		$filter_last->show_filters();
 		$filter_last->show_filters();
@@ -463,6 +471,7 @@ echo'<br />';
 		}
 		}
 
 
 		$tree = new Tree( $tbl );
 		$tree = new Tree( $tbl );
+		$tree->setProfiler($dbgExecTime);
 		$clbk = 'tree_callback__show_item_from_'.$tbl;
 		$clbk = 'tree_callback__show_item_from_'.$tbl;
 		$tree->set_param('show_item_callback', $clbk);
 		$tree->set_param('show_item_callback', $clbk);
 //TODO: add all filters from Filter - $tree_zasoby_filter
 //TODO: add all filters from Filter - $tree_zasoby_filter
@@ -589,6 +598,11 @@ echo'</pre>';
 
 
 	}
 	}
 
 
+	if($DBG_TIME){
+		$dbgExecTime->log('end');
+		$dbgExecTime->printDebug();
+	}
+
 }
 }
 
 
 
 

+ 29 - 7
SE/procesy5.php

@@ -2122,8 +2122,10 @@ function tree_callback__show_item_from_CRM_PROCES( &$r, &$tree ) {
 	$db = DB::getDB();
 	$db = DB::getDB();
 	$wsk = array();
 	$wsk = array();
 	Lib::loadClass('ProcesHelper');
 	Lib::loadClass('ProcesHelper');
+	$tree->log('show item - start');
 	if ($tree->get_param('rozwin_proces')) {
 	if ($tree->get_param('rozwin_proces')) {
 		$wsk = ProcesHelper::get_wskazniki($r->ID);
 		$wsk = ProcesHelper::get_wskazniki($r->ID);
+		$tree->log('show item -> get_wskazniki', array('get_wskazniki'));
 	}
 	}
 
 
 	$pytania = array();
 	$pytania = array();
@@ -2135,6 +2137,7 @@ function tree_callback__show_item_from_CRM_PROCES( &$r, &$tree ) {
 		$params = array();
 		$params = array();
 		$params['f_ID_PROCES'] = $r->ID;
 		$params['f_ID_PROCES'] = $r->ID;
 		$pytania = $dataSource->getItems($params);
 		$pytania = $dataSource->getItems($params);
+		$tree->log('show item -> fetch-pytania', array('fetch-pytania'));
 	}
 	}
 
 
 	$show_form = ($tree->get_param('show_form_at_item') == $r->ID);
 	$show_form = ($tree->get_param('show_form_at_item') == $r->ID);
@@ -2166,14 +2169,28 @@ function tree_callback__show_item_from_CRM_PROCES( &$r, &$tree ) {
 	echo App::link($out_id, array('task'=>"CRM_PROCES", 'filtr_id'=>$r->ID, '#'=>'TREE'.$r->ID), array('class'=>implode(' ', $cls)));
 	echo App::link($out_id, array('task'=>"CRM_PROCES", 'filtr_id'=>$r->ID, '#'=>'TREE'.$r->ID), array('class'=>implode(' ', $cls)));
 
 
 	//if($r->TYPE == 'PROCES_INIT')  {
 	//if($r->TYPE == 'PROCES_INIT')  {
-		 //todo do optymalizacji ze struktur
-		$sql="select ID from CRM_PROCES where IF_TRUE_GOTO='".$r->ID."' ";
-		//  $sql=" select 1+1 ";
-		$hh=DB::query($sql);
-		while($rr=DB::fetch($hh)) {
-		 echo App::link('&lt;'.$rr->ID.'&nbsp;', array('task'=>"PROCES_VIEW", 'id_proces'=>$rr->ID));   
+	$tree->log('show item -> fetch-IF_TRUE_GOTO start');
+	$gotoList = ProcesHelper::getGoToProces($r->ID);
+	foreach ($gotoList as $gotoId => $gotoFlag) {
+		$popupIcon = 'icon-chevron-left';
+		$popupLink = "procesy5.php?task=PROCES_VIEW&id_proces={$gotoId}";
+		$popupTitle = "GOTO";
+		$popupContent = "{$gotoId} {$gotoFlag} {$r->ID}";
+		$linkStyle = '';
+		if ('popover' == $linkStyle) {
+			?>
+				<a href="<?php echo $popupLink; ?>"><i class="<?php echo $popupIcon; ?> wsk-help popover-with-html">
+					<span class="popover-heading"><?php echo $popupTitle; ?></span>
+					<span class="popover-body"><?php echo $popupContent; ?></span>
+				</i><?php echo $gotoId; ?></a>
+			<?php
+		} else {
+			echo ' ';
+			echo App::link("&lt;{$gotoId}", array('task'=>'PROCES_VIEW', 'id_proces'=>$gotoId), array('title'=>$popupContent));
+			echo ' ';
 		}
 		}
-		
+	}
+	$tree->log('show item -> fetch-IF_TRUE_GOTO', array('fetch-IF_TRUE_GOTO'));
 	//}
 	//}
 
 
 	//echo App::link("&#9873;", array('task'=>"CRM_PROCES", 'filtr_id'=>$r->ID, '#'=>'TREE'.$r->ID), array('class'=>''));
 	//echo App::link("&#9873;", array('task'=>"CRM_PROCES", 'filtr_id'=>$r->ID, '#'=>'TREE'.$r->ID), array('class'=>''));
@@ -2242,7 +2259,9 @@ function tree_callback__show_item_from_CRM_PROCES( &$r, &$tree ) {
 		//if ($bold) echo "***";
 		//if ($bold) echo "***";
 
 
 	if ($r->IF_TRUE_GOTO > 0) {
 	if ($r->IF_TRUE_GOTO > 0) {
+		$tree->log('show item -> fetch-proces_flag - start');
 		$link_out = ProcesHelper::proces_flag($r->ID, $r->IF_TRUE_GOTO, $r->IF_TRUE_GOTO_FLAG);
 		$link_out = ProcesHelper::proces_flag($r->ID, $r->IF_TRUE_GOTO, $r->IF_TRUE_GOTO_FLAG);
+		$tree->log('show item -> fetch-proces_flag', array('fetch-proces_flag'));
 		echo App::link($link_out, "#TREE".$r->IF_TRUE_GOTO, array('onclick'=>"return scrollToProces('".$r->IF_TRUE_GOTO."');", 'title'=>$r->IF_TRUE_GOTO_FLAG." ".$r->IF_TRUE_GOTO, 'class'=>'btn-p5'));
 		echo App::link($link_out, "#TREE".$r->IF_TRUE_GOTO, array('onclick'=>"return scrollToProces('".$r->IF_TRUE_GOTO."');", 'title'=>$r->IF_TRUE_GOTO_FLAG." ".$r->IF_TRUE_GOTO, 'class'=>'btn-p5'));
 		echo "<a href=procesy5.php?task=PROCES_VIEW&id_proces=".$r->IF_TRUE_GOTO.">&gt;&gt;</a>";
 		echo "<a href=procesy5.php?task=PROCES_VIEW&id_proces=".$r->IF_TRUE_GOTO.">&gt;&gt;</a>";
 		if(empty($r->DESC)) {
 		if(empty($r->DESC)) {
@@ -2381,7 +2400,9 @@ function tree_callback__show_item_from_CRM_PROCES( &$r, &$tree ) {
 			$w_parents_out = '';
 			$w_parents_out = '';
 			$w_title_parents_out = '';
 			$w_title_parents_out = '';
 			if ($tree->get_param('rozwin_zasoby')) {
 			if ($tree->get_param('rozwin_zasoby')) {
+				$tree->log('show item -> fetch-get_all_parents - start');
 				$w->_parents = TreeHelper::get_all_parents( 'CRM_LISTA_ZASOBOW', $w->PARENT_ID );
 				$w->_parents = TreeHelper::get_all_parents( 'CRM_LISTA_ZASOBOW', $w->PARENT_ID );
+				$tree->log('show item -> fetch-get_all_parents', array('fetch-get_all_parents'));
 				$w_parents_out = array();
 				$w_parents_out = array();
 				foreach ($w->_parents as $w_p_id => $w_p) {
 				foreach ($w->_parents as $w_p_id => $w_p) {
 					$w_parents_out []= '[<b>'.$w_p->ID.'</b> '.$w_p->TYPE.' '.$w_p->DESC.']';
 					$w_parents_out []= '[<b>'.$w_p->ID.'</b> '.$w_p->TYPE.' '.$w_p->DESC.']';
@@ -2775,6 +2796,7 @@ echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;">zasoby_id
 	}
 	}
 
 
 	echo'</dl>'."\n";
 	echo'</dl>'."\n";
+	$tree->log('show item -> end');
 }
 }
 
 
 
 

+ 94 - 0
SE/se-lib/DebugExecutionTime.php

@@ -0,0 +1,94 @@
+<?php
+
+class DebugExecutionTime {
+
+	private $_log = array();
+	private $_logByGroups = array();
+	private $_isActive = false;
+	private $_lastTime = 0;
+
+	public function __construct() {
+		$this->_log = array();
+	}
+
+	public function activate() {
+		$this->_isActive = true;
+	}
+
+	public function log($msg, $groups = array()) {
+		if (!$this->_isActive) return;
+		$curTime = microtime(true);
+		$execTime = (!$this->_lastTime)? 0 : $curTime - $this->_lastTime;
+		$this->_lastTime = $curTime;
+
+		$this->_log[] = array($msg, $execTime);
+
+		foreach ($groups as $group) {
+			if (!array_key_exists($group, $this->_logByGroups)) $this->_logByGroups[$group] = 0;
+			$this->_logByGroups[$group] += $execTime;
+		}
+	}
+
+	public function printDebug() {
+		if (!$this->_isActive) return;
+		$sumExecTime = 0;
+		foreach ($this->_log as $log) $sumExecTime += $log[1];
+		?>
+		<table>
+			<tr>
+				<td style="vertical-align:top;">
+					<div style="max-height:300px;overflow:auto">
+		<table style="text-align:left;" border="1" cellspacing="0" cellpadding="1">
+			<thead>
+				<tr>
+					<th>msg</th>
+					<th>time</th>
+				</tr>
+			</thead>
+			<tfoot>
+				<th style="text-align:right">total:</th>
+				<th style="font-family:monospace;text-align:right;font-weight:bold;"><?php echo number_format($sumExecTime, 6); ?></th>
+			</tfoot>
+			<tbody>
+				<?php foreach ($this->_log as $log) : ?>
+					<tr>
+						<td><?php echo $log[0]; ?></td>
+						<td style="font-family:monospace;text-align:right;"><?php echo number_format($log[1], 6); ?></td>
+					</tr>
+				<?php endforeach; ?>
+			</tbody>
+		</table>
+					</div>
+				</td>
+				<td style="vertical-align:top;">
+
+		<?php if (!empty($this->_logByGroups)) : ?>
+		<table style="text-align:left;" border="1" cellspacing="0" cellpadding="1">
+			<thead>
+				<tr>
+					<th>group</th>
+					<th>time</th>
+					<th>time left</th>
+					<th>time %</th>
+				</tr>
+			</thead>
+			<tbody>
+				<?php foreach ($this->_logByGroups as $group => $execTime) : ?>
+					<tr>
+						<th><?php echo $group; ?></th>
+						<td style="font-family:monospace;text-align:right;"><?php echo number_format($execTime, 6); ?></td>
+						<td style="font-family:monospace;text-align:right;"><?php echo number_format($sumExecTime - $execTime, 6); ?></td>
+						<td style="font-family:monospace;text-align:right;"><?php echo (!$execTime)? 0 : round($execTime * 100 / $sumExecTime); ?>%</td>
+					</tr>
+				<?php endforeach; ?>
+			</tbody>
+		</table>
+		<?php endif; ?>
+
+				</td>
+			</tr>
+		</table>
+		<?php
+	}
+
+}

+ 24 - 0
SE/se-lib/ProcesHelper.php

@@ -394,6 +394,30 @@ echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;">wsk: ';pr
 		return $ret;
 		return $ret;
 	}
 	}
 
 
+	public static function getGoToProces($id) {
+		static $_cache;
+		if (!is_array($_cache)) {
+			$_cache = array();
+			$db = DB::getDB();
+			 //todo do optymalizacji ze struktur
+			$sql="select p.`ID`, p.`IF_TRUE_GOTO`, p.`IF_TRUE_GOTO_FLAG`
+				from `CRM_PROCES` as p
+				where p.`IF_TRUE_GOTO` > 0
+			";
+			$res = $db->query($sql);
+			while ($r = $db->fetch($res)) {
+				$_cache[$r->IF_TRUE_GOTO][$r->ID] = $r->IF_TRUE_GOTO_FLAG;
+			}
+		}
+
+		$gotoList = array();
+		if (array_key_exists($id, $_cache)) {
+			$gotoList = $_cache[$id];
+		}
+
+		return $gotoList;
+	}
+
 	public static function get_wskaznik( $wsk_id ) {
 	public static function get_wskaznik( $wsk_id ) {
 		$ret = array();
 		$ret = array();
 		$sql = "select
 		$sql = "select

+ 36 - 13
SE/se-lib/Tree.php

@@ -11,6 +11,7 @@ var $_limit;// limit nodes from DB
 var $_deep_limit;// limit nodes from DB
 var $_deep_limit;// limit nodes from DB
 var $_nodes_from_db;// how much nodes loaded from DB
 var $_nodes_from_db;// how much nodes loaded from DB
 var $_opened_nodes_to_save;// nodes forced to open, to save in cookie after show tree,subtree
 var $_opened_nodes_to_save;// nodes forced to open, to save in cookie after show tree,subtree
+	private $_profiler;
 
 
 
 
 function __construct( $table ) {
 function __construct( $table ) {
@@ -27,6 +28,16 @@ function __construct( $table ) {
 }
 }
 
 
 
 
+	public function setProfiler($profiler) {
+		$this->_profiler = $profiler;
+	}
+
+	public function log($msg, $groups = array()) {
+		if ($this->_profiler && method_exists($this->_profiler, 'log')) {
+			$this->_profiler->log($msg, $groups);
+		}
+	}
+
 function set_parent_id_col( $p_id_col ) {
 function set_parent_id_col( $p_id_col ) {
 	$this->_sql_parent_id_col = $p_id_col;
 	$this->_sql_parent_id_col = $p_id_col;
 }
 }
@@ -281,9 +292,13 @@ function show_rec( $parent_id = 0, $deep = 0 ) {
 	//	return;
 	//	return;
 	//}
 	//}
 
 
+	$this->log("show_rec({$parent_id}, {$deep}) start");
+
 	$list = $this->get_childrens($parent_id);
 	$list = $this->get_childrens($parent_id);
 	if (empty($list)) return;
 	if (empty($list)) return;
 
 
+	$this->log("show_rec({$parent_id}, {$deep}) -> get_childrens({$parent_id})", array('get_childrens'));
+
 	echo '<ul>'."\n";
 	echo '<ul>'."\n";
 	$list_total = count($list);
 	$list_total = count($list);
 	foreach ($list as $r) {
 	foreach ($list as $r) {
@@ -327,14 +342,17 @@ function show_rec( $parent_id = 0, $deep = 0 ) {
 					echo'<div class="btn-open'.$btn_open_cls_add.'" onclick="return '.$this->js_tree_hide_fun.'(this,'.$r->ID.');"></div>';
 					echo'<div class="btn-open'.$btn_open_cls_add.'" onclick="return '.$this->js_tree_hide_fun.'(this,'.$r->ID.');"></div>';
 				}
 				}
 			}
 			}
+			$this->log("show_rec({$parent_id}, {$deep}) -> show_item start");
 			$this->show_item($r);
 			$this->show_item($r);
+			$this->log("show_rec({$parent_id}, {$deep}) -> show_item end", array('show_item'));
 
 
 			if ($r->has_childrens) {
 			if ($r->has_childrens) {
 				$this->show_rec($r->ID, $deep + 1);
 				$this->show_rec($r->ID, $deep + 1);
 			}
 			}
 		echo '</li>'."\n";
 		echo '</li>'."\n";
-	}//end foreach
+	}
 	echo '</ul>'."\n";
 	echo '</ul>'."\n";
+	$this->log("show_rec({$parent_id}, {$deep}) end");
 }
 }
 
 
 
 
@@ -362,12 +380,6 @@ function &get_childrens( $parent_id ) {
 	$sql->select = array();
 	$sql->select = array();
 
 
 	$sql->select [] = "t.*";
 	$sql->select [] = "t.*";
-	// has_childrens
-	if ($this->_table == 'CRM_LISTA_ZASOBOW') {
-		$sql->select [] = "IF(t.`".$this->_sql_parent_id_col."`='".$parent_id."' and t2.`ID` is not null, 1, 0) as has_childrens";
-	} else {
-		$sql->select [] = "IF(t2.`ID` is not null, 1, 0) as has_childrens";
-	}
 
 
 	// PARENT_TYPE dla tabeli CRM_LISTA_ZASOBOW
 	// PARENT_TYPE dla tabeli CRM_LISTA_ZASOBOW
 	if ($this->_table == 'CRM_LISTA_ZASOBOW') {
 	if ($this->_table == 'CRM_LISTA_ZASOBOW') {
@@ -414,7 +426,6 @@ function &get_childrens( $parent_id ) {
 		}
 		}
 	}
 	}
 
 
-	$sql->select = implode("\n, ", $sql->select);
 	$sql->where = implode(" or ", $sql->filter);
 	$sql->where = implode(" or ", $sql->filter);
 	$sql->join_filter = implode(" or ", $sql->join_filter);
 	$sql->join_filter = implode(" or ", $sql->join_filter);
 
 
@@ -438,19 +449,31 @@ function &get_childrens( $parent_id ) {
 		$sql->order_by = "order by t.`ID` asc";
 		$sql->order_by = "order by t.`ID` asc";
 	}
 	}
 
 
+	// has_childrens
+	# IF((select 1 from `CRM_PROCES` as t2 where t2.`PARENT_ID` = t.`ID` limit 1) > 0, 1, 0) AS has_childrens
+	if ($this->_table == 'CRM_LISTA_ZASOBOW') {
+		//$sql->select [] = "IF(t.`".$this->_sql_parent_id_col."`='".$parent_id."' and t2.`ID` is not null, 1, 0) as has_childrens";
+		$sql->select[] = "IF((select 1 from `{$this->_table}` as t2 where {$sql->join_filter} limit 1) is not null, 1, 0) as has_childrens";
+	} else {
+		//$sql->select [] = "IF(t2.`ID` is not null, 1, 0) as has_childrens";
+		$sql->select[] = "IF((select 1 from `{$this->_table}` as t2 where {$sql->join_filter} limit 1) is not null, 1, 0) as has_childrens";
+	}
+
+	$db = DB::getDB();
+	$sql->select = implode("\n, ", $sql->select);
 	$sql = "select
 	$sql = "select
 			".$sql->select."
 			".$sql->select."
 		from `".$this->_table."` as t
 		from `".$this->_table."` as t
-			left join `".$this->_table."` as t2 on(".$sql->join_filter.")
+--			left join `".$this->_table."` as t2 on(".$sql->join_filter.")
 		where
 		where
 			".$sql->where."
 			".$sql->where."
-		group by t.`ID`
+--		group by t.`ID`
 		".$sql->order_by."
 		".$sql->order_by."
 	";
 	";
-
-	$res = DB::query( $sql );
+	if('123' == V::get('DBG_SQL', '', $_GET)){echo'<pre style="max-height:200px;overflow:auto;border:1px solid red;text-align:left;"> (' . __CLASS__ . '::' . __FUNCTION__ . ':' . __LINE__ . '): ';print_r($sql);echo'</pre>';}
+	$res = $db->query($sql);
 	$ile = 0;
 	$ile = 0;
-	while ($r = DB::fetch( $res )) {
+	while ($r = $db->fetch($res)) {
 		$ret[$r->ID] = $r;
 		$ret[$r->ID] = $r;
 		$ile++;
 		$ile++;
 	}
 	}