Framework  3.9
LeftOuterJoin Class Reference
+ Inheritance diagram for LeftOuterJoin:
+ Collaboration diagram for LeftOuterJoin:

Public Member Functions

 LeftOuterJoin ($tag="join")
 Create a new LeftOuterJoin object. More...
 
 generateQuery ($constraints="", $countOnly=false)
 
- Public Member Functions inherited from AbstractJoin
 add ($class)
 Adds a class to the join definition. More...
 
 setFilter ($class, $filter)
 Sets an InclusionFilter or ExclusionFilter on the specified class. More...
 
 constrain ($class, $constraint)
 Sets a query constraint on the given class. More...
 
 excludeKeyFromJoin ($class, $key)
 By default joins are generated following the "most restrictive search" principle. More...
 
 xref ($xref, $xrefFieldMaps=null)
 Adds a cross-reference class to the join definition. More...
 
 pseudo ($class, $items, $indexField)
 Registers a class and indexed array as a pseudo-join item. More...
 
 count ($constraints="", $countExpr=true)
 
 query ($constraints="", $page=-1, $size=-1)
 Performs a query against the database returning an array of JoinResult objects. More...
 
 iteratedQuery ($constraints="")
 Performs a query against the database returning an iterator of JoinResult objects. More...
 
 indexedQuery ($constraints="", $indexBy="")
 Performs a query against the database, returning an array of DataItem objects of the specified class, indexed by a particular field. More...
 
 groupedQuery ($constraints="", $indexBy="")
 Performs a query against the database, returning an array of arrays of DataItem objects of the specified class, grouped by a particular field. More...
 

Additional Inherited Members

- Public Attributes inherited from AbstractJoin
 $classes = array()
 The names of the DataItem classes being joined. More...
 
 $protos = array()
 Prototype instances of the DataItem classes being joined. More...
 
 $xrefs = array()
 Cross-reference classes (i.e. classes that are part of the join, but not the result) More...
 
 $xrefFieldMaps = array()
 Cross-reference field map (to support cross-referencing through fields with differing names) More...
 
 $aliases = array()
 Field aliases for output. More...
 
 $xrefAliases = array()
 Cross-reference table aliases. More...
 
 $constraints = array()
 Class-specific constraints add via the constrain() method. More...
 
 $unique = false
 true to output distinct rows only More...
 
 $tag = "join"
 XML tag name. More...
 
 $excludedKeys = array()
 
 $pseudos = array()
 Pseudo-join lookup tables. More...
 

Detailed Description

Definition at line 827 of file join.inc.

Member Function Documentation

◆ generateQuery()

LeftOuterJoin::generateQuery (   $constraints = "",
  $countOnly = false 
)

Reimplemented from AbstractJoin.

Definition at line 838 of file join.inc.

839  {
840  $tables = "";
841  $fields = "";
842  $alias = "";
843 
844  trace(print_r($this->constraints, true), 3);
845 
846  $tableConstraints = array();
847  $whereConstraints = array();
848 
849  for($i = 0; $i < count($this->classes); ++$i)
850  {
851  $class = $this->classes[$i];
852  $proto =& $this->protos[$class];
853 
854  $alias = "t$i";
855  $this->aliases[$proto->table] = $alias;
856 
857  if ($tables) $tables .= ", ";
858  $tables .= "{$proto->table} $alias";
859 
860  if (array_key_exists($class, $this->constraints))
861  {
862  $c = $this->constraints[$class];
863 
864  foreach($proto->getFields() as $field => $type)
865  {
866  $c = preg_replace("/([\s\‍(])(".$field.")\\b/", "$1t$i.$2", $c);
867  }
868 
869  $c = "(".preg_replace("/^\\s*(WHERE\\s+|AND\\s+|OR\\s+)/i", "", $c).")";
870 
871  if ($i == 0)
872  {
873  // Constraint on first (anchor) class goes into where clause
874  $this->whereConstraints[$class] = $c;
875  }
876  else
877  {
878  // Constraints on other classes go into join clauses
879  $this->tableConstraints[$class] = $c;
880  }
881  }
882 
883  $f = $proto->getFieldList($alias);
884  if ($fields && $f) $fields .=", ";
885  $fields .= $f;
886  }
887 
888  for($i = 0; $i < count($this->xrefs); ++$i)
889  {
890  $xref = $this->xrefs[$i];
891 
892  $alias = "x$i";
893  $this->xrefAliases[$xref->table] = $alias;
894 
895  if ($tables) $tables .= ", ";
896  $tables .= "{$xref->table} $alias";
897  }
898 
899  if ($this->unique) $fields = "DISTINCT $fields";
900 
901  $classConstraints = implode(" AND ", array_values($this->whereConstraints));
902 
903  if (strncmp($constraints, "WHERE", 5))
904  {
905  if ($classConstraints) $classConstraints = " AND ".$classConstraints;
906  $constraints = "WHERE 1=1 $classConstraints $constraints";
907  }
908  else
909  {
910  if ($classConstraints) $classConstraints = $classConstraints." AND ";
911  $constraints = preg_replace("/^\\s*WHERE/i", "WHERE $classConstraints", $constraints);
912  }
913 
914  $join = "";
915  $join = $this->protos[$this->classes[0]]->table . " t0";
916 
917  // Build Left Outer Join
918 
919  $joined = array();
920 
921  for($i = 0; $i < count($this->classes) - 1; ++$i)
922  {
923  $c = $this->classes[$i];
924  $p = $this->protos[$c];
925 
926 
927  for ($j = $i+1; $j < count($this->classes); ++$j)
928  {
929  $d = $this->classes[$j];
930  $q = $this->protos[$d];
931 
932 
933 
934  trace($p->primary_key." ".array_key_exists($p->primary_key, $q->getFields()), 5);
935  trace($q->primary_key." ".array_key_exists($q->primary_key, $p->getFields()), 5);
936 
937  if (array_key_exists($p->primary_key, $q->getFields()))
938  {
939  if ($this->excludedKeys[$d][$p->primary_key] ||
940  $this->excludedKeys[$c][$p->primary_key])
941  {
942  continue;
943  }
944 
945  //$join .= " AND t$i.{$p->primary_key}=t$j.{$p->primary_key}";
946  $idx = "{$j}-{$p->primary_key}";
947  if ($joined[$idx])
948  {
949  continue;
950  }
951 
952  if ($joined[$j])
953  {
954  $join .= " AND t$i.{$p->primary_key}=t$j.{$p->primary_key}";
955  }
956  else
957  {
958  $join .= " LEFT OUTER JOIN {$q->table} t$j ON t$i.{$p->primary_key}=t$j.{$p->primary_key}";
959  if ($this->tableConstraints[$d])
960  {
961  $join .= " AND ".$this->tableConstraints[$d];
962  }
963  }
964 
965  $joined[$j] = true;
966  $joined[$idx] = true;
967 
968  }
969  else if (array_key_exists($q->primary_key, $p->getFields()))
970  {
971  if ($this->excludedKeys[$d][$q->primary_key] ||
972  $this->excludedKeys[$c][$q->primary_key])
973  {
974  continue;
975  }
976 
977  $idx = "{$j}-{$q->primary_key}";
978  if ($joined[$idx])
979  {
980  continue;
981  }
982 
983  //$join .= " AND t$i.{$q->primary_key}=t$j.{$q->primary_key}";
984  if ($joined[$j])
985  {
986  $join .= " AND t$i.{$q->primary_key}=t$j.{$q->primary_key}";
987  }
988  else
989  {
990  $join .= " LEFT OUTER JOIN {$q->table} t$j ON t$i.{$q->primary_key}=t$j.{$q->primary_key}";
991  }
992 
993  $joined[$j] = true;
994  $joined[$idx] = true;
995  }
996 
997  }
998 
999  }
1000 
1001  // Alias main table fields
1002 
1003  for($i = 0; $i < count($this->classes); ++$i)
1004  {
1005  $c = $this->classes[$i];
1006  $p = $this->protos[$c];
1007  foreach($p->getFields() as $field => $type)
1008  {
1009  $constraints = preg_replace("/([\s\‍(])(".$field.")\\b/", "$1t$i.$2", $constraints);
1010  }
1011 
1012  foreach($p->calculatedFields as $field => $expr)
1013  {
1014  foreach($p->getFields() as $f => $type)
1015  {
1016  $expr = preg_replace("/([\s\‍(])(".$f.")\\b/", "$1t$i.$2", $expr);
1017  }
1018 
1019  $constraints = preg_replace("/([\s\‍(])(".$field.")\\b/", " $expr", $constraints);
1020  }
1021  }
1022 
1023  // Handle XRefs
1024 
1025  foreach($this->xrefs as $xref)
1026  {
1027  $map = $this->xrefFieldMaps[$xref->table];
1028 
1029  foreach($this->protos as $p)
1030  {
1031  $pk = $p->primary_key;
1032  $xk = ($map && array_key_exists($pk, $map)) ? $map[$pk] : $pk;
1033 
1034  if ($xref->hasField($xk))
1035  {
1036  $xa = $this->xrefAliases[$xref->table];
1037  $ta = $this->aliases[$p->table];
1038 
1039  $join .= " LEFT OUTER JOIN {$xref->table} $xa ON $xa.{$xk}=$ta.{$pk}";
1040  }
1041  }
1042  }
1043 
1044  $matches = array();
1045 
1046  $orderBy = "";
1047  if (preg_match("/^(.*?)(ORDER\\s+BY.*)/i", $constraints, $matches))
1048  {
1049  $constraints = $matches[1];
1050  $orderBy = $matches[2];
1051  }
1052  else if (preg_match("/^(.*?)(LIMIT.*)/i", $constraints, $matches))
1053  {
1054  $constraints = $matches[1];
1055  $orderBy = $matches[2];
1056  }
1057 
1058  if ($countOnly) $fields = (is_bool($countOnly)) ? "COUNT(1) as result" : "COUNT($countOnly) as result";
1059 
1060  $query = "SELECT $fields FROM $join $constraints $orderBy";
1061 
1062  trace("LeftOuterJoin::generateQuery() - $query", 3);
1063 
1064  return $query;
1065  }
$constraints
Class-specific constraints add via the constrain() method.
Definition: join.inc:242
count($constraints="", $countExpr=true)
Definition: join.inc:356
trace($msg, $lvl=3, $callStack=null)
Send output to the trace log.
Definition: functions.inc:1010

◆ LeftOuterJoin()

LeftOuterJoin::LeftOuterJoin (   $tag = "join")

Create a new LeftOuterJoin object.

Definition at line 833 of file join.inc.

834  {
835  $this->tag = $tag;
836  }
$tag
XML tag name.
Definition: join.inc:245

The documentation for this class was generated from the following file: