private function mysqlQueryInner($tableName, $inverted) { $constraints = new JsonStoreSearchAnd(); $schema = clone $this->schema; $typeArray = NULL; if (isset($schema->type)) { $typeArray = $schema->type; unset($schema->type); if (!is_array($typeArray)) { $typeArray = array($typeArray); } else { if (in_array('integer', $typeArray) && in_array('number', $typeArray)) { array_splice($typeArray, array_search('integer', $typeArray), 1); } } } // Go through known keywords, removing them after processing if (isset($schema->anyOf)) { $constraints->add(new JsonStoreSearchAnyOf($this->config, $schema->anyOf, $this->path)); unset($schema->anyOf); } if (isset($schema->items) || isset($schema->maxItems) || isset($schema->minItems)) { $arrayConstraints = new JsonStoreSearchAnd(); if (isset($typeArray)) { $objIndex = array_search("array", $typeArray); if ($objIndex !== FALSE) { // TODO: does this work if the item schemas just contain "not", and the properties are not defined? $typeArray[$objIndex] = $arrayConstraints; $arrayConstraints->add(new JsonStoreSearchType($this->config, array("array"), $this->path)); } } else { $or = new JsonStoreSearchOr(); $or->add($arrayConstraints); if (!isset($this->config['columns']['array' . $this->path]['parentColumn'])) { $or->add(new JsonStoreSearchNot(new JsonStoreSearchType($this->config, array("array"), $this->path))); } $constraints->add($or); } if (isset($schema->items) && !is_array($schema->items)) { $arrayConstraints->add(new JsonStoreSearchItems($this->config, $schema->items, $this->path)); unset($schema->items); } if (isset($schema->maxItems) || isset($schema->minItems)) { $arrayConstraints->add(new JsonStoreSearchItemLimits($this->config, array("minItems" => isset($schema->minItems) ? $schema->minItems : NULL, "maxItems" => isset($schema->maxItems) ? $schema->maxItems : NULL), $this->path)); unset($schema->minItems); unset($schema->maxItems); } } else { if (isset($schema->not) && isset($schema->not->items)) { // We can *splice* } } if (isset($schema->properties)) { $propertyConstraints = new JsonStoreSearchAnd(); if (isset($typeArray)) { $objIndex = array_search("object", $typeArray); if ($objIndex !== FALSE) { // TODO: does this work if the property schemas just contain "not", and the properties are not defined? $typeArray[$objIndex] = $propertyConstraints; } } else { $or = new JsonStoreSearchOr(); $or->add($propertyConstraints); $or->add(new JsonStoreSearchNot(new JsonStoreSearchType($this->config, array("object"), $this->path))); $constraints->add($or); } foreach ($schema->properties as $propertyName => $subSchema) { $path = $this->path . JsonStore::joinJsonPointer(array($propertyName)); $propertyConstraints->add(new JsonStoreSearch($this->config, $subSchema, $path)); } unset($schema->properties); } if (isset($schema->pattern)) { $stringConstraints = new JsonStoreSearchAnd(); if (isset($typeArray)) { $stringIndex = array_search("string", $typeArray); if ($stringIndex !== FALSE) { // The string constraints will also constitute a type-check $typeArray[$stringIndex] = $stringConstraints; } } else { $or = new JsonStoreSearchOr(); $or->add($stringConstraints); $or->add(new JsonStoreSearchNot(new JsonStoreSearchType($this->config, array("string"), $this->path))); $constraints->add($or); } if (isset($schema->pattern)) { $stringConstraints->add(new JsonStoreSearchPattern($this->config, $schema->pattern, $this->path)); unset($schema->pattern); } } if (isset($schema->minimum) || isset($schema->maximum)) { $numberConstraints = new JsonStoreSearchAnd(); $numberType = "number"; if (isset($typeArray)) { $numberIndex = array_search("number", $typeArray); if ($numberIndex === FALSE) { $numberType = "integer"; $numberIndex = array_search("integer", $typeArray); } if ($numberIndex !== FALSE) { // The numerical constraints will also constitute a type-check $typeArray[$numberIndex] = $numberConstraints; } } else { $or = new JsonStoreSearchOr(); $or->add($numberConstraints); $or->add(new JsonStoreSearchNot(new JsonStoreSearchType($this->config, array("number"), $this->path))); $constraints->add($or); } if (isset($schema->minimum)) { $exclusive = isset($schema->exclusiveMinimum) ? $schema->exclusiveMinimum : FALSE; $numberConstraints->add(new JsonStoreSearchMinimum($this->config, $schema->minimum, $exclusive, $numberType, $this->path)); } if (isset($schema->maximum)) { $exclusive = isset($schema->exclusiveMaximum) ? $schema->exclusiveMaximum : FALSE; $numberConstraints->add(new JsonStoreSearchMaximum($this->config, $schema->maximum, $exclusive, $numberType, $this->path)); } unset($schema->minimum); unset($schema->exclusiveMinimum); unset($schema->maximum); unset($schema->exclusiveMaximum); } if (isset($typeArray)) { $constraints->add(new JsonStoreSearchType($this->config, $typeArray, $this->path)); } if (isset($schema->enum)) { $constraints->add(new JsonStoreSearchEnum($this->config, $schema->enum, $this->path)); unset($schema->enum); } if (isset($schema->not)) { $constraints->add(new JsonStoreSearchNot(new JsonStoreSearch($this->config, $schema->not, $this->path))); unset($schema->not); } $unknownKeywords = array_keys(get_object_vars($schema)); $prefix = count($unknownKeywords) ? "/* " . JsonStoreSearch::$INCOMPLETE_TAG . ": Unknown schema keywords: " . implode(", ", $unknownKeywords) . " */ " : ""; if ($inverted) { return $prefix . $constraints->mysqlQueryNot($tableName); } else { return $prefix . $constraints->mysqlQuery($tableName); } }