public function toSql($tableSql, EarthIT_DBC_Namer $dbObjectNamer, EarthIT_DBC_ParamsBuilder $params) { static $aliasNum; // More properly this would be done with a join, // but that requires cooperation from code outside this filter. // Let's see if we can make this work with sub-selects... $table = EarthIT_DBC_SQLExpressionUtil::tableExpression($this->targetRc, $dbObjectNamer); $subItemTableSql = "{" . $params->newParam('t', $table) . "}"; $subItemAlias = 'subitem' . ++$aliasNum; $subItemFilterSql = str_replace("\n", "\n\t", $this->targetFilter->toSql($subItemAlias, $dbObjectNamer, $params)); $originFieldNames = $this->reference->getOriginFieldNames(); $targetFieldNames = $this->reference->getTargetFieldNames(); $joinConditionSqls = array(); for ($i = 0; $i < count($targetFieldNames); ++$i) { $targetCol = $dbObjectNamer->getColumnName($this->targetRc, $this->targetRc->getField($targetFieldNames[$i])); $originCol = $dbObjectNamer->getColumnName($this->originRc, $this->originRc->getField($originFieldNames[$i])); $joinConditionSqls[] = "{$subItemAlias}.{" . $params->newParam('c', new EarthIT_DBC_SQLIdentifier($targetCol)) . "} = " . "{$tableSql}.{" . $params->newParam('c', new EarthIT_DBC_SQLIdentifier($originCol)) . "}"; } $joinConditionSql = implode(" AND ", $joinConditionSqls); return "(\n" . "\tSELECT COUNT(*)\n" . "\tFROM {$subItemTableSql} AS {$subItemAlias}\n" . "\tWHERE {$subItemFilterSql} AND {$joinConditionSql}\n" . ") > 0"; }
protected function _bulkInsertQueries(array $itemData, EarthIT_Schema_ResourceClass $rc, $returnSaved) { $storableFields = EarthIT_Storage_Util::storableFields($rc); $defaultItem = EarthIT_Storage_Util::defaultItem($rc); foreach ($itemData as &$item) { $item += $defaultItem; } unset($item); $fieldsToStore = self::ensureSameFieldsGivenForAllItems($itemData, $storableFields); $params = array(); $params['table'] = EarthIT_DBC_SQLExpressionUtil::tableExpression($rc, $this->dbObjectNamer); $paramCounter = 0; $columnNameParams = array(); $columnNamePlaceholders = array(); $toStoreColumnNamePlaceholders = array(); // Only the ones we're specifying in our insert foreach ($storableFields as $fn => $f) { $columnNameParam = "c_" . $paramCounter++; $columnNameParams[$fn] = $columnNameParam; $params[$columnNameParam] = new EarthIT_DBC_SQLIdentifier($this->dbObjectNamer->getColumnName($rc, $f)); $columnNamePlaceholder = "{{$columnNameParam}}"; $columnNamePlaceholders[$fn] = $columnNamePlaceholder; } foreach ($fieldsToStore as $fn => $f) { $columnNameParam = $columnNameParams[$fn]; $toStoreColumnNamePlaceholders[] = $columnNamePlaceholders[$fn]; } $columnDbExternalValueSqls = array(); if ($returnSaved) { foreach ($storableFields as $fn => $f) { $t = $this->dbInternalToExternalValueSql($f, $rc, $columnNamePlaceholders[$fn]); if ($t != $columnNamePlaceholders[$fn]) { $t .= " AS " . $columnNamePlaceholders[$fn]; } $columnDbExternalValueSqls[$fn] = $t; } } if (count($fieldsToStore) == 0) { if ($returnSaved) { throw new Exception("Returning saved records not supported for MySQL."); } // INSERT INTO ... DEFAULT VALUES doesn't seem to have a bulk form, // so we'll have to make multiple queries. // Fortunately they're pretty simple queries (actually just the same one repeated). return array_fill(0, count($itemData), new EarthIT_Storage_StorageQuery("INSERT INTO {table} DEFAULT VALUES", $params, $returnSaved)); } $valueRows = array(); foreach ($itemData as $item) { $valueSqls = array(); foreach ($fieldsToStore as $fn => $f) { $paramName = "v_" . $paramCounter++; $value = isset($item[$fn]) ? $item[$fn] : null; if ($value instanceof EarthIT_DBC_SQLQueryComponent) { $isAlreadyInternal = true; } else { if ($value instanceof EarthIT_Storage_InternalValue) { $isAlreadyInternal = true; $value = $value->getValue(); } else { $isAlreadyInternal = false; } } if ($isAlreadyInternal) { $valueSqls[] = "{{$paramName}}"; $params[$paramName] = $value; } else { $valueSqls[] = $this->dbExternalToInternalValueSql($f, $rc, "{{$paramName}}"); $params[$paramName] = $this->schemaToDbExternalValue($value, $f, $rc); } } $valueRows[] = "(" . implode(', ', $valueSqls) . ")"; } $sql = "INSERT INTO {table}\n" . "(" . implode(", ", $toStoreColumnNamePlaceholders) . ") VALUES\n" . implode(",\n", $valueRows); if ($returnSaved) { $sql .= "\nRETURNING " . implode(', ', $columnDbExternalValueSqls); } return array(new EarthIT_Storage_StorageQuery($sql, $params, $returnSaved)); }