/** * Make where part of a SQL select to get children values * @param epDbObject $db the db connection * @param epObject $o the child object for query * @param int $depth how many children down we are * @param string $parent the parent of this child * @return array('from', 'where') * @author Oak Nauhygon <*****@*****.**> * @author Trevan Richins <*****@*****.**> */ public static function sqlSelectChildren($db, $o, $depth, $parent) { // array to keep new tables in 'from' $from = array(); // array to keep new expression in 'where' $where = array(); // get the class map for the child object $cm = $o->epGetClassMap(); // get all vars in the object $vars = $o->epGetVars(); // if object has oid, select use oid if ($oid = $o->epGetObjectId()) { $where[] = $db->quoteId($cm->getOidColumn()) . ' = ' . $oid; return array('from' => $from, 'where' => $where); } // mark child object under search (to avoid loops) $o->epSetSearching(true); // total number of vars (primitive or non-primitive) collected $n = 0; // new depth $depth++; // number of non-primitive (relationship) fields collected $nprim_id = 0; // loop through vars while (list($var, $val) = each($vars)) { // get field map if (!($fm =& $cm->getField($var))) { // should not happen continue; } // exclude null values (including empty strings) if (is_null($val) || !$val && $fm->getType() == epFieldMap::DT_CHAR) { continue; } // is it a primitive var? if ($fm->isPrimitive()) { $where[] = $db->quoteId($parent) . '.' . $db->quoteId($fm->getColumnName()) . ' = ' . $db->quote($val, $fm); // done for this var $n++; continue; } // okay we are dealing with a non-primitive (relationship) var if ($val instanceof epArray) { foreach ($val as $obj) { // skip object that is under searching if (!$obj || $obj->epIsSearching()) { continue; } // get 'where' and 'from' from relationship $from_where = epObj2Sql::sqlSelectRelations($db, $fm, $cm, $obj->epGetClassMap()->getTable(), $depth . $nprim_id, $parent); $where = array_merge($where, $from_where['where']); $from = array_merge($from, $from_where['from']); // get 'where' and 'from' from relationship $from_where = epObj2Sql::sqlSelectChildren($db, $obj, $depth, '_' . $depth . $nprim_id); $where = array_merge($where, $from_where['where']); $from = array_merge($from, $from_where['from']); $nprim_id++; } } else { if ($val instanceof epObject && !$val->epIsSearching()) { // get 'where' and 'from' from relationship $from_where = epObj2Sql::sqlSelectRelations($db, $fm, $cm, $val->epGetClassMap()->getTable(), $depth . $nprim_id, $parent); $where = array_merge($where, $from_where['where']); $from = array_merge($from, $from_where['from']); // get 'where' and 'from' from relationship $from_where = epObj2Sql::sqlSelectChildren($db, $val, $depth, '_' . $depth . $nprim_id); $where = array_merge($where, $from_where['where']); $from = array_merge($from, $from_where['from']); $nprim_id++; } } $n++; } // reset search flag on child object $o->epSetSearching(false); return array('from' => $from, 'where' => $where); }
/** * Builds SQL statement from an object * @param epObject &$o the object * @param epFieldMap &$fm the field map of the var that the object is assigned to * @param string $alias * @return array */ protected function _buildSqlObject(epObject &$o, epFieldMap &$fm, $alias = self::DUMMY_ALIAS) { $o->epSetSearching(true); // get class map $cm = $this->em->getClassMap($fm->getClass()); // for a committed object, simply use OID if ($oid = $o->epGetObjectId()) { $sql = $this->qid($alias) . '.' . $this->qid($cm->getOidColumn()); $sql .= '=' . $this->q($oid); return array($sql); } // arrays to keep expressions for primitve and relationship vars $exprs_prm = array(''); $exprs_rel = array(''); // go through each var foreach ($o as $var => $val) { // get field map for var if (!($fm = $cm->getField($var))) { continue; } // primitive var if ($fm->isPrimitive() && !is_null($val)) { $expr = $this->qid($alias) . '.' . $this->qid($fm->getColumnName()); $expr .= '=' . $this->q($val, $fm); $exprs_prm[] = $expr; continue; } // relationship var if (!$val) { // done if empty value or has been visited continue; } // is it a many-valued var? $vals = $val; if (!$fm->isMany()) { // arrayize it if not an array $vals = array($val); } // go through each value in array foreach ($vals as $val) { // build sql for the relationship field map $exprs_rf = $this->_buildSqlFieldMapRelationship($fm, $alias); // is it an error message? if (is_string($exprs_rf)) { throw new epExceptionQueryBuilder($this->_e($exprs)); continue; } // concat sql for field map ($exprs_rf) and sql for var value ($exprs_rv) foreach ($exprs_rf as $alias_ => $expr_rf) { // recursion: build sql for the relationship var $exprs_rv = $this->_buildSqlObject($val, $fm, $alias_); // collect expression for relationship var foreach ($exprs_rv as $expr_rv) { $exprs_rel[] = $expr_rf . ' AND ' . $expr_rv; } } } } // array to hold final results $exprs_obj = array(); // concat sql for primitive and relationship fields foreach ($exprs_rel as $expr_rel) { foreach ($exprs_prm as $expr_prm) { if (!$expr_rel && $expr_prm) { $exprs_obj[] = $expr_prm; } else { if ($expr_rel && !$expr_prm) { $exprs_obj[] = $expr_rel; } else { if ($expr_rel && $expr_prm) { $exprs_obj[] = $expr_rel . ' AND ' . $expr_prm; } } } } } $o->epSetSearching(false); return $exprs_obj; }