'JSONB', Mode::SQLite => 'TEXT', default => throw new DocumentException('Database mode not set; cannot make create table statement') }; return "CREATE TABLE IF NOT EXISTS $name (data $dataType NOT NULL)"; } /** * Split a schema and table name * * @param string $tableName The name of the table, possibly including the schema * @return array|string[] An array with the schema at index 0 and the table name at index 1 */ private static function splitSchemaAndTable(string $tableName): array { $parts = explode('.', $tableName); return sizeof($parts) == 1 ? ["", $tableName] : [$parts[0], $parts[1]]; } /** * SQL statement to create an index on one or more fields in a JSON document * * @param string $tableName The name of the table which should be indexed * @param string $indexName The name of the index to create * @param array $fields An array of fields to be indexed; may contain direction (ex. 'salary DESC') * @return string The CREATE INDEX statement to ensure the index exists */ public static function ensureIndexOn(string $tableName, string $indexName, array $fields): string { [, $tbl] = self::splitSchemaAndTable($tableName); $jsonFields = implode(', ', array_map(function (string $field) { $parts = explode(' ', $field); $fieldName = sizeof($parts) == 1 ? $field : $parts[0]; $direction = sizeof($parts) < 2 ? "" : " $parts[1]"; return "(data->>'$fieldName')$direction"; }, $fields)); return "CREATE INDEX IF NOT EXISTS idx_{$tbl}_$indexName ON $tableName ($jsonFields)"; } /** * SQL statement to create a key index for a document table * * @param string $tableName The name of the table whose key should be ensured * @return string The CREATE INDEX statement to ensure the key index exists */ public static function ensureKey(string $tableName): string { return str_replace('INDEX', 'UNIQUE INDEX', self::ensureIndexOn($tableName, 'key', [Configuration::$idField])); } }