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