Got most of #405 implemented on master

This commit is contained in:
Maurits van der Schee 2020-04-03 22:18:21 +02:00
commit 6ca92f12db
7 changed files with 173 additions and 96 deletions

View file

@ -22,9 +22,14 @@ class ColumnsBuilder
return '';
}
switch ($this->driver) {
case 'mysql':return " LIMIT $offset, $limit";
case 'pgsql':return " LIMIT $limit OFFSET $offset";
case 'sqlsrv':return " OFFSET $offset ROWS FETCH NEXT $limit ROWS ONLY";
case 'mysql':
return " LIMIT $offset, $limit";
case 'pgsql':
return " LIMIT $limit OFFSET $offset";
case 'sqlsrv':
return " OFFSET $offset ROWS FETCH NEXT $limit ROWS ONLY";
case 'sqlite':
return " LIMIT $limit OFFSET $offset";
}
}
@ -74,9 +79,14 @@ class ColumnsBuilder
$valuesSql = '(' . implode(',', $values) . ')';
$outputColumn = $this->quoteColumnName($table->getPk());
switch ($this->driver) {
case 'mysql':return "$columnsSql VALUES $valuesSql";
case 'pgsql':return "$columnsSql VALUES $valuesSql RETURNING $outputColumn";
case 'sqlsrv':return "$columnsSql OUTPUT INSERTED.$outputColumn VALUES $valuesSql";
case 'mysql':
return "$columnsSql VALUES $valuesSql";
case 'pgsql':
return "$columnsSql VALUES $valuesSql RETURNING $outputColumn";
case 'sqlsrv':
return "$columnsSql OUTPUT INSERTED.$outputColumn VALUES $valuesSql";
case 'sqlite':
return "$columnsSql VALUES $valuesSql";
}
}

View file

@ -27,10 +27,10 @@ class DataConverter
private function getRecordValueConversion(ReflectedColumn $column): string
{
if (in_array($this->driver, ['mysql', 'sqlsrv']) && $column->isBoolean()) {
if (in_array($this->driver, ['mysql', 'sqlsrv', 'sqlite']) && $column->isBoolean()) {
return 'boolean';
}
if ($this->driver == 'sqlsrv' && $column->getType() == 'bigint') {
if (in_array($this->driver, ['sqlsrv', 'sqlite']) && in_array($column->getType(), ['integer', 'bigint'])) {
return 'integer';
}
return 'none';

View file

@ -83,8 +83,7 @@ class GenericDB
\PDO::SQLSRV_ATTR_FETCHES_NUMERIC_TYPE => true,
];
case 'sqlite':
return $options + [
];
return $options + [];
}
}
@ -192,11 +191,17 @@ class GenericDB
case 'mysql':
$stmt = $this->query('SELECT LAST_INSERT_ID()', []);
break;
case 'sqlite':
$stmt = $this->query('SELECT LAST_INSERT_ROWID()', []);
break;
}
$pkValue = $stmt->fetchColumn(0);
if ($this->driver == 'sqlsrv' && $table->getPk()->getType() == 'bigint') {
return (int) $pkValue;
}
if ($this->driver == 'sqlite' && in_array($table->getPk()->getType(), ['integer', 'bigint'])) {
return (int) $pkValue;
}
return $pkValue;
}

View file

@ -23,50 +23,47 @@ class GenericReflection
private function createSqlLiteReflectionTables() /*: void */
{
$reflection = $this->query('SELECT "name" FROM "sqlite_master" WHERE "type" = \'table\' and name like \'sys/%\';',[]);
if (count($reflection->fetchAll())==0) {
//create reflection tables
$this->query('CREATE table "sys/version" ("version" integer);',[]);
$this->query('CREATE table "sys/tables" ("name" text, "type" text);',[]);
$this->query('CREATE table "sys/columns" ("self" text,"cid" integer,"name" text,"type" integer,"notnull" integer,"dflt_value" integer,"pk" integer);',[]);
$this->query('CREATE table "sys/foreign_keys" ("self" text,"id" integer,"seq" integer,"table" text,"from" text,"to" text,"on_update" text,"on_delete" text,"match" text);',[]);
}
$version = $this->query('pragma schema_version',[])->fetchColumn(0);
if ($version != $this->query('SELECT "version" from "sys/version";')->fetchColumn(0)) {
// reflection may take a while
set_time_limit(3600);
// update version data
$this->query('DELETE FROM "sys/version";');
$stmt = $this->pdo->prepare('INSERT into "sys/version" ("version") VALUES (?);');
$stmt->execute(array($version));
$reflection = $this->query('SELECT "name" FROM "sqlite_master" WHERE "type" = \'table\' and name like \'sys/%\';', []);
if (count($reflection) == 0) {
//create reflection tables
$this->query('CREATE table "sys/version" ("version" integer);', []);
$this->query('CREATE table "sys/tables" ("name" text, "type" text);', []);
$this->query('CREATE table "sys/columns" ("self" text,"cid" integer,"name" text,"type" integer,"notnull" integer,"dflt_value" integer,"pk" integer);', []);
$this->query('CREATE table "sys/foreign_keys" ("self" text,"id" integer,"seq" integer,"table" text,"from" text,"to" text,"on_update" text,"on_delete" text,"match" text);', []);
}
$version = $this->query('pragma schema_version;', [])[0]["schema_version"];
$current = $this->query('SELECT "version" from "sys/version";', []);
if (!$current || count($current) == 0 || !isset($current[0]["schema_version"]) || $version != $current[0]["schema_version"]) {
// reflection may take a while
set_time_limit(3600);
// update version data
$this->query('DELETE FROM "sys/version";', []);
$this->query('INSERT into "sys/version" ("version") VALUES (?);', [$version]);
// update tables data
$this->query('DELETE FROM "sys/tables";');
$result = $this->query('SELECT "name", "type" FROM sqlite_master WHERE ("type" = \'table\' or "type" = \'view\') and name not like "sys/%" and name<>"sqlite_sequence";');
$tables = array();
foreach($result as $row) {
$tables[] = $row['name'];
$stmt = $this->pdo->prepare('INSERT into "sys/tables" ("name", "type") VALUES (?, ?);');
$stmt->execute(array($row['name'], $row['type']));
}
// update columns and foreign_keys data
$this->query('DELETE FROM "sys/columns"');
$this->query('DELETE FROM "sys/foreign_keys"');
foreach ($tables as $table) {
$result = $this->query("pragma table_info(`$table`);");
foreach($result as $row) {
array_unshift($row, $table);
$stmt = $this->pdo->prepare('INSERT into "sys/columns" ("self","cid","name","type","notnull","dflt_value","pk") VALUES (?,?,?,?,?,?,?);');
$stmt->execute(array_values($row));
}
$result = $this->query("pragma foreign_key_list(`$table`);");
foreach($result as $row) {
array_unshift($row, $table);
$stmt = $this->pdo->prepare('INSERT into "sys/foreign_keys" ("self","id","seq","table","from","to","on_update","on_delete","match") VALUES (?,?,?,?,?,?,?,?,?);');
$stmt->execute(array_values($row));
}
}
}
// update tables data
$this->query('DELETE FROM "sys/tables";', []);
$result = $this->query('SELECT "name", "type" FROM sqlite_master WHERE ("type" = \'table\' or "type" = \'view\') and name not like "sys/%" and name<>"sqlite_sequence";', []);
$tables = array();
foreach ($result as $row) {
$tables[] = $row['name'];
$this->query('INSERT into "sys/tables" ("name", "type") VALUES (?, ?);', [$row['name'], $row['type']]);
}
// update columns and foreign_keys data
$this->query('DELETE FROM "sys/columns";', []);
$this->query('DELETE FROM "sys/foreign_keys";', []);
foreach ($tables as $table) {
$result = $this->query("pragma table_info(`$table`);", []);
foreach ($result as $row) {
array_unshift($row, $table);
$this->query('INSERT into "sys/columns" ("self","cid","name","type","notnull","dflt_value","pk") VALUES (?,?,?,?,?,?,?);', array_values($row));
}
$result = $this->query("pragma foreign_key_list(`$table`);", []);
foreach ($result as $row) {
array_unshift($row, $table);
$this->query('INSERT into "sys/foreign_keys" ("self","id","seq","table","from","to","on_update","on_delete","match") VALUES (?,?,?,?,?,?,?,?,?);', array_values($row));
}
}
}
}
public function getIgnoredTables(): array
@ -79,12 +76,10 @@ class GenericReflection
case 'sqlsrv':
return [];
case 'sqlite':
return ['sys/version','sys/tables','sys/columns','sys/foreign_keys'];
return ['sys/version', 'sys/tables', 'sys/columns', 'sys/foreign_keys'];
}
}
private function getTablesSQL(): string
{
switch ($this->driver) {
@ -96,7 +91,7 @@ class GenericReflection
return 'SELECT o.name as "TABLE_NAME", o.xtype as "TABLE_TYPE" FROM sysobjects o WHERE o.xtype IN (\'U\', \'V\') ORDER BY "TABLE_NAME"';
case 'sqlite':
$this->createSqlLiteReflectionTables();
return 'SELECT t.name as "TABLE_NAME", t.type as "TABLE_TYPE" FROM "sys/tables" t WHERE t.type IN (\'table\', \'view\') ORDER BY "TABLE_NAME"';
return 'SELECT t.name as "TABLE_NAME", t.type as "TABLE_TYPE" FROM "sys/tables" t WHERE t.type IN (\'table\', \'view\') AND \'\' <> ? ORDER BY "TABLE_NAME"';
}
}
@ -109,6 +104,8 @@ class GenericReflection
return 'SELECT a.attname AS "COLUMN_NAME", case when a.attnotnull then \'NO\' else \'YES\' end as "IS_NULLABLE", pg_catalog.format_type(a.atttypid, -1) as "DATA_TYPE", case when a.atttypmod < 0 then NULL else a.atttypmod-4 end as "CHARACTER_MAXIMUM_LENGTH", case when a.atttypid != 1700 then NULL else ((a.atttypmod - 4) >> 16) & 65535 end as "NUMERIC_PRECISION", case when a.atttypid != 1700 then NULL else (a.atttypmod - 4) & 65535 end as "NUMERIC_SCALE", \'\' AS "COLUMN_TYPE" FROM pg_attribute a JOIN pg_class pgc ON pgc.oid = a.attrelid WHERE pgc.relname = ? AND \'\' <> ? AND a.attnum > 0 AND NOT a.attisdropped;';
case 'sqlsrv':
return 'SELECT c.name AS "COLUMN_NAME", c.is_nullable AS "IS_NULLABLE", t.Name AS "DATA_TYPE", (c.max_length/2) AS "CHARACTER_MAXIMUM_LENGTH", c.precision AS "NUMERIC_PRECISION", c.scale AS "NUMERIC_SCALE", \'\' AS "COLUMN_TYPE" FROM sys.columns c INNER JOIN sys.types t ON c.user_type_id = t.user_type_id WHERE c.object_id = OBJECT_ID(?) AND \'\' <> ?';
case 'sqlite':
return 'SELECT "name" AS "COLUMN_NAME", case when "notnull"==1 then \'no\' else \'yes\' end as "IS_NULLABLE", "type" AS "DATA_TYPE", 2147483647 AS "CHARACTER_MAXIMUM_LENGTH", 0 AS "NUMERIC_PRECISION", 0 AS "NUMERIC_SCALE", \'\' AS "COLUMN_TYPE" FROM "sys/columns" WHERE "self" = ? AND \'\' <> ?';
}
}
@ -121,6 +118,8 @@ class GenericReflection
return 'SELECT a.attname AS "COLUMN_NAME" FROM pg_attribute a JOIN pg_constraint c ON (c.conrelid, c.conkey[1]) = (a.attrelid, a.attnum) JOIN pg_class pgc ON pgc.oid = a.attrelid WHERE pgc.relname = ? AND \'\' <> ? AND c.contype = \'p\'';
case 'sqlsrv':
return 'SELECT c.NAME as "COLUMN_NAME" FROM sys.key_constraints kc inner join sys.objects t on t.object_id = kc.parent_object_id INNER JOIN sys.index_columns ic ON kc.parent_object_id = ic.object_id and kc.unique_index_id = ic.index_id INNER JOIN sys.columns c ON ic.object_id = c.object_id AND ic.column_id = c.column_id WHERE kc.type = \'PK\' and t.object_id = OBJECT_ID(?) and \'\' <> ?';
case 'sqlite':
return 'SELECT "name" as "COLUMN_NAME" FROM "sys/columns" WHERE "pk"=1 AND "self"=? AND \'\' <> ?';
}
}
@ -133,6 +132,8 @@ class GenericReflection
return 'SELECT a.attname AS "COLUMN_NAME", c.confrelid::regclass::text AS "REFERENCED_TABLE_NAME" FROM pg_attribute a JOIN pg_constraint c ON (c.conrelid, c.conkey[1]) = (a.attrelid, a.attnum) JOIN pg_class pgc ON pgc.oid = a.attrelid WHERE pgc.relname = ? AND \'\' <> ? AND c.contype = \'f\'';
case 'sqlsrv':
return 'SELECT COL_NAME(fc.parent_object_id, fc.parent_column_id) AS "COLUMN_NAME", OBJECT_NAME (f.referenced_object_id) AS "REFERENCED_TABLE_NAME" FROM sys.foreign_keys AS f INNER JOIN sys.foreign_key_columns AS fc ON f.OBJECT_ID = fc.constraint_object_id WHERE f.parent_object_id = OBJECT_ID(?) and \'\' <> ?';
case 'sqlite':
return 'SELECT "from" AS "COLUMN_NAME", "table" AS "REFERENCED_TABLE_NAME" FROM "sys/foreign_keys" WHERE "self" = ? AND \'\' <> ?';
}
}
@ -150,20 +151,22 @@ class GenericReflection
return !$tables || in_array($v['TABLE_NAME'], $tables);
});
foreach ($results as &$result) {
$map = [];
switch ($this->driver) {
case 'mysql':
$map = ['BASE TABLE' => 'table', 'VIEW' => 'view'];
$result['TABLE_TYPE'] = $map[$result['TABLE_TYPE']];
break;
case 'pgsql':
$map = ['r' => 'table', 'v' => 'view'];
$result['TABLE_TYPE'] = $map[$result['TABLE_TYPE']];
break;
case 'sqlsrv':
$map = ['U' => 'table', 'V' => 'view'];
$result['TABLE_TYPE'] = $map[trim($result['TABLE_TYPE'])];
break;
case 'sqlite':
$map = ['table' => 'table', 'view' => 'view'];
break;
}
$result['TABLE_TYPE'] = $map[trim($result['TABLE_TYPE'])];
}
return $results;
}
@ -192,6 +195,23 @@ class GenericReflection
}
}
}
if ($this->driver == 'sqlite') {
foreach ($results as &$result) {
// mysql does not properly reflect display width of types
preg_match('|([a-z]+)(\(([0-9]+)(,([0-9]+))?\))?|', $result['DATA_TYPE'], $matches);
if (isset($matches[1])) {
$result['DATA_TYPE'] = $matches[1];
} else {
$result['DATA_TYPE'] = 'text';
}
if (isset($matches[5])) {
$result['NUMERIC_PRECISION'] = $matches[3];
$result['NUMERIC_SCALE'] = $matches[5];
} else if (isset($matches[3])) {
$result['CHARACTER_MAXIMUM_LENGTH'] = $matches[3];
}
}
}
return $results;
}

View file

@ -121,6 +121,20 @@ class TypeConverter
'uniqueidentifier' => 'char',
'xml' => 'clob',
],
'sqlite' => [
'tinytext' => 'clob',
'text' => 'clob',
'mediumtext' => 'clob',
'longtext' => 'clob',
'mediumint' => 'integer',
'int' => 'integer',
'bigint' => 'bigint',
'int2' => 'smallint',
'int4' => 'integer',
'int8' => 'bigint',
'double precision' => 'double',
'datetime' => 'timestamp',
],
];
// source: https://docs.oracle.com/javase/9/docs/api/java/sql/Types.html

View file

@ -141,6 +141,8 @@ class SimpleRouter implements Router
} catch (\PDOException $e) {
if (strpos(strtolower($e->getMessage()), 'duplicate') !== false) {
$response = $this->responder->error(ErrorCode::DUPLICATE_KEY_EXCEPTION, '');
} elseif (strpos(strtolower($e->getMessage()), 'unique constraint') !== false) {
$response = $this->responder->error(ErrorCode::DUPLICATE_KEY_EXCEPTION, '');
} elseif (strpos(strtolower($e->getMessage()), 'default value') !== false) {
$response = $this->responder->error(ErrorCode::DATA_INTEGRITY_VIOLATION, '');
} elseif (strpos(strtolower($e->getMessage()), 'allow nulls') !== false) {

View file

@ -5,27 +5,31 @@ PRAGMA foreign_keys = off;
DROP TABLE IF EXISTS "categories";
CREATE TABLE "categories" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" text(255) NOT NULL,
"icon" data NULL
"name" varchar(255) NOT NULL,
"icon" blob NULL
);
INSERT INTO "categories" ("id", "name", "icon") VALUES (1, 'announcement', NULL);
INSERT INTO "categories" ("id", "name", "icon") VALUES (2, 'article', NULL);
INSERT INTO "categories" ("id", "name", "icon") VALUES (1, 'announcement', NULL);
INSERT INTO "categories" ("id", "name", "icon") VALUES (2, 'article', NULL);
INSERT INTO "categories" ("id", "name", "icon") VALUES (3, 'comment', NULL);
DROP TABLE IF EXISTS "comments";
CREATE TABLE "comments" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"post_id" integer NOT NULL,
"message" text NOT NULL,
FOREIGN KEY ("post_id") REFERENCES "posts" ("id")
"category_id" integer NOT NULL,
FOREIGN KEY ("post_id") REFERENCES "posts" ("id"),
FOREIGN KEY ("category_id") REFERENCES "categories" ("id")
);
CREATE INDEX "comments_post_id" ON "comments" ("post_id");
CREATE INDEX "comments_category_id" ON "comments" ("category_id");
INSERT INTO "comments" ("id", "post_id", "message") VALUES (1, 1, 'great');
INSERT INTO "comments" ("id", "post_id", "message") VALUES (2, 1, 'fantastic');
INSERT INTO "comments" ("id", "post_id", "message") VALUES (3, 2, 'thank you');
INSERT INTO "comments" ("id", "post_id", "message") VALUES (4, 2, 'awesome');
INSERT INTO "comments" ("id", "post_id", "message", "category_id") VALUES (1, 1, 'great', 3);
INSERT INTO "comments" ("id", "post_id", "message", "category_id") VALUES (2, 1, 'fantastic', 3);
INSERT INTO "comments" ("id", "post_id", "message", "category_id") VALUES (3, 2, 'thank you', 3);
INSERT INTO "comments" ("id", "post_id", "message", "category_id") VALUES (4, 2, 'awesome', 3);
DROP TABLE IF EXISTS "post_tags";
CREATE TABLE "post_tags" (
@ -38,10 +42,10 @@ CREATE TABLE "post_tags" (
CREATE UNIQUE INDEX "post_tags_post_id_tag_id" ON "post_tags" ("post_id", "tag_id");
INSERT INTO "post_tags" ("id", "post_id", "tag_id") VALUES (1, 1, 1);
INSERT INTO "post_tags" ("id", "post_id", "tag_id") VALUES (2, 1, 2);
INSERT INTO "post_tags" ("id", "post_id", "tag_id") VALUES (3, 2, 1);
INSERT INTO "post_tags" ("id", "post_id", "tag_id") VALUES (4, 2, 2);
INSERT INTO "post_tags" ("id", "post_id", "tag_id") VALUES (1, 1, 1);
INSERT INTO "post_tags" ("id", "post_id", "tag_id") VALUES (2, 1, 2);
INSERT INTO "post_tags" ("id", "post_id", "tag_id") VALUES (3, 2, 1);
INSERT INTO "post_tags" ("id", "post_id", "tag_id") VALUES (4, 2, 2);
DROP TABLE IF EXISTS "posts";
CREATE TABLE "posts" (
@ -57,48 +61,58 @@ CREATE INDEX "posts_user_id" ON "posts" ("user_id");
CREATE INDEX "posts_category_id" ON "posts" ("category_id");
INSERT INTO "posts" ("id", "user_id", "category_id", "content") VALUES (1, 1, 1, 'blog started');
INSERT INTO "posts" ("id", "user_id", "category_id", "content") VALUES (2, 1, 2, 'It works!');
INSERT INTO "posts" ("id", "user_id", "category_id", "content") VALUES (1, 1, 1, 'blog started');
INSERT INTO "posts" ("id", "user_id", "category_id", "content") VALUES (2, 1, 2, 'It works!');
DROP TABLE IF EXISTS "tags";
CREATE TABLE "tags" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" text(255) NOT NULL
"name" varchar(255) NOT NULL,
"is_important" boolean NOT NULL
);
INSERT INTO "tags" ("id", "name") VALUES (1, 'funny');
INSERT INTO "tags" ("id", "name") VALUES (2, 'important');
INSERT INTO "tags" ("id", "name", "is_important") VALUES (1, 'funny', 0);
INSERT INTO "tags" ("id", "name", "is_important") VALUES (2, 'important', 1);
DROP TABLE IF EXISTS "users";
CREATE TABLE "users" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"username" text(255) NOT NULL,
"password" text(255) NOT NULL,
"location" geometry NULL
"username" varchar(255) NOT NULL,
"password" varchar(255) NOT NULL,
"location" clob NULL
);
INSERT INTO "users" ("id", "username", "password", "location") VALUES (1, 'user1', 'pass1', NULL);
INSERT INTO "users" ("id", "username", "password", "location") VALUES (2, 'user2', 'pass2', NULL);
INSERT INTO "users" ("id", "username", "password", "location") VALUES (1, 'user1', 'pass1', NULL);
INSERT INTO "users" ("id", "username", "password", "location") VALUES (2, 'user2', 'pass2', NULL);
DROP TABLE IF EXISTS "countries";
CREATE TABLE "countries" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" text(255) NOT NULL,
"shape" geometry NOT NULL
"name" varchar(255) NOT NULL,
"shape" clob NOT NULL
);
INSERT INTO "countries" ("id", "name", "shape") VALUES (1, 'Left', 'POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))');
INSERT INTO "countries" ("id", "name", "shape") VALUES (2, 'Right', 'POLYGON ((70 10, 80 40, 60 40, 50 20, 70 10))');
INSERT INTO "countries" ("id", "name", "shape") VALUES (1, 'Left', 'POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))');
INSERT INTO "countries" ("id", "name", "shape") VALUES (2, 'Right', 'POLYGON ((70 10, 80 40, 60 40, 50 20, 70 10))');
INSERT INTO "countries" ("id", "name", "shape") VALUES (3, 'Point', 'POINT (30 10)');
INSERT INTO "countries" ("id", "name", "shape") VALUES (4, 'Line', 'LINESTRING (30 10, 10 30, 40 40)');
INSERT INTO "countries" ("id", "name", "shape") VALUES (5, 'Poly1', 'POLYGON ((30 10, 40 40, 20 40, 10 20, 30 10))');
INSERT INTO "countries" ("id", "name", "shape") VALUES (6, 'Poly2', 'POLYGON ((35 10, 45 45, 15 40, 10 20, 35 10),(20 30, 35 35, 30 20, 20 30))');
INSERT INTO "countries" ("id", "name", "shape") VALUES (7, 'Mpoint', 'MULTIPOINT (10 40, 40 30, 20 20, 30 10)');
INSERT INTO "countries" ("id", "name", "shape") VALUES (8, 'Mline', 'MULTILINESTRING ((10 10, 20 20, 10 40),(40 40, 30 30, 40 20, 30 10))');
INSERT INTO "countries" ("id", "name", "shape") VALUES (9, 'Mpoly1', 'MULTIPOLYGON (((30 20, 45 40, 10 40, 30 20)),((15 5, 40 10, 10 20, 5 10, 15 5)))');
INSERT INTO "countries" ("id", "name", "shape") VALUES (10, 'Mpoly2', 'MULTIPOLYGON (((40 40, 20 45, 45 30, 40 40)),((20 35, 10 30, 10 10, 30 5, 45 20, 20 35),(30 20, 20 15, 20 25, 30 20)))');
INSERT INTO "countries" ("id", "name", "shape") VALUES (11, 'Gcoll', 'GEOMETRYCOLLECTION(POINT(4 6),LINESTRING(4 6,7 10))');
DROP TABLE IF EXISTS "events";
CREATE TABLE "events" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" text(255) NOT NULL,
"name" varchar(255) NOT NULL,
"datetime" datetime NOT NULL,
"visitors" integer NOT NULL
);
INSERT INTO "events" ("id", "name", "datetime", "visitors") VALUES (1, 'Launch', '2016-01-01 13:01:01', 0);
INSERT INTO "events" ("id", "name", "datetime", "visitors") VALUES (1, 'Launch', '2016-01-01 13:01:01', 0);
DROP VIEW IF EXISTS "tag_usage";
CREATE VIEW "tag_usage" AS select "name", count("name") AS "count" from "tags", "post_tags" where "tags"."id" = "post_tags"."tag_id" group by "name" order by "count" desc, "name";
@ -106,24 +120,36 @@ CREATE VIEW "tag_usage" AS select "name", count("name") AS "count" from "tags",
DROP TABLE IF EXISTS "products";
CREATE TABLE "products" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"name" text(255) NOT NULL,
"price" text(12) NOT NULL,
"properties" json NOT NULL,
"name" varchar(255) NOT NULL,
"price" varchar(12) NOT NULL,
"properties" clob NOT NULL,
"created_at" datetime NOT NULL,
"deleted_at" datetime NULL
);
INSERT INTO "products" ("id", "name", "price", "properties", "created_at") VALUES (1, 'Calculator', '23.01', '{"depth":false,"model":"TRX-120","width":100,"height":null}', '1970-01-01 01:01:01');
INSERT INTO "products" ("id", "name", "price", "properties", "created_at") VALUES (1, 'Calculator', '23.01', '{"depth":false,"model":"TRX-120","width":100,"height":null}', '1970-01-01 01:01:01');
DROP TABLE IF EXISTS "barcodes";
CREATE TABLE "barcodes" (
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
"product_id" integer NOT NULL,
"hex" text(255) NOT NULL,
"bin" binary(255) NOT NULL
"hex" varchar(255) NOT NULL,
"bin" blob NOT NULL
);
INSERT INTO "barcodes" ("id", "product_id", "hex", "bin") VALUES (1, 1, '00ff01', 'AP8B');
INSERT INTO "barcodes" ("id", "product_id", "hex", "bin") VALUES (1, 1, '00ff01', 'AP8B');
DROP TABLE IF EXISTS "kunsthåndværk";
CREATE TABLE "kunsthåndværk" (
"id" varchar(36) NOT NULL PRIMARY KEY,
"Umlauts ä_ö_ü-COUNT" integer NOT NULL UNIQUE,
"user_id" integer NOT NULL,
"invisible" varchar(36),
FOREIGN KEY ("user_id") REFERENCES "users" ("id") ON DELETE RESTRICT ON UPDATE RESTRICT
);
INSERT INTO "kunsthåndværk" ("id", "Umlauts ä_ö_ü-COUNT", "user_id", "invisible") VALUES ('e42c77c6-06a4-4502-816c-d112c7142e6d', 1, 1, NULL);
INSERT INTO "kunsthåndværk" ("id", "Umlauts ä_ö_ü-COUNT", "user_id", "invisible") VALUES ('e31ecfe6-591f-4660-9fbd-1a232083037f', 2, 2, NULL);
PRAGMA foreign_keys = on;