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));
 }