コード例 #1
0
 public function testcreateWithAutoCommit()
 {
     $this->connection->expects($this->once())->method('queryWithAutoCommit');
     $instance = new TemporaryTableBuilder($this->connection);
     $instance->WithAutoCommit(true);
     $instance->create('Foo');
 }
コード例 #2
0
 /**
  * @note we use two helper tables. One holds the results of each new iteration, one holds the
  * results of the previous iteration. One could of course do with only the above result table,
  * but then every iteration would use all elements of this table, while only the new ones
  * obtained in the previous step are relevant. So this is a performance measure.
  */
 private function buildTempTableFor($tablename, $values, $smwtable, $depth)
 {
     $db = $this->connection;
     $tmpnew = 'smw_new';
     $tmpres = 'smw_res';
     $this->temporaryTableBuilder->create($tmpnew);
     $this->temporaryTableBuilder->create($tmpres);
     // Adding multiple values for the same column in sqlite is not supported
     foreach (explode(',', $values) as $value) {
         $db->query("INSERT " . "IGNORE" . " INTO {$tablename} (id) VALUES {$value}", __METHOD__);
         $db->query("INSERT " . "IGNORE" . " INTO {$tmpnew} (id) VALUES {$value}", __METHOD__);
     }
     for ($i = 0; $i < $depth; $i++) {
         $db->query("INSERT " . 'IGNORE ' . "INTO {$tmpres} (id) SELECT s_id" . '@INT' . " FROM {$smwtable}, {$tmpnew} WHERE o_id=id", __METHOD__);
         if ($db->affectedRows() == 0) {
             // no change, exit loop
             break;
         }
         $db->query("INSERT " . 'IGNORE ' . "INTO {$tablename} (id) SELECT {$tmpres}.id FROM {$tmpres}", __METHOD__);
         if ($db->affectedRows() == 0) {
             // no change, exit loop
             break;
         }
         // empty "new" table
         $db->query('TRUNCATE TABLE ' . $tmpnew, __METHOD__);
         $tmpname = $tmpnew;
         $tmpnew = $tmpres;
         $tmpres = $tmpname;
     }
     $this->hierarchyCache[$values] = $tablename;
     $this->temporaryTableBuilder->drop($tmpnew);
     $this->temporaryTableBuilder->drop($tmpres);
 }
コード例 #3
0
 private function doResolveBySegment(QuerySegment &$query)
 {
     $db = $this->connection;
     switch ($query->type) {
         case QuerySegment::Q_TABLE:
             // Normal query with conjunctive subcondition.
             foreach ($query->components as $qid => $joinField) {
                 $subQuery = $this->querySegmentList[$qid];
                 $this->doResolveBySegment($subQuery);
                 if ($subQuery->joinTable !== '') {
                     // Join with jointable.joinfield
                     $query->from .= ' INNER JOIN ' . $db->tableName($subQuery->joinTable) . " AS {$subQuery->alias} ON {$joinField}=" . $subQuery->joinfield;
                 } elseif ($subQuery->joinfield !== '') {
                     // Require joinfield as "value" via WHERE.
                     $condition = '';
                     foreach ($subQuery->joinfield as $value) {
                         $condition .= ($condition ? ' OR ' : '') . "{$joinField}=" . $db->addQuotes($value);
                     }
                     if (count($subQuery->joinfield) > 1) {
                         $condition = "({$condition})";
                     }
                     $query->where .= ($query->where === '' ? '' : ' AND ') . $condition;
                 } else {
                     // interpret empty joinfields as impossible condition (empty result)
                     $query->joinfield = '';
                     // make whole query false
                     $query->joinTable = '';
                     $query->where = '';
                     $query->from = '';
                     break;
                 }
                 if ($subQuery->where !== '') {
                     $query->where .= ($query->where === '' ? '' : ' AND ') . '(' . $subQuery->where . ')';
                 }
                 $query->from .= $subQuery->from;
             }
             $query->components = array();
             break;
         case QuerySegment::Q_CONJUNCTION:
             reset($query->components);
             $key = false;
             // Pick one subquery as anchor point ...
             foreach ($query->components as $qkey => $qid) {
                 $key = $qkey;
                 if ($this->querySegmentList[$qkey]->joinTable !== '') {
                     break;
                 }
             }
             $result = $this->querySegmentList[$key];
             unset($query->components[$key]);
             // Execute it first (may change jointable and joinfield, e.g. when making temporary tables)
             $this->doResolveBySegment($result);
             // ... and append to this query the remaining queries.
             foreach ($query->components as $qid => $joinfield) {
                 $result->components[$qid] = $result->joinfield;
             }
             // Second execute, now incorporating remaining conditions.
             $this->doResolveBySegment($result);
             $query = $result;
             break;
         case QuerySegment::Q_DISJUNCTION:
             if ($this->queryMode !== Query::MODE_NONE) {
                 $this->temporaryTableBuilder->create($db->tableName($query->alias));
             }
             $this->executedQueries[$query->alias] = array();
             foreach ($query->components as $qid => $joinField) {
                 $subQuery = $this->querySegmentList[$qid];
                 $this->doResolveBySegment($subQuery);
                 $sql = '';
                 if ($subQuery->joinTable !== '') {
                     $sql = 'INSERT ' . 'IGNORE ' . 'INTO ' . $db->tableName($query->alias) . " SELECT DISTINCT {$subQuery->joinfield} FROM " . $db->tableName($subQuery->joinTable) . " AS {$subQuery->alias} {$subQuery->from}" . ($subQuery->where ? " WHERE {$subQuery->where}" : '');
                 } elseif ($subQuery->joinfield !== '') {
                     // NOTE: this works only for single "unconditional" values without further
                     // WHERE or FROM. The execution must take care of not creating any others.
                     $values = '';
                     // This produces an error on postgres with
                     // pg_query(): Query failed: ERROR:  duplicate key value violates
                     // unique constraint "sunittest_t3_pkey" DETAIL:  Key (id)=(274) already exists.
                     foreach ($subQuery->joinfield as $value) {
                         $values .= ($values ? ',' : '') . '(' . $db->addQuotes($value) . ')';
                     }
                     $sql = 'INSERT ' . 'IGNORE ' . 'INTO ' . $db->tableName($query->alias) . " (id) VALUES {$values}";
                 }
                 // else: // interpret empty joinfields as impossible condition (empty result), ignore
                 if ($sql) {
                     $this->executedQueries[$query->alias][] = $sql;
                     if ($this->queryMode !== Query::MODE_NONE) {
                         $db->query($sql, __METHOD__);
                     }
                 }
             }
             $query->type = QuerySegment::Q_TABLE;
             $query->where = '';
             $query->components = array();
             $query->joinTable = $query->alias;
             $query->joinfield = "{$query->alias}.id";
             $query->sortfields = array();
             // Make sure we got no sortfields.
             // TODO: currently this eliminates sortkeys, possibly keep them (needs different temp table format though, maybe not such a good thing to do)
             break;
         case QuerySegment::Q_PROP_HIERARCHY:
         case QuerySegment::Q_CLASS_HIERARCHY:
             // make a saturated hierarchy
             $this->resolveHierarchyForSegment($query);
             break;
         case QuerySegment::Q_VALUE:
             break;
             // nothing to do
     }
 }