29 const OPT_SKIP_THESE =
'skipThese';
30 const OPT_ITEM_FILTER =
'ut.filter';
31 const OPT_GROUP_ID =
'groupId';
32 const OPT_REALPARENT =
'realParent';
33 const OPT_RANGE =
'lft,rgt';
34 const OPT_EXT =
'ext';
35 const OPT_HEAD =
'head';
36 const OPT_AGENT_SET =
'agentArray';
37 const OPT_SCAN_REF =
'scanRef';
38 const OPT_CONCLUDE_REF =
'conRef';
39 const OPT_SKIP_ALREADY_CLEARED =
'alreadyCleared';
42 private $uploadTreeTableName;
46 private $params = array();
53 public function __construct($uploadId, $options, $uploadTreeTableName, $uploadTreeViewName=null)
55 $this->uploadId = $uploadId;
56 $this->uploadTreeTableName = $uploadTreeTableName;
57 $dbViewName = $uploadTreeViewName ?:
'UploadTreeView'.(isset($this->dbViewName) ?:
'');
59 parent::__construct($dbViewQuery, $dbViewName);
67 return $this->uploadTreeTableName;
77 if (empty($options)) {
78 return self::getDefaultUploadTreeView($this->uploadId, $uploadTreeTableName);
82 $this->dbViewName =
'';
84 if (array_key_exists(self::OPT_REALPARENT, $options)) {
85 $filter .=
" AND ut.ufile_mode & (1<<28) = 0 AND ut.realparent=".$this->addParamAndGetExpr(
'realParent',$options[self::OPT_REALPARENT]);
86 $this->dbViewName .=
"_".self::OPT_REALPARENT;
87 } elseif (array_key_exists(self::OPT_RANGE,$options)) {
88 $itemBounds = $options[self::OPT_RANGE];
89 $filter .=
" AND ut.ufile_mode & (3<<28) = 0 AND (ut.lft BETWEEN ".$this->addParamAndGetExpr(
'lft',$itemBounds->getLeft()).
90 " AND ".$this->addParamAndGetExpr(
'rgt',$itemBounds->getRight()).
")";
91 $this->dbViewName .=
"_".self::OPT_RANGE;
94 if (array_key_exists(self::OPT_EXT, $options)) {
95 $filter .=
" AND ufile_name ILIKE ".$this->addParamAndGetExpr(
'patternExt',
'%.'.$options[self::OPT_EXT]);
96 $this->dbViewName .=
"_".self::OPT_EXT;
99 if (array_key_exists(self::OPT_HEAD, $options)) {
100 $filter .=
" AND ufile_name ILIKE ".$this->addParamAndGetExpr(
'patternHead',$options[self::OPT_HEAD].
'%');
101 $this->dbViewName .=
"_".self::OPT_HEAD;
104 if (array_key_exists(self::OPT_SCAN_REF,$options)) {
105 $filter .= $this->addScanFilter($options);
108 if (array_key_exists(self::OPT_CONCLUDE_REF, $options) && array_key_exists(self::OPT_GROUP_ID, $options)) {
109 $filter .= $this->addConFilter($options);
112 if (array_key_exists(self::OPT_SKIP_ALREADY_CLEARED, $options) && array_key_exists(self::OPT_GROUP_ID, $options)
113 && array_key_exists(self::OPT_AGENT_SET, $options)) {
114 $agentIdSet =
'{' . implode(
',', array_values($options[self::OPT_AGENT_SET])) .
'}';
115 $agentFilter =
" AND agent_fk=ANY(".$this->addParamAndGetExpr(
'agentIdSet', $agentIdSet).
")";
116 $this->dbViewName .=
"_".self::OPT_SKIP_ALREADY_CLEARED;
117 $groupAlias = $this->addParamAndGetExpr(
'groupId', $options[self::OPT_GROUP_ID]);
118 if (array_key_exists(self::OPT_RANGE, $options)) {
119 $filter .=
' AND '.self::getQueryCondition(self::OPT_SKIP_ALREADY_CLEARED, $groupAlias, $agentFilter);
120 } elseif (array_key_exists(self::OPT_SKIP_ALREADY_CLEARED, $options) && array_key_exists(self::OPT_GROUP_ID, $options)
121 && array_key_exists(self::OPT_AGENT_SET, $options) && array_key_exists(self::OPT_REALPARENT, $options)) {
122 $childFilter = self::getQueryCondition(self::OPT_SKIP_ALREADY_CLEARED, $groupAlias, $agentFilter);
123 $filter .=
' AND EXISTS(SELECT * FROM '.$this->uploadTreeTableName.
' utc WHERE utc.upload_fk='.$this->uploadId
124 .
' AND (utc.lft BETWEEN ut.lft AND ut.rgt) AND utc.ufile_mode&(3<<28)=0 AND ' 125 .preg_replace(
'/([a-z])ut\./',
'\1utc.', $childFilter).
')';
129 if (array_key_exists(self::OPT_ITEM_FILTER, $options)) {
130 $filter .=
' '.$options[self::OPT_ITEM_FILTER];
131 $this->dbViewName .=
"_".md5($options[self::OPT_ITEM_FILTER]);
133 $options[self::OPT_ITEM_FILTER] = $filter;
134 return self::getUploadTreeView($this->uploadId, $options, $uploadTreeTableName);
137 private function addConFilter($options)
140 if (array_key_exists(self::OPT_REALPARENT, $options)) {
141 $filter .=
" AND EXISTS(SELECT * FROM ".$this->uploadTreeTableName.
" usub" 142 .
" WHERE (usub.lft BETWEEN ut.lft AND ut.rgt) AND upload_fk=".$this->uploadId
143 .
" AND ".$this->subqueryConcludeRefMatches(
'usub', $options) .
")";
144 $this->dbViewName .=
"_".self::OPT_CONCLUDE_REF;
145 } elseif (array_key_exists(self::OPT_RANGE, $options)) {
146 $filter.=
" AND ".$this->subqueryConcludeRefMatches(
'ut', $options);
147 $this->dbViewName .=
"_".self::OPT_CONCLUDE_REF;
152 private function addScanFilter($options)
154 $this->dbViewName .=
"_".self::OPT_SCAN_REF;
155 if (array_key_exists(self::OPT_AGENT_SET, $options)) {
156 $this->dbViewName .=
"_".self::OPT_AGENT_SET;
158 if (array_key_exists(self::OPT_REALPARENT, $options)) {
159 return " AND EXISTS(SELECT * FROM ".$this->uploadTreeTableName.
" usub, " 160 . $this->subqueryLicenseFileMatchWhere($options)
161 .
" usub.pfile_fk=license_file.pfile_fk" 162 .
" AND (usub.lft BETWEEN ut.lft AND ut.rgt) AND upload_fk=".$this->uploadId.
")";
164 if (array_key_exists(self::OPT_RANGE, $options)) {
165 return " AND EXISTS(SELECT * FROM " . $this->subqueryLicenseFileMatchWhere($options)
166 .
" ut.pfile_fk=license_file.pfile_fk)";
170 private function subqueryLicenseFileMatchWhere($options)
172 $filter =
" license_file LEFT JOIN license_map ON license_file.rf_fk=license_map.rf_fk" 173 .
" AND usage=".LicenseMap::CONCLUSION.
" WHERE";
174 if (array_key_exists(self::OPT_AGENT_SET, $options)) {
175 $agentIdSet =
'{' . implode(
',', array_values($options[self::OPT_AGENT_SET])) .
'}';
176 $filter .=
" agent_fk=ANY(".$this->addParamAndGetExpr(
'agentIdSet', $agentIdSet).
") AND";
178 $rfId = $this->addParamAndGetExpr(
'scanRef', $options[self::OPT_SCAN_REF]);
179 return $filter .
" (license_file.rf_fk=$rfId OR rf_parent=$rfId) AND ";
182 private function subqueryConcludeRefMatches($itemTable,$options)
184 return "NOT(SELECT (removed OR cd.decision_type=".DecisionTypes::IRRELEVANT.
") excluded" 185 .
" FROM clearing_decision cd, clearing_decision_event cde, clearing_event ce" 186 .
" WHERE ((cd.group_fk=".$this->addParamAndGetExpr(
'groupId', $options[self::OPT_GROUP_ID])
187 .
" AND cd.uploadtree_fk=$itemTable.uploadtree_pk)" 188 .
" OR (cd.scope=".DecisionScopes::REPO.
" AND cd.pfile_fk=$itemTable.pfile_fk))" 189 .
" AND clearing_decision_pk=clearing_decision_fk" 190 .
" AND clearing_event_fk=clearing_event_pk" 191 .
" AND rf_fk=".$this->addParamAndGetExpr(
'conId',$options[self::OPT_CONCLUDE_REF])
192 .
" AND cd.decision_type!=".DecisionTypes::WIP
193 .
" ORDER BY CASE cd.scope WHEN ".DecisionScopes::REPO.
" THEN 1 ELSE 0 END,cd.date_added DESC LIMIT 1)";
205 if (
'uploadtree' === $uploadTreeTableName ||
'uploadtree_a' == $uploadTreeTableName) {
206 $condition =
" WHERE ut.upload_fk=$uploadId $additionalCondition";
207 } elseif ($additionalCondition) {
208 $condition =
" WHERE 1=1 $additionalCondition";
210 $uploadTreeView =
"SELECT * FROM $uploadTreeTableName ut $condition";
211 return $uploadTreeView;
222 $additionalCondition = array_key_exists(self::OPT_ITEM_FILTER, $options) ? $options[self::OPT_ITEM_FILTER] :
'';
223 $skipThese = array_key_exists(self::OPT_SKIP_THESE,$options) ? $options[self::OPT_SKIP_THESE] :
'none';
224 $groupId = array_key_exists(self::OPT_GROUP_ID, $options) ? $options[self::OPT_GROUP_ID] : null;
225 $agentFilter = self::getAgentFilter($options, $uploadId);
227 switch ($skipThese) {
229 case self::OPT_SKIP_ALREADY_CLEARED:
233 $queryCondition = self::getQueryCondition($skipThese, $groupId, $agentFilter).
" ".$additionalCondition;
234 if (
'uploadtree' === $uploadTreeTableName ||
'uploadtree_a' == $uploadTreeTableName) {
235 $queryCondition =
"ut.upload_fk=$uploadId AND ($queryCondition)";
237 $uploadTreeView =
"SELECT * FROM $uploadTreeTableName ut WHERE $queryCondition";
242 $uploadTreeView = self::getDefaultUploadTreeView($uploadId, $uploadTreeTableName, $additionalCondition);
245 return $uploadTreeView;
248 private static function getAgentFilter($options,$uploadId=0)
250 if (!array_key_exists(self::OPT_SKIP_THESE, $options)) {
253 $skipThese = $options[self::OPT_SKIP_THESE];
254 if ($skipThese !=
"noLicense" && $skipThese != self::OPT_SKIP_ALREADY_CLEARED) {
258 if (array_key_exists(self::OPT_AGENT_SET, $options)) {
259 $agentIds =
'array[' . implode(
',',$options[self::OPT_AGENT_SET]) .
']';
260 $agentFilter =
" AND lf.agent_fk=ANY($agentIds)";
262 $scanJobProxy =
new ScanJobProxy($GLOBALS[
'container']->
get(
'dao.agent'),$uploadId);
263 $scanJobProxy->createAgentStatus(array_keys(AgentRef::AGENT_LIST));
264 $latestAgentIds = $scanJobProxy->getLatestSuccessfulAgentIds();
265 $agentFilter = $latestAgentIds ?
" AND lf.agent_fk=ANY(array[".implode(
',',$latestAgentIds).
"])" :
"AND 0=1";
276 $conditionQueryHasLicense =
"(EXISTS (SELECT 1 FROM license_ref lr INNER JOIN license_file lf" 277 .
" ON lf.rf_fk=lr.rf_pk WHERE rf_shortname NOT IN ('No_license_found', 'Void') AND lf.pfile_fk = ut.pfile_fk $agentFilter LIMIT 1) 278 OR EXISTS (SELECT 1 FROM clearing_decision AS cd WHERE cd.group_fk = $groupId AND ut.uploadtree_pk = cd.uploadtree_fk LIMIT 1))";
280 switch ($skipThese) {
282 return $conditionQueryHasLicense;
283 case self::OPT_SKIP_ALREADY_CLEARED:
285 SELECT decision_type, ROW_NUMBER() OVER ( 286 PARTITION BY pfile_fk ORDER BY clearing_decision_pk 289 SELECT * FROM clearing_decision cd 291 ut.uploadtree_pk = cd.uploadtree_fk AND cd.group_fk = $groupId 293 cd.pfile_fk = ut.pfile_fk AND cd.scope=".DecisionScopes::REPO.
" 295 ) AS filtered_clearing_decision ORDER BY rnum DESC LIMIT 1";
296 return " $conditionQueryHasLicense 297 AND NOT EXISTS (SELECT 1 FROM ($decisionQuery) as latest_decision WHERE latest_decision.decision_type IN (".DecisionTypes::IRRELEVANT.
",".DecisionTypes::IDENTIFIED.
",".DecisionTypes::DO_NOT_USE.
") )";
299 return "EXISTS (SELECT copyright_pk FROM copyright cp WHERE cp.pfile_fk=ut.pfile_fk and cp.hash is not null )";
301 return "EXISTS (SELECT ecc_pk FROM ecc cp WHERE cp.pfile_fk=ut.pfile_fk and cp.hash is not null )";
313 $dbManager = $GLOBALS[
'container']->get(
'db.manager');
314 $params = $this->params;
315 if (array_key_exists(
'uploadId', $params)) {
316 $uploadExpr =
'$'.(1+array_search(
'uploadId', array_keys($params)));
318 $params[] = $this->uploadId;
319 $uploadExpr =
'$'.count($params);
322 $parentExpr =
'$'.count($params);
324 $sql =
"SELECT count(*) cnt, u.uploadtree_pk, u.ufile_mode FROM ".$this->uploadTreeTableName.
" u, " 326 .
" AND v.lft BETWEEN u.lft and u.rgt and u.parent=$parentExpr GROUP BY u.uploadtree_pk, u.ufile_mode";
328 if (!$this->materialized) {
329 $sql = $this->
asCTE().
' '.$sql;
332 $dbManager->prepare($stmt,$sql);
333 $res = $dbManager->execute($stmt,$params);
335 $artifactContainers = array();
336 while ($row=$dbManager->fetchArray($res)) {
337 $children[$row[
'uploadtree_pk']] = $row[
'cnt'];
338 if (($row[
'ufile_mode'] & (3<<28)) == (3<<28)) {
339 $artifactContainers[] = $row[
'uploadtree_pk'];
342 $dbManager->freeResult($res);
343 foreach ($artifactContainers as $ac) {
345 $children[$utid] = $cnt;
357 $uploadExpr =
'$'.(count($this->params)+1);
358 $lftExpr =
'$'.(count($this->params)+2);
359 $rgtExpr =
'$'.(count($this->params)+3);
360 $dbManager = $GLOBALS[
'container']->get(
'db.manager');
361 $sql =
"SELECT u.uploadtree_pk FROM ".$this->getDbViewName().
" u " 362 .
"WHERE u.upload_fk=$uploadExpr AND (u.lft BETWEEN $lftExpr AND $rgtExpr) AND u.ufile_mode & (3<<28) = 0";
364 if (!$this->materialized) {
365 $sql = $this->
asCTE().
' '.$sql;
368 $dbManager->prepare($stmt,$sql);
369 $params = array_merge($this->params,
371 $res = $dbManager->execute($stmt,$params);
372 $descendants = array();
373 while ($row = $dbManager->fetchArray($res)) {
374 $descendants[$row[
'uploadtree_pk']] = 1;
376 $dbManager->freeResult($res);
386 $dbManager = $container->get(
'db.manager');
387 if ($this->materialized) {
388 $sql =
"SELECT count(*) FROM $this->dbViewName";
390 $sql =
"SELECT count(*) FROM ($this->dbViewQuery) $this->dbViewName";
392 $summary = $dbManager->getSingleRow($sql,$this->params,$this->dbViewName);
393 return $summary[
'count'];
396 private function addParamAndGetExpr($key,$value)
398 if (array_key_exists($key, $this->params)) {
399 return '$' . (1 + array_search($key, array_keys($this->params)));
402 $this->params[] = $value;
403 return '$'.count($this->params);
406 public function getParams()
408 return $this->params;
static getQueryCondition($skipThese, $groupId=null, $agentFilter='')
__construct($uploadId, $options, $uploadTreeTableName, $uploadTreeViewName=null)
createUploadTreeViewQuery($options, $uploadTreeTableName)
static getDefaultUploadTreeView($uploadId, $uploadTreeTableName, $additionalCondition='')
countMaskedNonArtifactChildren($parent)
count elements childrenwise (or grandchildrenwise if child is artifact)
getNonArtifactDescendants(ItemTreeBounds $itemTreeBounds)
asCTE()
Common Table Expressions.
static getUploadTreeView($uploadId, $options, $uploadTreeTableName)