From aac6f69ea23dec574c76631278117fd2b28a21e4 Mon Sep 17 00:00:00 2001
From: eikek <eike.kettner@posteo.de>
Date: Tue, 9 Aug 2022 17:44:19 +0200
Subject: [PATCH 1/6] Update h2 and flyway

Sadly it is necessary to fix an existing changeset for H2.
---
 .../migration/h2/V1.39.0__collective_id.sql   |   2 +-
 .../migration/h2/V1.9.3__joblog_counter.sql   |   2 +-
 ...-0.24.0-dump-h2-1.24.0-2021-07-13-2307.sql | 559 ++++++++----------
 project/Dependencies.scala                    |   4 +-
 tools/h2-util.sh                              | 131 ++++
 5 files changed, 390 insertions(+), 308 deletions(-)
 create mode 100755 tools/h2-util.sh

diff --git a/modules/store/src/main/resources/db/migration/h2/V1.39.0__collective_id.sql b/modules/store/src/main/resources/db/migration/h2/V1.39.0__collective_id.sql
index 0443335b..81ef78eb 100644
--- a/modules/store/src/main/resources/db/migration/h2/V1.39.0__collective_id.sql
+++ b/modules/store/src/main/resources/db/migration/h2/V1.39.0__collective_id.sql
@@ -1,5 +1,5 @@
 -- add new id column
-alter table "collective" add column "id" bigserial not null;
+alter table "collective" add column "id" bigserial not null unique;
 create unique index "collective_id_idx" on "collective"("id");
 
 -- change references: source
diff --git a/modules/store/src/main/resources/db/migration/h2/V1.9.3__joblog_counter.sql b/modules/store/src/main/resources/db/migration/h2/V1.9.3__joblog_counter.sql
index 4de893d2..9c31f320 100644
--- a/modules/store/src/main/resources/db/migration/h2/V1.9.3__joblog_counter.sql
+++ b/modules/store/src/main/resources/db/migration/h2/V1.9.3__joblog_counter.sql
@@ -1,2 +1,2 @@
 ALTER TABLE "joblog"
-ADD COLUMN "counter" bigint auto_increment;
+ADD COLUMN "counter" bigint generated always as identity;
diff --git a/modules/store/src/test/resources/docspell-0.24.0-dump-h2-1.24.0-2021-07-13-2307.sql b/modules/store/src/test/resources/docspell-0.24.0-dump-h2-1.24.0-2021-07-13-2307.sql
index 5af8c2c6..11d4457f 100644
--- a/modules/store/src/test/resources/docspell-0.24.0-dump-h2-1.24.0-2021-07-13-2307.sql
+++ b/modules/store/src/test/resources/docspell-0.24.0-dump-h2-1.24.0-2021-07-13-2307.sql
@@ -1,58 +1,20 @@
+-- H2 2.1.214; 
 ;              
 CREATE USER IF NOT EXISTS "DOCSPELL" SALT '982433cdd49da2f5' HASH '28cc9a709ecd82c2d017c43c42038bc5df88230ea9e092fb6a53ccdaa5d4dbd2' ADMIN;    
-DROP TABLE IF EXISTS "public"."flyway_schema_history" CASCADE; 
-DROP TABLE IF EXISTS "public"."filemeta" CASCADE;              
-DROP TABLE IF EXISTS "public"."filechunk" CASCADE;             
-DROP TABLE IF EXISTS "public"."user_" CASCADE; 
-DROP TABLE IF EXISTS "public"."invitation" CASCADE;            
-DROP TABLE IF EXISTS "public"."tagsource" CASCADE;             
-DROP TABLE IF EXISTS "public"."node" CASCADE;  
-DROP TABLE IF EXISTS "public"."source" CASCADE;
-DROP TABLE IF EXISTS "public"."folder" CASCADE;
-DROP TABLE IF EXISTS "public"."rememberme" CASCADE;            
-DROP TABLE IF EXISTS "public"."contact" CASCADE;               
-DROP TABLE IF EXISTS "public"."organization" CASCADE;          
-DROP TABLE IF EXISTS "public"."attachment" CASCADE;            
-DROP TABLE IF EXISTS "public"."equipment" CASCADE;             
-DROP TABLE IF EXISTS "public"."tag" CASCADE;   
-DROP TABLE IF EXISTS "public"."tagitem" CASCADE;               
-DROP TABLE IF EXISTS "public"."job" CASCADE;   
-DROP TABLE IF EXISTS "public"."attachment_preview" CASCADE;    
-DROP TABLE IF EXISTS "public"."jobgroupuse" CASCADE;           
-DROP TABLE IF EXISTS "public"."useremail" CASCADE;             
-DROP TABLE IF EXISTS "public"."sentmail" CASCADE;              
-DROP TABLE IF EXISTS "public"."sentmailitem" CASCADE;          
-DROP TABLE IF EXISTS "public"."joblog" CASCADE;
-DROP TABLE IF EXISTS "public"."attachment_source" CASCADE;     
-DROP TABLE IF EXISTS "public"."client_settings" CASCADE;       
-DROP TABLE IF EXISTS "public"."attachment_archive" CASCADE;    
-DROP TABLE IF EXISTS "public"."collective" CASCADE;            
-DROP TABLE IF EXISTS "public"."folder_member" CASCADE;         
-DROP TABLE IF EXISTS "public"."item" CASCADE;  
-DROP TABLE IF EXISTS "public"."classifier_model" CASCADE;      
-DROP TABLE IF EXISTS "public"."custom_field" CASCADE;          
-DROP TABLE IF EXISTS "public"."custom_field_value" CASCADE;    
-DROP TABLE IF EXISTS "public"."person" CASCADE;
-DROP TABLE IF EXISTS "public"."userimap" CASCADE;              
-DROP TABLE IF EXISTS "public"."item_proposal" CASCADE;         
-DROP TABLE IF EXISTS "public"."attachmentmeta" CASCADE;        
-DROP TABLE IF EXISTS "public"."classifier_setting" CASCADE;    
-DROP TABLE IF EXISTS "public"."periodic_task" CASCADE;         
-DROP ALIAS IF EXISTS "public"."cast_to_numeric";               
-CREATE FORCE ALIAS "public"."cast_to_numeric" FOR "docspell.store.impl.h2.CastNumericFun.castToNumeric";       
-CREATE SEQUENCE "public"."SYSTEM_SEQUENCE_95446BBD_DF65_42A9_A00E_2556C5A54A0C" START WITH 977 BELONGS_TO_TABLE;               
+CREATE USER IF NOT EXISTS "SA" SALT '0350c81faca6374e' HASH '9e59bcd632e9d817d0cb48849febcda4ca45c879e8c77118930dbcf6d8c31ef6' ADMIN;          
+CREATE FORCE ALIAS "public"."cast_to_numeric" FOR 'docspell.store.impl.h2.CastNumericFun.castToNumeric';       
 CREATE CACHED TABLE "public"."flyway_schema_history"(
-    "installed_rank" INT NOT NULL,
-    "version" VARCHAR(50),
-    "description" VARCHAR(200) NOT NULL,
-    "type" VARCHAR(20) NOT NULL,
-    "script" VARCHAR(1000) NOT NULL,
-    "checksum" INT,
-    "installed_by" VARCHAR(100) NOT NULL,
+    "installed_rank" INTEGER NOT NULL,
+    "version" CHARACTER VARYING(50),
+    "description" CHARACTER VARYING(200) NOT NULL,
+    "type" CHARACTER VARYING(20) NOT NULL,
+    "script" CHARACTER VARYING(1000) NOT NULL,
+    "checksum" INTEGER,
+    "installed_by" CHARACTER VARYING(100) NOT NULL,
     "installed_on" TIMESTAMP DEFAULT CURRENT_TIMESTAMP NOT NULL,
-    "execution_time" INT NOT NULL,
+    "execution_time" INTEGER NOT NULL,
     "success" BOOLEAN NOT NULL
-);         
+);           
 ALTER TABLE "public"."flyway_schema_history" ADD CONSTRAINT "public"."flyway_schema_history_pk" PRIMARY KEY("installed_rank"); 
 -- 35 +/- SELECT COUNT(*) FROM public.flyway_schema_history;   
 INSERT INTO "public"."flyway_schema_history" VALUES
@@ -68,7 +30,7 @@ INSERT INTO "public"."flyway_schema_history" VALUES
 (9, '1.8.0', 'folders', 'SQL', 'V1.8.0__folders.sql', 1074998524, 'DOCSPELL', TIMESTAMP '2021-01-03 20:49:32.515', 26, TRUE),
 (10, '1.9.0', 'updated column', 'SQL', 'V1.9.0__updated_column.sql', -1023981633, 'DOCSPELL', TIMESTAMP '2021-01-03 20:49:32.558', 30, TRUE),
 (11, '1.9.1', 'classifier', 'SQL', 'V1.9.1__classifier.sql', -920209386, 'DOCSPELL', TIMESTAMP '2021-01-03 20:49:32.572', 2, TRUE),
-(12, '1.9.3', 'joblog counter', 'SQL', 'V1.9.3__joblog_counter.sql', 175554607, 'DOCSPELL', TIMESTAMP '2021-01-03 20:49:32.591', 6, TRUE),
+(12, '1.9.3', 'joblog counter', 'SQL', 'V1.9.3__joblog_counter.sql', -276220379, 'DOCSPELL', TIMESTAMP '2021-01-03 20:49:32.591', 6, TRUE),
 (13, '1.9.4', 'unique equipments', 'SQL', 'V1.9.4__unique_equipments.sql', 770293754, 'DOCSPELL', TIMESTAMP '2021-01-03 20:49:32.605', 1, TRUE),
 (14, '1.10.0', 'attachment preview', 'SQL', 'V1.10.0__attachment_preview.sql', 175251272, 'DOCSPELL', TIMESTAMP '2021-01-03 20:49:32.619', 2, TRUE),
 (15, '1.11.0', 'pdf pages', 'SQL', 'V1.11.0__pdf_pages.sql', -235351002, 'DOCSPELL', TIMESTAMP '2021-01-03 20:49:32.636', 2, TRUE),
@@ -92,15 +54,15 @@ INSERT INTO "public"."flyway_schema_history" VALUES
 (32, '1.22.0', 'add task name', 'SQL', 'V1.22.0__add_task_name.sql', -1625232914, 'DOCSPELL', TIMESTAMP '2021-05-29 14:02:47.320332', 48, TRUE),
 (33, '1.23.0', 'clientsettings', 'SQL', 'V1.23.0__clientsettings.sql', 1152128793, 'DOCSPELL', TIMESTAMP '2021-05-29 14:02:47.454567', 17, TRUE),
 (34, '1.24.0', 'drop fts migration', 'SQL', 'V1.24.0__drop_fts_migration.sql', -501760318, 'DOCSPELL', TIMESTAMP '2021-06-11 16:12:26.558332', 35, TRUE);     
-CREATE INDEX "public"."flyway_schema_history_s_idx" ON "public"."flyway_schema_history"("success");            
+CREATE INDEX "public"."flyway_schema_history_s_idx" ON "public"."flyway_schema_history"("success" NULLS FIRST);
 CREATE CACHED TABLE "public"."filemeta"(
-    "id" VARCHAR(254) NOT NULL,
-    "timestamp" VARCHAR(40) NOT NULL,
-    "mimetype" VARCHAR(254) NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "timestamp" CHARACTER VARYING(40) NOT NULL,
+    "mimetype" CHARACTER VARYING(254) NOT NULL,
     "length" BIGINT NOT NULL,
-    "checksum" VARCHAR(254) NOT NULL,
-    "chunks" INT NOT NULL,
-    "chunksize" INT NOT NULL
+    "checksum" CHARACTER VARYING(254) NOT NULL,
+    "chunks" INTEGER NOT NULL,
+    "chunksize" INTEGER NOT NULL
 );            
 ALTER TABLE "public"."filemeta" ADD CONSTRAINT "public"."CONSTRAINT_D" PRIMARY KEY("id");      
 -- 11 +/- SELECT COUNT(*) FROM public.filemeta;
@@ -117,11 +79,11 @@ INSERT INTO "public"."filemeta" VALUES
 ('39fJiyTA5cF-NbFRocgVXsa-8HZq4chnjuj-PtT7VwD4EWV', '2021-07-13T21:03:16.189302Z', 'application/gzip', 13096, 'd9298fb169c51890ad5e146108c75bfeb8e8452bd54b2cdb32f1000e2146a4e4', 4, 4096),
 ('DHGeDybWtnT-AkD5avn2wTB-RvfFeVguPUu-LDJADAajdSD', '2021-07-13T21:03:16.435753Z', 'application/gzip', 12734, 'fc228c554ae12b3998728b00f098dbc0aa20ae767c6f945acc8f0ae65fcb35fb', 4, 4096);              
 CREATE CACHED TABLE "public"."filechunk"(
-    "fileid" VARCHAR(254) NOT NULL,
-    "chunknr" INT NOT NULL,
-    "chunklength" INT NOT NULL,
-    "chunkdata" BYTEA NOT NULL
-);    
+    "fileid" CHARACTER VARYING(254) NOT NULL,
+    "chunknr" INTEGER NOT NULL,
+    "chunklength" INTEGER NOT NULL,
+    "chunkdata" BINARY VARYING NOT NULL
+);         
 ALTER TABLE "public"."filechunk" ADD CONSTRAINT "public"."CONSTRAINT_B" PRIMARY KEY("fileid", "chunknr");      
 -- 26 +/- SELECT COUNT(*) FROM public.filechunk;               
 INSERT INTO "public"."filechunk" VALUES
@@ -173,13 +135,13 @@ INSERT INTO "public"."filechunk" VALUES
 INSERT INTO "public"."filechunk" VALUES
 ('DHGeDybWtnT-AkD5avn2wTB-RvfFeVguPUu-LDJADAajdSD', 3, 446, X'b0b0293c68be7ed0ed59549b5c5128b66a8dc9258dd184e0dd3b9f354fc63d3aafc3cda4e36945bcbb6cacd090212ddbe26610b2b4f3578567ac4bfaebf2498385e158fe5af08ca1e451bdd068950b1591e8da420bbeafe5f6351f514f1c5bbc73ded4a39306ddeef68df578589fc235f35f9cca14785701a7bd4f01674f799025c562bb51284eca5b53cff6a6450f8c56130f33d5391e9f36e876e3e3ee07c613a80be86e313bb554cbe0a95ef79948157b69c2c35262d9ddefeefdace75d83df058f37c6c02862ceca4c3cd37deca9a9f9fd99e41fe6fbc5979ff7e353ee9b7dbe7bf6bfa926e9bf932f3ef9df349a6a37d5d69f0a214a807bdd08163f655f48eef73beef15f3f77d95c83c9e34fb4a94ffd938fb80facfae0b987ee78e2feb7a461859fbed4699404197bf353f4a2267d532c5b31facd6dd5017f57dff9c9a43182d062d0e5eae4e79020742d179cd93c6aaa5311ff9aff15d3cc30fe23d3927f618aee7fc4b4e4dff4ffc4346f8a755d4c03fd9bfe0d9f003fc30cd7024edc7266fdfcc10bcfeafc6ffedc13cf3af282c317bfe0cc39072d3e62f116dc1f85db3ef979fec20b8f587cc8e20b122417f401f5ff016469b277dae20000');          
 CREATE CACHED TABLE "public"."user_"(
-    "uid" VARCHAR(254) NOT NULL,
-    "login" VARCHAR(254) NOT NULL,
-    "cid" VARCHAR(254) NOT NULL,
-    "password" VARCHAR(254) NOT NULL,
-    "state" VARCHAR(254) NOT NULL,
-    "email" VARCHAR(254),
-    "logincount" INT NOT NULL,
+    "uid" CHARACTER VARYING(254) NOT NULL,
+    "login" CHARACTER VARYING(254) NOT NULL,
+    "cid" CHARACTER VARYING(254) NOT NULL,
+    "password" CHARACTER VARYING(254) NOT NULL,
+    "state" CHARACTER VARYING(254) NOT NULL,
+    "email" CHARACTER VARYING(254),
+    "logincount" INTEGER NOT NULL,
     "lastlogin" TIMESTAMP,
     "created" TIMESTAMP NOT NULL
 );    
@@ -188,89 +150,89 @@ ALTER TABLE "public"."user_" ADD CONSTRAINT "public"."CONSTRAINT_6" PRIMARY KEY(
 INSERT INTO "public"."user_" VALUES
 ('Bx213P591Rr-enoBUH66pTn-81emkqRGdQj-XNxT85q7YM5', 'demo', 'demo', '$2a$10$GlIOWljA8hfBZpUVmXdJAON4cM96HyZcHzQKj.pYM7zImeY4uhHY.', 'active', NULL, 7, TIMESTAMP '2021-07-13 21:06:56.472803', TIMESTAMP '2021-01-03 21:13:16.146');       
 CREATE CACHED TABLE "public"."invitation"(
-    "id" VARCHAR(254) NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
     "created" TIMESTAMP NOT NULL
-); 
+);       
 ALTER TABLE "public"."invitation" ADD CONSTRAINT "public"."CONSTRAINT_4" PRIMARY KEY("id");    
 -- 0 +/- SELECT COUNT(*) FROM public.invitation;               
 CREATE CACHED TABLE "public"."tagsource"(
-    "id" VARCHAR(254) NOT NULL,
-    "source_id" VARCHAR(254) NOT NULL,
-    "tag_id" VARCHAR(254) NOT NULL
-);         
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "source_id" CHARACTER VARYING(254) NOT NULL,
+    "tag_id" CHARACTER VARYING(254) NOT NULL
+);           
 ALTER TABLE "public"."tagsource" ADD CONSTRAINT "public"."CONSTRAINT_9E" PRIMARY KEY("id");    
 -- 0 +/- SELECT COUNT(*) FROM public.tagsource;
 CREATE CACHED TABLE "public"."node"(
-    "id" VARCHAR(254) NOT NULL,
-    "type" VARCHAR(254) NOT NULL,
-    "url" VARCHAR(254) NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "type" CHARACTER VARYING(254) NOT NULL,
+    "url" CHARACTER VARYING(254) NOT NULL,
     "updated" TIMESTAMP NOT NULL,
     "created" TIMESTAMP NOT NULL,
-    "not_found" INT DEFAULT 0 NOT NULL
-);          
+    "not_found" INTEGER DEFAULT 0 NOT NULL
+);        
 -- 2 +/- SELECT COUNT(*) FROM public.node;     
 INSERT INTO "public"."node" VALUES
 ('rest1', 'restserver', 'http://localhost:7020', TIMESTAMP '2021-07-13 21:06:44.235033', TIMESTAMP '2021-01-03 20:49:33.047', 0),
 ('joex1', 'joex', 'http://localhost:7021', TIMESTAMP '2021-07-13 21:06:03.808725', TIMESTAMP '2021-01-03 20:49:34.078', 0);               
 CREATE CACHED TABLE "public"."source"(
-    "sid" VARCHAR(254) NOT NULL,
-    "cid" VARCHAR(254) NOT NULL,
-    "abbrev" VARCHAR(254) NOT NULL,
-    "description" TEXT,
-    "counter" INT NOT NULL,
+    "sid" CHARACTER VARYING(254) NOT NULL,
+    "cid" CHARACTER VARYING(254) NOT NULL,
+    "abbrev" CHARACTER VARYING(254) NOT NULL,
+    "description" CHARACTER VARYING,
+    "counter" INTEGER NOT NULL,
     "enabled" BOOLEAN NOT NULL,
-    "priority" INT NOT NULL,
+    "priority" INTEGER NOT NULL,
     "created" TIMESTAMP NOT NULL,
-    "folder_id" VARCHAR(254),
-    "file_filter" VARCHAR(254),
-    "doc_lang" VARCHAR(254)
-);   
+    "folder_id" CHARACTER VARYING(254),
+    "file_filter" CHARACTER VARYING(254),
+    "doc_lang" CHARACTER VARYING(254)
+);  
 ALTER TABLE "public"."source" ADD CONSTRAINT "public"."CONSTRAINT_C" PRIMARY KEY("sid");       
 -- 1 +/- SELECT COUNT(*) FROM public.source;   
 INSERT INTO "public"."source" VALUES
 ('FcVZWHAgfFD-MdYCm3qWTyX-a7hcbVhsgKG-FG9DwArw9eQ', 'demo', 'test', NULL, 0, TRUE, 0, TIMESTAMP '2021-01-03 21:35:32.86', NULL, NULL, NULL);              
 CREATE CACHED TABLE "public"."folder"(
-    "id" VARCHAR(254) NOT NULL,
-    "name" VARCHAR(254) NOT NULL,
-    "cid" VARCHAR(254) NOT NULL,
-    "owner" VARCHAR(254) NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "name" CHARACTER VARYING(254) NOT NULL,
+    "cid" CHARACTER VARYING(254) NOT NULL,
+    "owner" CHARACTER VARYING(254) NOT NULL,
     "created" TIMESTAMP NOT NULL
-);               
+);       
 ALTER TABLE "public"."folder" ADD CONSTRAINT "public"."CONSTRAINT_B4" PRIMARY KEY("id");       
 -- 0 +/- SELECT COUNT(*) FROM public.folder;   
 CREATE CACHED TABLE "public"."rememberme"(
-    "id" VARCHAR(254) NOT NULL,
-    "cid" VARCHAR(254) NOT NULL,
-    "login" VARCHAR(254) NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "cid" CHARACTER VARYING(254) NOT NULL,
+    "login" CHARACTER VARYING(254) NOT NULL,
     "created" TIMESTAMP NOT NULL,
-    "uses" INT NOT NULL
-);    
+    "uses" INTEGER NOT NULL
+);  
 ALTER TABLE "public"."rememberme" ADD CONSTRAINT "public"."CONSTRAINT_20" PRIMARY KEY("id");   
 -- 0 +/- SELECT COUNT(*) FROM public.rememberme;               
 CREATE CACHED TABLE "public"."contact"(
-    "contactid" VARCHAR(254) NOT NULL,
-    "value" VARCHAR(254) NOT NULL,
-    "kind" VARCHAR(254) NOT NULL,
-    "pid" VARCHAR(254),
-    "oid" VARCHAR(254),
+    "contactid" CHARACTER VARYING(254) NOT NULL,
+    "value" CHARACTER VARYING(254) NOT NULL,
+    "kind" CHARACTER VARYING(254) NOT NULL,
+    "pid" CHARACTER VARYING(254),
+    "oid" CHARACTER VARYING(254),
     "created" TIMESTAMP NOT NULL
-);        
+);      
 ALTER TABLE "public"."contact" ADD CONSTRAINT "public"."CONSTRAINT_3" PRIMARY KEY("contactid");
 -- 0 +/- SELECT COUNT(*) FROM public.contact;  
 CREATE CACHED TABLE "public"."organization"(
-    "oid" VARCHAR(254) NOT NULL,
-    "cid" VARCHAR(254) NOT NULL,
-    "name" VARCHAR(254) NOT NULL,
-    "street" VARCHAR(254),
-    "zip" VARCHAR(254),
-    "city" VARCHAR(254),
-    "country" VARCHAR(254),
-    "notes" TEXT,
+    "oid" CHARACTER VARYING(254) NOT NULL,
+    "cid" CHARACTER VARYING(254) NOT NULL,
+    "name" CHARACTER VARYING(254) NOT NULL,
+    "street" CHARACTER VARYING(254),
+    "zip" CHARACTER VARYING(254),
+    "city" CHARACTER VARYING(254),
+    "country" CHARACTER VARYING(254),
+    "notes" CHARACTER VARYING,
     "created" TIMESTAMP NOT NULL,
     "updated" TIMESTAMP NOT NULL,
-    "short_name" VARCHAR(254),
-    "org_use" VARCHAR(254) NOT NULL
-);           
+    "short_name" CHARACTER VARYING(254),
+    "org_use" CHARACTER VARYING(254) NOT NULL
+);    
 ALTER TABLE "public"."organization" ADD CONSTRAINT "public"."CONSTRAINT_46" PRIMARY KEY("oid");
 -- 3 +/- SELECT COUNT(*) FROM public.organization;             
 INSERT INTO "public"."organization" VALUES
@@ -278,36 +240,36 @@ INSERT INTO "public"."organization" VALUES
 ('85CGijc6q6q-Vj1dZXCPGcK-rpDK7MKVrRz-xyNsSbEbuJy', 'demo', 'Pancake Company', '', '', '', '', NULL, TIMESTAMP '2021-01-03 21:33:01.966', TIMESTAMP '2021-01-03 21:33:01.966', NULL, 'correspondent'),
 ('Gu3ufBQNyco-TqVjyREXNpJ-f4j9VCdyYoR-TNgUkiQXR1Y', 'demo', 'Sliced Invoices', '', '', '', '', NULL, TIMESTAMP '2021-01-03 21:34:29.153', TIMESTAMP '2021-01-03 21:34:29.153', NULL, 'correspondent');        
 CREATE CACHED TABLE "public"."attachment"(
-    "attachid" VARCHAR(254) NOT NULL,
-    "itemid" VARCHAR(254) NOT NULL,
-    "filemetaid" VARCHAR(254) NOT NULL,
-    "position" INT NOT NULL,
+    "attachid" CHARACTER VARYING(254) NOT NULL,
+    "itemid" CHARACTER VARYING(254) NOT NULL,
+    "filemetaid" CHARACTER VARYING(254) NOT NULL,
+    "position" INTEGER NOT NULL,
     "created" TIMESTAMP NOT NULL,
-    "name" VARCHAR(254)
-);         
+    "name" CHARACTER VARYING(254)
+);             
 ALTER TABLE "public"."attachment" ADD CONSTRAINT "public"."CONSTRAINT_8" PRIMARY KEY("attachid");              
 -- 2 +/- SELECT COUNT(*) FROM public.attachment;               
 INSERT INTO "public"."attachment" VALUES
 ('2ecoA7A7HgT-xPwzNQYfiZd-rF1XF3aEPMr-qsNJXoe36oZ', 'J4wAkg3jxt5-7QaYXD1WTmF-gq4kGaS89RP-DnPyUwa77fK', '8jre1Sk2anC-XycazyE1d9M-UUjNsj1LsLu-zmZfiPwKB6J', 0, TIMESTAMP '2021-01-03 21:13:33.416', 'wordpress-pdf-invoice-plugin-sample.converted.pdf'),
 ('4SDQngEFYuK-tb9xAachZSt-LNCrE36NFRr-U8avxFCW9A4', '2wKtSUVt3Kj-mAmexmm1jFe-BU6aY6PN4vo-5cpaDD2EyRm', 'BQR2G7GT5LQ-FKV4FQ1hnDu-9TSkF7nhUyz-nmpe9qDVvBd', 0, TIMESTAMP '2021-01-03 21:34:43.9', 'letter-en.converted.pdf');   
 CREATE CACHED TABLE "public"."equipment"(
-    "eid" VARCHAR(254) NOT NULL,
-    "cid" VARCHAR(254) NOT NULL,
-    "name" VARCHAR(254) NOT NULL,
+    "eid" CHARACTER VARYING(254) NOT NULL,
+    "cid" CHARACTER VARYING(254) NOT NULL,
+    "name" CHARACTER VARYING(254) NOT NULL,
     "created" TIMESTAMP NOT NULL,
     "updated" TIMESTAMP NOT NULL,
-    "notes" TEXT,
-    "equip_use" VARCHAR(254) NOT NULL
-);   
+    "notes" CHARACTER VARYING,
+    "equip_use" CHARACTER VARYING(254) NOT NULL
+);              
 ALTER TABLE "public"."equipment" ADD CONSTRAINT "public"."CONSTRAINT_40" PRIMARY KEY("eid");   
 -- 0 +/- SELECT COUNT(*) FROM public.equipment;
 CREATE CACHED TABLE "public"."tag"(
-    "tid" VARCHAR(254) NOT NULL,
-    "cid" VARCHAR(254) NOT NULL,
-    "name" VARCHAR(254) NOT NULL,
-    "category" VARCHAR(254),
+    "tid" CHARACTER VARYING(254) NOT NULL,
+    "cid" CHARACTER VARYING(254) NOT NULL,
+    "name" CHARACTER VARYING(254) NOT NULL,
+    "category" CHARACTER VARYING(254),
     "created" TIMESTAMP NOT NULL
-);       
+);               
 ALTER TABLE "public"."tag" ADD CONSTRAINT "public"."CONSTRAINT_1B" PRIMARY KEY("tid");         
 -- 5 +/- SELECT COUNT(*) FROM public.tag;      
 INSERT INTO "public"."tag" VALUES
@@ -317,10 +279,10 @@ INSERT INTO "public"."tag" VALUES
 ('4ugueUtfP1p-oqrtQDHmY6V-Yd9PEvhr1Zz-X9aurGADsgK', 'demo', 'Notice', 'doctype', TIMESTAMP '2021-01-03 21:32:41.632'),
 ('EMp5ZCBvt6X-jx579vGQa7Y-VpWD1zqFTnZ-XSU1r9bEn9j', 'demo', 'Todo', 'state', TIMESTAMP '2021-01-03 21:32:50.08');         
 CREATE CACHED TABLE "public"."tagitem"(
-    "tagitemid" VARCHAR(254) NOT NULL,
-    "itemid" VARCHAR(254) NOT NULL,
-    "tid" VARCHAR(254) NOT NULL
-);          
+    "tagitemid" CHARACTER VARYING(254) NOT NULL,
+    "itemid" CHARACTER VARYING(254) NOT NULL,
+    "tid" CHARACTER VARYING(254) NOT NULL
+);            
 ALTER TABLE "public"."tagitem" ADD CONSTRAINT "public"."CONSTRAINT_A" PRIMARY KEY("tagitemid");
 -- 3 +/- SELECT COUNT(*) FROM public.tagitem;  
 INSERT INTO "public"."tagitem" VALUES
@@ -328,23 +290,23 @@ INSERT INTO "public"."tagitem" VALUES
 ('ATAxJL8LASW-be9FMJabPbX-KBpHqAk5asG-KHxJMk1A7aw', '2wKtSUVt3Kj-mAmexmm1jFe-BU6aY6PN4vo-5cpaDD2EyRm', 'AYmkK5Y5mvF-xBh4gGkA3z9-HWHxM2cs4v6-r5Wcqw9vEpY'),
 ('6W1PtieE38Y-oLfG17gPirm-5sa9xjykAQ3-tqYH69ipDRy', 'J4wAkg3jxt5-7QaYXD1WTmF-gq4kGaS89RP-DnPyUwa77fK', 'EMp5ZCBvt6X-jx579vGQa7Y-VpWD1zqFTnZ-XSU1r9bEn9j');         
 CREATE CACHED TABLE "public"."job"(
-    "jid" VARCHAR(254) NOT NULL,
-    "task" VARCHAR(254) NOT NULL,
-    "group_" VARCHAR(254) NOT NULL,
-    "args" TEXT NOT NULL,
-    "subject" VARCHAR(254) NOT NULL,
+    "jid" CHARACTER VARYING(254) NOT NULL,
+    "task" CHARACTER VARYING(254) NOT NULL,
+    "group_" CHARACTER VARYING(254) NOT NULL,
+    "args" CHARACTER VARYING NOT NULL,
+    "subject" CHARACTER VARYING(254) NOT NULL,
     "submitted" TIMESTAMP NOT NULL,
-    "submitter" VARCHAR(254) NOT NULL,
-    "priority" INT NOT NULL,
-    "state" VARCHAR(254) NOT NULL,
-    "retries" INT NOT NULL,
-    "progress" INT NOT NULL,
-    "tracker" VARCHAR(254),
-    "worker" VARCHAR(254),
+    "submitter" CHARACTER VARYING(254) NOT NULL,
+    "priority" INTEGER NOT NULL,
+    "state" CHARACTER VARYING(254) NOT NULL,
+    "retries" INTEGER NOT NULL,
+    "progress" INTEGER NOT NULL,
+    "tracker" CHARACTER VARYING(254),
+    "worker" CHARACTER VARYING(254),
     "started" TIMESTAMP,
     "finished" TIMESTAMP,
     "startedmillis" BIGINT
-);          
+); 
 ALTER TABLE "public"."job" ADD CONSTRAINT "public"."CONSTRAINT_19" PRIMARY KEY("jid");         
 -- 17 +/- SELECT COUNT(*) FROM public.job;     
 INSERT INTO "public"."job" VALUES
@@ -367,72 +329,72 @@ INSERT INTO "public"."job" VALUES
 ('Fb6p5jSp6Xg-hSw4kYdk9gB-hSQFML94yzP-FLxtPWufche', 'all-previews', 'docspell-system', '{"collective":null,"storeMode":"whenmissing"}', 'Create preview images', TIMESTAMP '2021-07-13 21:06:03.679443', 'docspell-system', 0, 'success', 0, 0, 'generate-all-previews', 'joex1', TIMESTAMP '2021-07-13 21:06:08.582687', TIMESTAMP '2021-07-13 21:06:08.962884', 1626210368582),
 ('8HEvkXhpQPF-vswPxVSYdVP-fBcsCh6bCmk-vaaCguTKpWU', 'all-page-count', 'docspell-system', '{}', 'Create all page-counts', TIMESTAMP '2021-07-13 21:06:03.732908', 'docspell-system', 0, 'success', 0, 0, 'all-page-count-tracker', 'joex1', TIMESTAMP '2021-07-13 21:06:09.056159', TIMESTAMP '2021-07-13 21:06:09.175354', 1626210369056);           
 CREATE CACHED TABLE "public"."attachment_preview"(
-    "id" VARCHAR(254) NOT NULL,
-    "file_id" VARCHAR(254) NOT NULL,
-    "filename" VARCHAR(254),
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "file_id" CHARACTER VARYING(254) NOT NULL,
+    "filename" CHARACTER VARYING(254),
     "created" TIMESTAMP NOT NULL
-);       
+);         
 ALTER TABLE "public"."attachment_preview" ADD CONSTRAINT "public"."CONSTRAINT_2D" PRIMARY KEY("id");           
 -- 2 +/- SELECT COUNT(*) FROM public.attachment_preview;       
 INSERT INTO "public"."attachment_preview" VALUES
 ('2ecoA7A7HgT-xPwzNQYfiZd-rF1XF3aEPMr-qsNJXoe36oZ', 'D8Cj2R2fmSM-z31GMJF61iG-BQnDzjGWeh1-bhQfBym5qrQ', 'wordpress-pdf-invoice-plugin-sample.converted_preview.png', TIMESTAMP '2021-01-03 21:13:35.431'),
 ('4SDQngEFYuK-tb9xAachZSt-LNCrE36NFRr-U8avxFCW9A4', '7Vvy4bZfe3b-YCpAVWc8Lw9-wUkKLWjo3RL-4RnazGiQtnY', 'letter-en.converted_preview.png', TIMESTAMP '2021-01-03 21:34:45.865');     
 CREATE CACHED TABLE "public"."jobgroupuse"(
-    "groupid" VARCHAR(254) NOT NULL,
-    "workerid" VARCHAR(254) NOT NULL
-);       
+    "groupid" CHARACTER VARYING(254) NOT NULL,
+    "workerid" CHARACTER VARYING(254) NOT NULL
+);   
 ALTER TABLE "public"."jobgroupuse" ADD CONSTRAINT "public"."CONSTRAINT_7" PRIMARY KEY("groupid", "workerid");  
 -- 2 +/- SELECT COUNT(*) FROM public.jobgroupuse;              
 INSERT INTO "public"."jobgroupuse" VALUES
 ('joex1', 'docspell-system'),
 ('joex1', 'demo');     
 CREATE CACHED TABLE "public"."useremail"(
-    "id" VARCHAR(254) NOT NULL,
-    "uid" VARCHAR(254) NOT NULL,
-    "name" VARCHAR(254) NOT NULL,
-    "smtp_host" VARCHAR(254) NOT NULL,
-    "smtp_port" INT,
-    "smtp_user" VARCHAR(254),
-    "smtp_password" VARCHAR(254),
-    "smtp_ssl" VARCHAR(254) NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "uid" CHARACTER VARYING(254) NOT NULL,
+    "name" CHARACTER VARYING(254) NOT NULL,
+    "smtp_host" CHARACTER VARYING(254) NOT NULL,
+    "smtp_port" INTEGER,
+    "smtp_user" CHARACTER VARYING(254),
+    "smtp_password" CHARACTER VARYING(254),
+    "smtp_ssl" CHARACTER VARYING(254) NOT NULL,
     "smtp_certcheck" BOOLEAN NOT NULL,
-    "mail_from" VARCHAR(254) NOT NULL,
-    "mail_replyto" VARCHAR(254),
+    "mail_from" CHARACTER VARYING(254) NOT NULL,
+    "mail_replyto" CHARACTER VARYING(254),
     "created" TIMESTAMP NOT NULL
-);              
+);
 ALTER TABLE "public"."useremail" ADD CONSTRAINT "public"."CONSTRAINT_14" PRIMARY KEY("id");    
 -- 1 +/- SELECT COUNT(*) FROM public.useremail;
 INSERT INTO "public"."useremail" VALUES
 ('HjroW9mh3d7-Hpfc9aiWkjP-Uc9KbcRj2Hd-1rtLJEecUSn', 'Bx213P591Rr-enoBUH66pTn-81emkqRGdQj-XNxT85q7YM5', 'testmail', 'localhost', 25, 'test', 'test', 'noencryption', TRUE, 'test@test.com', NULL, TIMESTAMP '2021-01-04 08:57:55.739'); 
 CREATE CACHED TABLE "public"."sentmail"(
-    "id" VARCHAR(254) NOT NULL,
-    "uid" VARCHAR(254) NOT NULL,
-    "message_id" VARCHAR(254) NOT NULL,
-    "sender" VARCHAR(254) NOT NULL,
-    "conn_name" VARCHAR(254) NOT NULL,
-    "subject" VARCHAR(254) NOT NULL,
-    "recipients" VARCHAR(254) NOT NULL,
-    "body" TEXT NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "uid" CHARACTER VARYING(254) NOT NULL,
+    "message_id" CHARACTER VARYING(254) NOT NULL,
+    "sender" CHARACTER VARYING(254) NOT NULL,
+    "conn_name" CHARACTER VARYING(254) NOT NULL,
+    "subject" CHARACTER VARYING(254) NOT NULL,
+    "recipients" CHARACTER VARYING(254) NOT NULL,
+    "body" CHARACTER VARYING NOT NULL,
     "created" TIMESTAMP NOT NULL
-);        
+);     
 ALTER TABLE "public"."sentmail" ADD CONSTRAINT "public"."CONSTRAINT_4B" PRIMARY KEY("id");     
 -- 0 +/- SELECT COUNT(*) FROM public.sentmail; 
 CREATE CACHED TABLE "public"."sentmailitem"(
-    "id" VARCHAR(254) NOT NULL,
-    "item_id" VARCHAR(254) NOT NULL,
-    "sentmail_id" VARCHAR(254) NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "item_id" CHARACTER VARYING(254) NOT NULL,
+    "sentmail_id" CHARACTER VARYING(254) NOT NULL,
     "created" TIMESTAMP NOT NULL
-); 
+);   
 ALTER TABLE "public"."sentmailitem" ADD CONSTRAINT "public"."CONSTRAINT_5" PRIMARY KEY("id");  
 -- 0 +/- SELECT COUNT(*) FROM public.sentmailitem;             
 CREATE CACHED TABLE "public"."joblog"(
-    "id" VARCHAR(254) NOT NULL,
-    "jid" VARCHAR(254) NOT NULL,
-    "level" VARCHAR(254) NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "jid" CHARACTER VARYING(254) NOT NULL,
+    "level" CHARACTER VARYING(254) NOT NULL,
     "created" TIMESTAMP NOT NULL,
-    "message" TEXT NOT NULL,
-    "counter" BIGINT DEFAULT NEXT VALUE FOR "public"."SYSTEM_SEQUENCE_95446BBD_DF65_42A9_A00E_2556C5A54A0C" NOT NULL NULL_TO_DEFAULT SEQUENCE "public"."SYSTEM_SEQUENCE_95446BBD_DF65_42A9_A00E_2556C5A54A0C"
-);     
+    "message" CHARACTER VARYING NOT NULL,
+    "counter" BIGINT GENERATED BY DEFAULT AS IDENTITY(START WITH 977) DEFAULT ON NULL NOT NULL
+);         
 ALTER TABLE "public"."joblog" ADD CONSTRAINT "public"."CONSTRAINT_BB" PRIMARY KEY("id");       
 -- 185 +/- SELECT COUNT(*) FROM public.joblog; 
 INSERT INTO "public"."joblog" VALUES
@@ -631,88 +593,88 @@ INSERT INTO "public"."joblog" VALUES
 ('BBs6to96VHZ-4zr7ZPdztKL-HBoaftmqReY-MM1njyjcLBb', '8HEvkXhpQPF-vswPxVSYdVP-fBcsCh6bCmk-vaaCguTKpWU', 'info', TIMESTAMP '2021-07-13 21:06:09.126876', 'Submitted 0 jobs', 975),
 ('7fF3dSegsV2-nYAZd8pnFUM-efwZAJ1skr4-TDiJLZpsHFG', '8HEvkXhpQPF-vswPxVSYdVP-fBcsCh6bCmk-vaaCguTKpWU', 'info', TIMESTAMP '2021-07-13 21:06:09.173384', 'Job execution successful', 976);        
 CREATE CACHED TABLE "public"."attachment_source"(
-    "id" VARCHAR(254) NOT NULL,
-    "file_id" VARCHAR(254) NOT NULL,
-    "filename" VARCHAR(254),
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "file_id" CHARACTER VARYING(254) NOT NULL,
+    "filename" CHARACTER VARYING(254),
     "created" TIMESTAMP NOT NULL
-);        
+);          
 ALTER TABLE "public"."attachment_source" ADD CONSTRAINT "public"."CONSTRAINT_69" PRIMARY KEY("id");            
 -- 2 +/- SELECT COUNT(*) FROM public.attachment_source;        
 INSERT INTO "public"."attachment_source" VALUES
 ('2ecoA7A7HgT-xPwzNQYfiZd-rF1XF3aEPMr-qsNJXoe36oZ', 'DtG18bCtiGr-fGEwzMKktpB-tosSKp9g7ty-wDgXGffbp1f', 'wordpress-pdf-invoice-plugin-sample.pdf', TIMESTAMP '2021-01-03 21:13:33.416'),
 ('4SDQngEFYuK-tb9xAachZSt-LNCrE36NFRr-U8avxFCW9A4', 'JXziW35E2TW-zXPFxZeeNwA-M1fcdXMEdAL-FVYEyKNC7N', 'letter-en.pdf', TIMESTAMP '2021-01-03 21:34:43.9');             
 CREATE CACHED TABLE "public"."client_settings"(
-    "id" VARCHAR(254) NOT NULL,
-    "client_id" VARCHAR(254) NOT NULL,
-    "user_id" VARCHAR(254) NOT NULL,
-    "settings_data" TEXT NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "client_id" CHARACTER VARYING(254) NOT NULL,
+    "user_id" CHARACTER VARYING(254) NOT NULL,
+    "settings_data" CHARACTER VARYING NOT NULL,
     "created" TIMESTAMP NOT NULL,
     "updated" TIMESTAMP NOT NULL
-);           
+);
 ALTER TABLE "public"."client_settings" ADD CONSTRAINT "public"."CONSTRAINT_E" PRIMARY KEY("id");               
 -- 1 +/- SELECT COUNT(*) FROM public.client_settings;          
 INSERT INTO "public"."client_settings" VALUES
 ('JAX2ZTZsv6m-aTkj5aSfNjK-VTRkbN7o8QN-XfLNRdd7a8P', 'webClient', 'Bx213P591Rr-enoBUH66pTn-81emkqRGdQj-XNxT85q7YM5', '{"itemSearchPageSize":60,"tagCategoryColors":{"doctype":"yellow","state":"green"},"nativePdfPreview":true,"itemSearchNoteLength":0,"itemDetailNotesPosition":"bottom","searchMenuFolderCount":3,"searchMenuTagCount":6,"searchMenuTagCatCount":3,"formFields":["concequip","concperson","corrorg","corrperson","customfields","date","direction","duedate","folder","preview","sourcename","tag"],"itemDetailShortcuts":false,"searchMenuVisible":false,"editMenuVisible":false,"cardPreviewSize":"medium","cardTitleTemplate":"{{name}}","cardSubtitleTemplate":"{{dateLong}}","searchStatsVisible":true,"cardPreviewFullWidth":false,"uiTheme":"Dark","sideMenuVisible":true,"powerSearchEnabled":true,"uiLang":"gb"}', TIMESTAMP '2021-05-29 14:03:42.867883', TIMESTAMP '2021-05-29 14:04:52.065916');  
 CREATE CACHED TABLE "public"."attachment_archive"(
-    "id" VARCHAR(254) NOT NULL,
-    "file_id" VARCHAR(254) NOT NULL,
-    "filename" VARCHAR(254),
-    "message_id" VARCHAR(254),
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "file_id" CHARACTER VARYING(254) NOT NULL,
+    "filename" CHARACTER VARYING(254),
+    "message_id" CHARACTER VARYING(254),
     "created" TIMESTAMP NOT NULL
-);        
+);
 ALTER TABLE "public"."attachment_archive" ADD CONSTRAINT "public"."CONSTRAINT_13" PRIMARY KEY("id");           
 -- 0 +/- SELECT COUNT(*) FROM public.attachment_archive;       
-CREATE INDEX "public"."attachment_archive_message_id_idx" ON "public"."attachment_archive"("message_id");      
+CREATE INDEX "public"."attachment_archive_message_id_idx" ON "public"."attachment_archive"("message_id" NULLS FIRST);          
 CREATE CACHED TABLE "public"."collective"(
-    "cid" VARCHAR(254) NOT NULL,
-    "state" VARCHAR(254) NOT NULL,
-    "doclang" VARCHAR(254) NOT NULL,
+    "cid" CHARACTER VARYING(254) NOT NULL,
+    "state" CHARACTER VARYING(254) NOT NULL,
+    "doclang" CHARACTER VARYING(254) NOT NULL,
     "created" TIMESTAMP NOT NULL,
     "integration_enabled" BOOLEAN NOT NULL
-);            
+);              
 ALTER TABLE "public"."collective" ADD CONSTRAINT "public"."CONSTRAINT_9" PRIMARY KEY("cid");   
 -- 1 +/- SELECT COUNT(*) FROM public.collective;               
 INSERT INTO "public"."collective" VALUES
 ('demo', 'active', 'deu', TIMESTAMP '2021-01-03 21:13:16.146', TRUE); 
 CREATE CACHED TABLE "public"."folder_member"(
-    "id" VARCHAR(254) NOT NULL,
-    "folder_id" VARCHAR(254) NOT NULL,
-    "user_id" VARCHAR(254) NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "folder_id" CHARACTER VARYING(254) NOT NULL,
+    "user_id" CHARACTER VARYING(254) NOT NULL,
     "created" TIMESTAMP NOT NULL
-);  
+);    
 ALTER TABLE "public"."folder_member" ADD CONSTRAINT "public"."CONSTRAINT_BD" PRIMARY KEY("id");
 -- 0 +/- SELECT COUNT(*) FROM public.folder_member;            
 CREATE CACHED TABLE "public"."item"(
-    "itemid" VARCHAR(254) NOT NULL,
-    "cid" VARCHAR(254) NOT NULL,
-    "name" VARCHAR(254) NOT NULL,
+    "itemid" CHARACTER VARYING(254) NOT NULL,
+    "cid" CHARACTER VARYING(254) NOT NULL,
+    "name" CHARACTER VARYING(254) NOT NULL,
     "itemdate" TIMESTAMP,
-    "source" VARCHAR(254) NOT NULL,
+    "source" CHARACTER VARYING(254) NOT NULL,
     "incoming" BOOLEAN NOT NULL,
-    "state" VARCHAR(254) NOT NULL,
-    "corrorg" VARCHAR(254),
-    "corrperson" VARCHAR(254),
-    "concperson" VARCHAR(254),
-    "concequipment" VARCHAR(254),
-    "inreplyto" VARCHAR(254),
+    "state" CHARACTER VARYING(254) NOT NULL,
+    "corrorg" CHARACTER VARYING(254),
+    "corrperson" CHARACTER VARYING(254),
+    "concperson" CHARACTER VARYING(254),
+    "concequipment" CHARACTER VARYING(254),
+    "inreplyto" CHARACTER VARYING(254),
     "duedate" TIMESTAMP,
-    "notes" TEXT,
+    "notes" CHARACTER VARYING,
     "created" TIMESTAMP NOT NULL,
     "updated" TIMESTAMP NOT NULL,
-    "folder_id" VARCHAR(254)
-);         
+    "folder_id" CHARACTER VARYING(254)
+);              
 ALTER TABLE "public"."item" ADD CONSTRAINT "public"."CONSTRAINT_31" PRIMARY KEY("itemid");     
 -- 2 +/- SELECT COUNT(*) FROM public.item;     
 INSERT INTO "public"."item" VALUES
 ('J4wAkg3jxt5-7QaYXD1WTmF-gq4kGaS89RP-DnPyUwa77fK', 'demo', 'wordpress-pdf-invoice-plugin-sample.pdf', TIMESTAMP '2016-01-25 12:00:00', 'webapp', TRUE, 'confirmed', 'Gu3ufBQNyco-TqVjyREXNpJ-f4j9VCdyYoR-TNgUkiQXR1Y', NULL, NULL, NULL, NULL, NULL, NULL, TIMESTAMP '2021-01-03 21:13:33.41', TIMESTAMP '2021-01-03 21:34:33.901', NULL),
 ('2wKtSUVt3Kj-mAmexmm1jFe-BU6aY6PN4vo-5cpaDD2EyRm', 'demo', 'letter-en.pdf', TIMESTAMP '2019-09-03 12:00:00', 'webapp', TRUE, 'confirmed', '85CGijc6q6q-Vj1dZXCPGcK-rpDK7MKVrRz-xyNsSbEbuJy', '83XuNaLvbMt-E3ocm83uYtt-VoLgToV7gxz-rYhG6ZDZmB6', '2vhk349kjyK-LYQWRjTPLro-E4hCRgJyGC3-BMqG3bcVw4y', NULL, NULL, NULL, NULL, TIMESTAMP '2021-01-03 21:34:43.896', TIMESTAMP '2021-01-03 21:35:05.565', NULL);    
 CREATE CACHED TABLE "public"."classifier_model"(
-    "id" VARCHAR(254) NOT NULL,
-    "cid" VARCHAR(254) NOT NULL,
-    "name" VARCHAR(254) NOT NULL,
-    "file_id" VARCHAR(254) NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "cid" CHARACTER VARYING(254) NOT NULL,
+    "name" CHARACTER VARYING(254) NOT NULL,
+    "file_id" CHARACTER VARYING(254) NOT NULL,
     "created" TIMESTAMP NOT NULL
-);   
+);           
 ALTER TABLE "public"."classifier_model" ADD CONSTRAINT "public"."CONSTRAINT_BC" PRIMARY KEY("id");             
 -- 5 +/- SELECT COUNT(*) FROM public.classifier_model;         
 INSERT INTO "public"."classifier_model" VALUES
@@ -722,13 +684,13 @@ INSERT INTO "public"."classifier_model" VALUES
 ('EeRCrtyYxLw-sFZSqYQpF2x-xRNYmtpehF5-gnUpF3p677F', 'demo', 'concernedperson', '39fJiyTA5cF-NbFRocgVXsa-8HZq4chnjuj-PtT7VwD4EWV', TIMESTAMP '2021-07-13 21:03:16.246099'),
 ('7bSotqXw7Rh-JYioDdg7imG-3L2b5gbKrcJ-nHjGjYQo7A2', 'demo', 'concernedequip', 'DHGeDybWtnT-AkD5avn2wTB-RvfFeVguPUu-LDJADAajdSD', TIMESTAMP '2021-07-13 21:03:16.487072');             
 CREATE CACHED TABLE "public"."custom_field"(
-    "id" VARCHAR(254) NOT NULL,
-    "name" VARCHAR(254) NOT NULL,
-    "label" VARCHAR(254),
-    "cid" VARCHAR(254) NOT NULL,
-    "ftype" VARCHAR(100) NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "name" CHARACTER VARYING(254) NOT NULL,
+    "label" CHARACTER VARYING(254),
+    "cid" CHARACTER VARYING(254) NOT NULL,
+    "ftype" CHARACTER VARYING(100) NOT NULL,
     "created" TIMESTAMP NOT NULL
-);               
+);             
 ALTER TABLE "public"."custom_field" ADD CONSTRAINT "public"."CONSTRAINT_2A" PRIMARY KEY("id"); 
 -- 3 +/- SELECT COUNT(*) FROM public.custom_field;             
 INSERT INTO "public"."custom_field" VALUES
@@ -736,120 +698,109 @@ INSERT INTO "public"."custom_field" VALUES
 ('HGU7e4ViYRK-C45csppWGya-JfvqSBK7RHV-hewejitFZLt', 'usd', 'USD', 'demo', 'money', TIMESTAMP '2021-01-03 21:33:38.397'),
 ('H4GdvuxxiTu-xkrSbSiLEYu-AaEmVaX3T8d-EwNA1fEWzar', 'paid', 'Paid', 'demo', 'date', TIMESTAMP '2021-01-03 21:33:49.783');         
 CREATE CACHED TABLE "public"."custom_field_value"(
-    "id" VARCHAR(254) NOT NULL,
-    "item_id" VARCHAR(254) NOT NULL,
-    "field" VARCHAR(254) NOT NULL,
-    "field_value" VARCHAR(300) NOT NULL
-);          
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "item_id" CHARACTER VARYING(254) NOT NULL,
+    "field" CHARACTER VARYING(254) NOT NULL,
+    "field_value" CHARACTER VARYING(300) NOT NULL
+);  
 ALTER TABLE "public"."custom_field_value" ADD CONSTRAINT "public"."CONSTRAINT_6F" PRIMARY KEY("id");           
 -- 2 +/- SELECT COUNT(*) FROM public.custom_field_value;       
 INSERT INTO "public"."custom_field_value" VALUES
 ('5mTamR1DWyQ-GnQbNwRN3hA-LhhkXvrLTAp-Rx8kzt5cHFV', 'J4wAkg3jxt5-7QaYXD1WTmF-gq4kGaS89RP-DnPyUwa77fK', 'HGU7e4ViYRK-C45csppWGya-JfvqSBK7RHV-hewejitFZLt', '93.50'),
 ('FRgFi2EJe7E-QHeQwhJJeJu-ddtSXiH3rY7-BFiTLJ52TbK', 'J4wAkg3jxt5-7QaYXD1WTmF-gq4kGaS89RP-DnPyUwa77fK', 'H4GdvuxxiTu-xkrSbSiLEYu-AaEmVaX3T8d-EwNA1fEWzar', '2016-01-28');  
 CREATE CACHED TABLE "public"."person"(
-    "pid" VARCHAR(254) NOT NULL,
-    "cid" VARCHAR(254) NOT NULL,
-    "name" VARCHAR(254) NOT NULL,
-    "street" VARCHAR(254),
-    "zip" VARCHAR(254),
-    "city" VARCHAR(254),
-    "country" VARCHAR(254),
-    "notes" TEXT,
+    "pid" CHARACTER VARYING(254) NOT NULL,
+    "cid" CHARACTER VARYING(254) NOT NULL,
+    "name" CHARACTER VARYING(254) NOT NULL,
+    "street" CHARACTER VARYING(254),
+    "zip" CHARACTER VARYING(254),
+    "city" CHARACTER VARYING(254),
+    "country" CHARACTER VARYING(254),
+    "notes" CHARACTER VARYING,
     "created" TIMESTAMP NOT NULL,
     "updated" TIMESTAMP NOT NULL,
-    "oid" VARCHAR(254),
-    "person_use" VARCHAR(254)
-);              
+    "oid" CHARACTER VARYING(254),
+    "person_use" CHARACTER VARYING(254)
+);       
 ALTER TABLE "public"."person" ADD CONSTRAINT "public"."CONSTRAINT_C4" PRIMARY KEY("pid");      
 -- 2 +/- SELECT COUNT(*) FROM public.person;   
 INSERT INTO "public"."person" VALUES
 ('83XuNaLvbMt-E3ocm83uYtt-VoLgToV7gxz-rYhG6ZDZmB6', 'demo', 'Marcus Leaf', '', '', '', '', NULL, TIMESTAMP '2021-01-03 21:33:10.411', TIMESTAMP '2021-01-03 21:33:10.411', '85CGijc6q6q-Vj1dZXCPGcK-rpDK7MKVrRz-xyNsSbEbuJy', 'correspondent'),
 ('2vhk349kjyK-LYQWRjTPLro-E4hCRgJyGC3-BMqG3bcVw4y', 'demo', 'Derek Jeter', '', '', '', '', NULL, TIMESTAMP '2021-01-03 21:33:17.323', TIMESTAMP '2021-01-03 21:33:17.323', NULL, 'concerning');           
 CREATE CACHED TABLE "public"."userimap"(
-    "id" VARCHAR(254) NOT NULL,
-    "uid" VARCHAR(254) NOT NULL,
-    "name" VARCHAR(254) NOT NULL,
-    "imap_host" VARCHAR(254) NOT NULL,
-    "imap_port" INT,
-    "imap_user" VARCHAR(254),
-    "imap_password" VARCHAR(254),
-    "imap_ssl" VARCHAR(254) NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
+    "uid" CHARACTER VARYING(254) NOT NULL,
+    "name" CHARACTER VARYING(254) NOT NULL,
+    "imap_host" CHARACTER VARYING(254) NOT NULL,
+    "imap_port" INTEGER,
+    "imap_user" CHARACTER VARYING(254),
+    "imap_password" CHARACTER VARYING(254),
+    "imap_ssl" CHARACTER VARYING(254) NOT NULL,
     "imap_certcheck" BOOLEAN NOT NULL,
     "created" TIMESTAMP NOT NULL,
     "imap_oauth2" BOOLEAN NOT NULL
-);   
+);         
 ALTER TABLE "public"."userimap" ADD CONSTRAINT "public"."CONSTRAINT_F" PRIMARY KEY("id");      
 -- 1 +/- SELECT COUNT(*) FROM public.userimap; 
 INSERT INTO "public"."userimap" VALUES
 ('8B2utYsaPVY-SbAV8AfdLHY-HMM9DhcyLSh-tH1xPia5kab', 'Bx213P591Rr-enoBUH66pTn-81emkqRGdQj-XNxT85q7YM5', 'testmail', 'localhost', 143, 'test', 'test', 'noencryption', TRUE, TIMESTAMP '2021-01-04 08:58:06.485', FALSE); 
 CREATE CACHED TABLE "public"."item_proposal"(
-    "itemid" VARCHAR(254) NOT NULL,
-    "classifier_proposals" TEXT NOT NULL,
-    "classifier_tags" TEXT NOT NULL,
+    "itemid" CHARACTER VARYING(254) NOT NULL,
+    "classifier_proposals" CHARACTER VARYING NOT NULL,
+    "classifier_tags" CHARACTER VARYING NOT NULL,
     "created" TIMESTAMP NOT NULL
-);           
+);       
 ALTER TABLE "public"."item_proposal" ADD CONSTRAINT "public"."CONSTRAINT_DBF" PRIMARY KEY("itemid");           
 -- 0 +/- SELECT COUNT(*) FROM public.item_proposal;            
 CREATE CACHED TABLE "public"."attachmentmeta"(
-    "attachid" VARCHAR(254) NOT NULL,
-    "content" TEXT,
-    "nerlabels" TEXT,
-    "itemproposals" TEXT,
+    "attachid" CHARACTER VARYING(254) NOT NULL,
+    "content" CHARACTER VARYING,
+    "nerlabels" CHARACTER VARYING,
+    "itemproposals" CHARACTER VARYING,
     "page_count" SMALLINT,
-    "language" VARCHAR(254)
-);             
+    "language" CHARACTER VARYING(254)
+);  
 ALTER TABLE "public"."attachmentmeta" ADD CONSTRAINT "public"."CONSTRAINT_1" PRIMARY KEY("attachid");          
 -- 2 +/- SELECT COUNT(*) FROM public.attachmentmeta;           
-CREATE TABLE IF NOT EXISTS SYSTEM_LOB_STREAM(ID INT NOT NULL, PART INT NOT NULL, CDATA VARCHAR, BDATA BINARY); 
-CREATE PRIMARY KEY SYSTEM_LOB_STREAM_PRIMARY_KEY ON SYSTEM_LOB_STREAM(ID, PART);               
-CREATE ALIAS IF NOT EXISTS SYSTEM_COMBINE_CLOB FOR "org.h2.command.dml.ScriptCommand.combineClob";             
-CREATE ALIAS IF NOT EXISTS SYSTEM_COMBINE_BLOB FOR "org.h2.command.dml.ScriptCommand.combineBlob";             
-INSERT INTO SYSTEM_LOB_STREAM VALUES(0, 0, '[{"label":"Sliced Invoices | admin@slicedinvoices.com","tag":"misc","startPosition":138,"endPosition":180},{"label":"Page 1/1","tag":"misc","startPosition":182,"endPosition":190},{"label":"Sliced Invoices","tag":"misc","startPosition":206,"endPosition":221},{"label":"Date January","tag":"person","startPosition":359,"endPosition":371},{"label":"Due Date January","tag":"person","startPosition":382,"endPosition":398},{"label":"Total Due $","tag":"misc","startPosition":409,"endPosition":420},{"label":"Price Adjust Sub Total","tag":"misc","startPosition":522,"endPosition":544},{"label":"1.00 Web Design This","tag":"misc","startPosition":546,"endPosition":566},{"label":"Sub Total $","tag":"misc","startPosition":616,"endPosition":627},{"label":"Tax $","tag":"misc","startPosition":634,"endPosition":639},{"label":"ANZ Bank","tag":"organization","startPosition":659,"endPosition":667},{"label":"Pa id","tag":"misc","startPosition":701,"endPosition":706},{"label":"PDF Invoice Example Sliced","tag":"misc","startPosition":708,"endPosition":734},{"label":"Sliced","tag":"misc","startPosition":138,"endPosition":144},{"label":"Invoices","tag":"misc","startPosition":145,"endPosition":153},{"label":"|","tag":"misc","startPosition":154,"endPosition":155},{"label":"admin@slicedinvoices.com","tag":"misc","startPosition":156,"endPosition":180},{"label":"Page","tag":"misc","startPosition":182,"endPosition":186},{"label":"1/1","tag":"misc","startPosition":187,"endPosition":190},{"label":"From","tag":"misc","startPosition":192,"endPosition":196},{"label":"Sliced","tag":"misc","startPosition":206,"endPosition":212},{"label":"Invoices","tag":"misc","startPosition":213,"endPosition":221},{"label":"Suite","tag":"misc","startPosition":223,"endPosition":228},{"label":"Street","tag":"organization","startPosition":252,"endPosition":258},{"label":"Your","tag":"organization","startPosition":260,"endPosition":264},{"label":"Date","tag":"person","startPosition":359,"endPosition":363},{"label":"January","tag":"person","startPosition":364,"endPosition":371},{"label":"Due","tag":"person","startPosition":382,"endPosition":385},{"label":"Date","tag":"person","startPosition":386,"endPosition":390},{"label":"January","tag":"person","startPosition":391,"endPosition":398},{"label":"Total","tag":"misc","startPosition":409,"endPosition":414},{"label":"Due","tag":"misc","startPosition":415,"endPosition":418},{"label":"$","tag":"misc","startPosition":419,"endPosition":420},{"label":"St","tag":"location","startPosition":461,"endPosition":463},{"label":"Melbourne","tag":"location","startPosition":465,"endPosition":474},{"label":"Price","tag":"misc","startPosition":522,"endPosition":527},{"label":"Adjust","tag":"misc","startPosition":528,"endPosition":534},{"label":"Sub","tag":"misc","startPosition":535,"endPosition":538},{"label":"Total","tag":"misc","startPosition":539,"endPosition":544},{"label":"1.00","tag":"misc","startPosition":546,"endPosition":550},{"label":"Web","tag":"misc","startPosition":551,"endPosition":554},{"label":"Design","tag":"misc","startPosition":555,"endPosition":561},{"label":"This","tag":"misc","startPosition":562,"endPosition":566},{"label":"$","tag":"misc","startPosition":595,"endPosition":596},{"label":"$","tag":"misc","startPosition":608,"endPosition":609},{"label":"85.00","tag":"misc","startPosition":609,"endPosition":614},{"label":"Sub","tag":"misc","startPosition":616,"endPosition":619},{"label":"Total","tag":"misc","startPosition":620,"endPosition":625},{"label":"$","tag":"misc","startPosition":626,"endPosition":627},{"label":"85.00","tag":"misc","startPosition":627,"endPosition":632},{"label":"Tax","tag":"misc","startPosition":634,"endPosition":637},{"label":"$","tag":"misc","startPosition":638,"endPosition":639},{"label":"$","tag":"misc","startPosition":651,"endPosition":652},{"label":"ANZ","tag":"organization","startPosition":659,"endPosition":662},{"label":"Bank","tag":"organization","startPosition":663,"endPosition":667},{"label":"ACC","tag":"organization","startPosition":669,"endPosition":672},{"label":"Pa","tag":"misc","startPosition":7', NULL);          
-INSERT INTO SYSTEM_LOB_STREAM VALUES(0, 1, '01,"endPosition":703},{"label":"id","tag":"misc","startPosition":704,"endPosition":706},{"label":"PDF","tag":"misc","startPosition":708,"endPosition":711},{"label":"Invoice","tag":"misc","startPosition":712,"endPosition":719},{"label":"Example","tag":"misc","startPosition":720,"endPosition":727},{"label":"Sliced","tag":"misc","startPosition":728,"endPosition":734},{"label":"admin@slicedinvoices.com","tag":"email","startPosition":156,"endPosition":180},{"label":"admin@slicedinvoices.com","tag":"email","startPosition":280,"endPosition":304},{"label":"test@test.com","tag":"email","startPosition":486,"endPosition":499},{"label":"2016-01-25","tag":"date","startPosition":364,"endPosition":374},{"label":"2016-01-31","tag":"date","startPosition":391,"endPosition":401}]', NULL);       
-INSERT INTO SYSTEM_LOB_STREAM VALUES(1, 0, '[{"label":"Derek Jeter","tag":"person","startPosition":0,"endPosition":11},{"label":"Derek Jeter","tag":"person","startPosition":69,"endPosition":80},{"label":"M. Leaf","tag":"person","startPosition":142,"endPosition":149},{"label":"Syrup Production","tag":"organization","startPosition":160,"endPosition":176},{"label":"Old Sticky Pancake Company","tag":"organization","startPosition":178,"endPosition":204},{"label":"456 Maple Lane","tag":"organization","startPosition":206,"endPosition":220},{"label":"Let me begin by thanking you for your past contributions to our Little League baseball","tag":"misc","startPosition":287,"endPosition":373},{"label":"their past years of service and present employees for their","tag":"organization","startPosition":621,"endPosition":680},{"label":"Derek Jeter","tag":"person","startPosition":1128,"endPosition":1139},{"label":"Derek Jeter","tag":"person","startPosition":1141,"endPosition":1152},{"label":"Derek","tag":"person","startPosition":0,"endPosition":5},{"label":"Jeter","tag":"person","startPosition":6,"endPosition":11},{"label":"Elm","tag":"location","startPosition":17,"endPosition":20},{"label":"Derek","tag":"person","startPosition":69,"endPosition":74},{"label":"Jeter","tag":"person","startPosition":75,"endPosition":80},{"label":"Elm","tag":"location","startPosition":86,"endPosition":89},{"label":"M.","tag":"person","startPosition":142,"endPosition":144},{"label":"Leaf","tag":"person","startPosition":145,"endPosition":149},{"label":"Syrup","tag":"organization","startPosition":160,"endPosition":165},{"label":"Production","tag":"organization","startPosition":166,"endPosition":176},{"label":"Old","tag":"organization","startPosition":178,"endPosition":181},{"label":"Sticky","tag":"organization","startPosition":182,"endPosition":188},{"label":"Pancake","tag":"organization","startPosition":189,"endPosition":196},{"label":"Company","tag":"organization","startPosition":197,"endPosition":204},{"label":"456","tag":"organization","startPosition":206,"endPosition":209},{"label":"Maple","tag":"organization","startPosition":210,"endPosition":215},{"label":"Lane","tag":"organization","startPosition":216,"endPosition":220},{"label":"Forest","tag":"organization","startPosition":222,"endPosition":228},{"label":"Leaf","tag":"person","startPosition":280,"endPosition":284},{"label":"Let","tag":"misc","startPosition":287,"endPosition":290},{"label":"me","tag":"misc","startPosition":291,"endPosition":293},{"label":"begin","tag":"misc","startPosition":294,"endPosition":299},{"label":"by","tag":"misc","startPosition":300,"endPosition":302},{"label":"thanking","tag":"misc","startPosition":303,"endPosition":311},{"label":"you","tag":"misc","startPosition":312,"endPosition":315},{"label":"for","tag":"misc","startPosition":316,"endPosition":319},{"label":"your","tag":"misc","startPosition":320,"endPosition":324},{"label":"past","tag":"misc","startPosition":325,"endPosition":329},{"label":"contributions","tag":"misc","startPosition":330,"endPosition":343},{"label":"to","tag":"misc","startPosition":344,"endPosition":346},{"label":"our","tag":"misc","startPosition":347,"endPosition":350},{"label":"Little","tag":"misc","startPosition":351,"endPosition":357},{"label":"League","tag":"misc","startPosition":358,"endPosition":364},{"label":"baseball","tag":"misc","startPosition":365,"endPosition":373},{"label":"team","tag":"misc","startPosition":375,"endPosition":379},{"label":"company","tag":"organization","startPosition":524,"endPosition":531},{"label":"pancake","tag":"organization","startPosition":569,"endPosition":576},{"label":"their","tag":"organization","startPosition":621,"endPosition":626},{"label":"past","tag":"organization","startPosition":627,"endPosition":631},{"label":"years","tag":"organization","startPosition":632,"endPosition":637},{"label":"of","tag":"organization","startPosition":638,"endPosition":640},{"label":"service","tag":"organization","startPosition":641,"endPosition":648},{"label":"and","tag":"organization","startPosition":649,"endPosition":652},{"label":"present","tag":"organization","startPosit', NULL);          
-INSERT INTO SYSTEM_LOB_STREAM VALUES(1, 1, 'ion":653,"endPosition":660},{"label":"employees","tag":"organization","startPosition":661,"endPosition":670},{"label":"for","tag":"organization","startPosition":671,"endPosition":674},{"label":"their","tag":"organization","startPosition":675,"endPosition":680},{"label":"loyalty","tag":"organization","startPosition":682,"endPosition":689},{"label":"company","tag":"organization","startPosition":803,"endPosition":810},{"label":"pancake","tag":"organization","startPosition":828,"endPosition":835},{"label":"Derek","tag":"person","startPosition":1128,"endPosition":1133},{"label":"Jeter","tag":"person","startPosition":1134,"endPosition":1139},{"label":"Derek","tag":"person","startPosition":1141,"endPosition":1146},{"label":"Jeter","tag":"person","startPosition":1147,"endPosition":1152},{"label":"2016-11-07","tag":"date","startPosition":51,"endPosition":61},{"label":"2016-11-07","tag":"date","startPosition":120,"endPosition":130},{"label":"2019-09-03","tag":"date","startPosition":252,"endPosition":263},{"label":"2016-12-12","tag":"date","startPosition":1087,"endPosition":1098}]', NULL);            
 INSERT INTO "public"."attachmentmeta" VALUES
-('2ecoA7A7HgT-xPwzNQYfiZd-rF1XF3aEPMr-qsNJXoe36oZ', STRINGDECODE('Invoice\n\nPayment is due within 30 days from date of invoice. Late payment is subject to fees of 5% per month.\n\nThanks for choosing DEMO - Sliced Invoices | admin@slicedinvoices.com\n\nPage 1/1\n\nFrom:\n\nDEMO - Sliced Invoices\n\nSuite 5A-1204\n\n123 Somewhere Street\n\nYour City AZ 12345\n\nadmin@slicedinvoices.com\n\nInvoice Number INV-3337\n\nOrder Number 12345\n\nInvoice Date January 25, 2016\n\nDue Date January 31, 2016\n\nTotal Due $93.50\n\nTo:\n\nTest Business\n\n123 Somewhere St\n\nMelbourne, VIC 3000\n\ntest@test.com\n\nHrs/Qty Service Rate/Price Adjust Sub Total\n\n1.00\nWeb Design\nThis is a sample description...\n\n$85.00 0.00% $85.00\n\nSub Total $85.00\n\nTax $8.50\n\nTotal $93.50\n\nANZ Bank\n\nACC # 1234 1234\n\nBSB # 4321 432 Pa\nid\n\nPDF Invoice Example\nSliced Invoices\nExample PDF invoice that was created using the Sli\n2016-02-04'), SYSTEM_COMBINE_CLOB(0), '{"proposals":[{"proposalType":"docdate","values":[{"ref":{"id":"2016-01-25","name":"2016-01-25"},"origin":[{"label":"January 25, 2016","tag":"date","startPosition":364,"endPosition":374}],"weight":0.0753623188405797},{"ref":{"id":"2016-01-31","name":"2016-01-31"},"origin":[{"label":"January 31, 2016","tag":"date","startPosition":391,"endPosition":401}],"weight":0.08095238095238094}]}]}', 1, 'deu'),
-('4SDQngEFYuK-tb9xAachZSt-LNCrE36NFRr-U8avxFCW9A4', STRINGDECODE('Derek Jeter\n\n123 Elm Ave.\n\nTreesville, ON M1N 2P3\n\nNovember 7, 2016\n\nDerek Jeter, 123 Elm Ave., Treesville, ON M1N 2P3, November 7, 2016\n\nMr. M. Leaf\n\nChief of Syrup Production\n\nOld Sticky Pancake Company\n\n456 Maple Lane\n\nForest, ON 7W8 9Y0\n\nHemptown, September 3, 2019\n\nDear Mr. Leaf,\n\nLet me begin by thanking you for your past contributions to our Little League baseball\n\nteam. Your sponsorship aided in the purchase of ten full uniforms and several pieces of\n\nbaseball equipment for last year\u2019s season.\n\nNext month, our company is planning an employee appreciation pancake breakfast hon-\n\noring retired employees for their past years of service and present employees for their\n\nloyalty and dedication in spite of the current difficult economic conditions.\n\nWe would like to place an order with your company for 25 pounds of pancake mix and\n\nfive gallons of maple syrup. We hope you will be able to provide these products in the\n\nbulk quantities we require.\n\nAs you are a committed corporate sponsor and long-time associate, we hope that you\n\nwill be able to join us for breakfast on December 12, 2016.\n\nRespectfully yours,\n\nDerek Jeter\n\nDerek Jeter\n2019-09-03'), SYSTEM_COMBINE_CLOB(1), '{"proposals":[{"proposalType":"corrperson","values":[{"ref":{"id":"83XuNaLvbMt-E3ocm83uYtt-VoLgToV7gxz-rYhG6ZDZmB6","name":"Marcus Leaf"},"origin":[{"label":"Leaf","tag":"person","startPosition":145,"endPosition":149}],"weight":0.024935511607910577}]},{"proposalType":"corrorg","values":[{"ref":{"id":"85CGijc6q6q-Vj1dZXCPGcK-rpDK7MKVrRz-xyNsSbEbuJy","name":"Pancake Company"},"origin":[{"label":"Company","tag":"organization","startPosition":197,"endPosition":204},{"label":"Pancake","tag":"organization","startPosition":189,"endPosition":196}],"weight":0.03250214961306965}]},{"proposalType":"concperson","values":[{"ref":{"id":"2vhk349kjyK-LYQWRjTPLro-E4hCRgJyGC3-BMqG3bcVw4y","name":"Derek Jeter"},"origin":[{"label":"Derek Jeter","tag":"person","startPosition":0,"endPosition":11}],"weight":0.0}]},{"proposalType":"docdate","values":[{"ref":{"id":"2016-11-07","name":"2016-11-07"},"origin":[{"label":"November 7, 2016","tag":"date","startPosition":51,"endPosition":61}],"weight":0.007308684436801376},{"ref":{"id":"2016-11-07","name":"2016-11-07"},"origin":[{"label":"November 7, 2016","tag":"date","startPosition":120,"endPosition":130}],"weight":0.017196904557179708},{"ref":{"id":"2019-09-03","name":"2019-09-03"},"origin":[{"label":"September 3, 2019","tag":"date","startPosition":252,"endPosition":263}],"weight":0.03611349957007738},{"ref":{"id":"2016-12-12","name":"2016-12-12"},"origin":[{"label":"December 12, 2016","tag":"date","startPosition":1087,"endPosition":1098}],"weight":0.3115505875609057}]}]}', 1, 'deu');
+('2ecoA7A7HgT-xPwzNQYfiZd-rF1XF3aEPMr-qsNJXoe36oZ', U&'Invoice\000a\000aPayment is due within 30 days from date of invoice. Late payment is subject to fees of 5% per month.\000a\000aThanks for choosing DEMO - Sliced Invoices | admin@slicedinvoices.com\000a\000aPage 1/1\000a\000aFrom:\000a\000aDEMO - Sliced Invoices\000a\000aSuite 5A-1204\000a\000a123 Somewhere Street\000a\000aYour City AZ 12345\000a\000aadmin@slicedinvoices.com\000a\000aInvoice Number INV-3337\000a\000aOrder Number 12345\000a\000aInvoice Date January 25, 2016\000a\000aDue Date January 31, 2016\000a\000aTotal Due $93.50\000a\000aTo:\000a\000aTest Business\000a\000a123 Somewhere St\000a\000aMelbourne, VIC 3000\000a\000atest@test.com\000a\000aHrs/Qty Service Rate/Price Adjust Sub Total\000a\000a1.00\000aWeb Design\000aThis is a sample description...\000a\000a$85.00 0.00% $85.00\000a\000aSub Total $85.00\000a\000aTax $8.50\000a\000aTotal $93.50\000a\000aANZ Bank\000a\000aACC # 1234 1234\000a\000aBSB # 4321 432 Pa\000aid\000a\000aPDF Invoice Example\000aSliced Invoices\000aExample PDF invoice that was created using the Sli\000a2016-02-04', '[{"label":"Sliced Invoices | admin@slicedinvoices.com","tag":"misc","startPosition":138,"endPosition":180},{"label":"Page 1/1","tag":"misc","startPosition":182,"endPosition":190},{"label":"Sliced Invoices","tag":"misc","startPosition":206,"endPosition":221},{"label":"Date January","tag":"person","startPosition":359,"endPosition":371},{"label":"Due Date January","tag":"person","startPosition":382,"endPosition":398},{"label":"Total Due $","tag":"misc","startPosition":409,"endPosition":420},{"label":"Price Adjust Sub Total","tag":"misc","startPosition":522,"endPosition":544},{"label":"1.00 Web Design This","tag":"misc","startPosition":546,"endPosition":566},{"label":"Sub Total $","tag":"misc","startPosition":616,"endPosition":627},{"label":"Tax $","tag":"misc","startPosition":634,"endPosition":639},{"label":"ANZ Bank","tag":"organization","startPosition":659,"endPosition":667},{"label":"Pa id","tag":"misc","startPosition":701,"endPosition":706},{"label":"PDF Invoice Example Sliced","tag":"misc","startPosition":708,"endPosition":734},{"label":"Sliced","tag":"misc","startPosition":138,"endPosition":144},{"label":"Invoices","tag":"misc","startPosition":145,"endPosition":153},{"label":"|","tag":"misc","startPosition":154,"endPosition":155},{"label":"admin@slicedinvoices.com","tag":"misc","startPosition":156,"endPosition":180},{"label":"Page","tag":"misc","startPosition":182,"endPosition":186},{"label":"1/1","tag":"misc","startPosition":187,"endPosition":190},{"label":"From","tag":"misc","startPosition":192,"endPosition":196},{"label":"Sliced","tag":"misc","startPosition":206,"endPosition":212},{"label":"Invoices","tag":"misc","startPosition":213,"endPosition":221},{"label":"Suite","tag":"misc","startPosition":223,"endPosition":228},{"label":"Street","tag":"organization","startPosition":252,"endPosition":258},{"label":"Your","tag":"organization","startPosition":260,"endPosition":264},{"label":"Date","tag":"person","startPosition":359,"endPosition":363},{"label":"January","tag":"person","startPosition":364,"endPosition":371},{"label":"Due","tag":"person","startPosition":382,"endPosition":385},{"label":"Date","tag":"person","startPosition":386,"endPosition":390},{"label":"January","tag":"person","startPosition":391,"endPosition":398},{"label":"Total","tag":"misc","startPosition":409,"endPosition":414},{"label":"Due","tag":"misc","startPosition":415,"endPosition":418},{"label":"$","tag":"misc","startPosition":419,"endPosition":420},{"label":"St","tag":"location","startPosition":461,"endPosition":463},{"label":"Melbourne","tag":"location","startPosition":465,"endPosition":474},{"label":"Price","tag":"misc","startPosition":522,"endPosition":527},{"label":"Adjust","tag":"misc","startPosition":528,"endPosition":534},{"label":"Sub","tag":"misc","startPosition":535,"endPosition":538},{"label":"Total","tag":"misc","startPosition":539,"endPosition":544},{"label":"1.00","tag":"misc","startPosition":546,"endPosition":550},{"label":"Web","tag":"misc","startPosition":551,"endPosition":554},{"label":"Design","tag":"misc","startPosition":555,"endPosition":561},{"label":"This","tag":"misc","startPosition":562,"endPosition":566},{"label":"$","tag":"misc","startPosition":595,"endPosition":596},{"label":"$","tag":"misc","startPosition":608,"endPosition":609},{"label":"85.00","tag":"misc","startPosition":609,"endPosition":614},{"label":"Sub","tag":"misc","startPosition":616,"endPosition":619},{"label":"Total","tag":"misc","startPosition":620,"endPosition":625},{"label":"$","tag":"misc","startPosition":626,"endPosition":627},{"label":"85.00","tag":"misc","startPosition":627,"endPosition":632},{"label":"Tax","tag":"misc","startPosition":634,"endPosition":637},{"label":"$","tag":"misc","startPosition":638,"endPosition":639},{"label":"$","tag":"misc","startPosition":651,"endPosition":652},{"label":"ANZ","tag":"organization","startPosition":659,"endPosition":662},{"label":"Bank","tag":"organization","startPosition":663,"endPosition":667},{"label":"ACC","tag":"organization","startPosition":669,"endPosition":672},{"label":"Pa","tag":"misc","startPosition":701,"endPosition":703},{"label":"id","tag":"misc","startPosition":704,"endPosition":706},{"label":"PDF","tag":"misc","startPosition":708,"endPosition":711},{"label":"Invoice","tag":"misc","startPosition":712,"endPosition":719},{"label":"Example","tag":"misc","startPosition":720,"endPosition":727},{"label":"Sliced","tag":"misc","startPosition":728,"endPosition":734},{"label":"admin@slicedinvoices.com","tag":"email","startPosition":156,"endPosition":180},{"label":"admin@slicedinvoices.com","tag":"email","startPosition":280,"endPosition":304},{"label":"test@test.com","tag":"email","startPosition":486,"endPosition":499},{"label":"2016-01-25","tag":"date","startPosition":364,"endPosition":374},{"label":"2016-01-31","tag":"date","startPosition":391,"endPosition":401}]', '{"proposals":[{"proposalType":"docdate","values":[{"ref":{"id":"2016-01-25","name":"2016-01-25"},"origin":[{"label":"January 25, 2016","tag":"date","startPosition":364,"endPosition":374}],"weight":0.0753623188405797},{"ref":{"id":"2016-01-31","name":"2016-01-31"},"origin":[{"label":"January 31, 2016","tag":"date","startPosition":391,"endPosition":401}],"weight":0.08095238095238094}]}]}', 1, 'deu');          
+INSERT INTO "public"."attachmentmeta" VALUES
+('4SDQngEFYuK-tb9xAachZSt-LNCrE36NFRr-U8avxFCW9A4', U&'Derek Jeter\000a\000a123 Elm Ave.\000a\000aTreesville, ON M1N 2P3\000a\000aNovember 7, 2016\000a\000aDerek Jeter, 123 Elm Ave., Treesville, ON M1N 2P3, November 7, 2016\000a\000aMr. M. Leaf\000a\000aChief of Syrup Production\000a\000aOld Sticky Pancake Company\000a\000a456 Maple Lane\000a\000aForest, ON 7W8 9Y0\000a\000aHemptown, September 3, 2019\000a\000aDear Mr. Leaf,\000a\000aLet me begin by thanking you for your past contributions to our Little League baseball\000a\000ateam. Your sponsorship aided in the purchase of ten full uniforms and several pieces of\000a\000abaseball equipment for last year\2019s season.\000a\000aNext month, our company is planning an employee appreciation pancake breakfast hon-\000a\000aoring retired employees for their past years of service and present employees for their\000a\000aloyalty and dedication in spite of the current difficult economic conditions.\000a\000aWe would like to place an order with your company for 25 pounds of pancake mix and\000a\000afive gallons of maple syrup. We hope you will be able to provide these products in the\000a\000abulk quantities we require.\000a\000aAs you are a committed corporate sponsor and long-time associate, we hope that you\000a\000awill be able to join us for breakfast on December 12, 2016.\000a\000aRespectfully yours,\000a\000aDerek Jeter\000a\000aDerek Jeter\000a2019-09-03', '[{"label":"Derek Jeter","tag":"person","startPosition":0,"endPosition":11},{"label":"Derek Jeter","tag":"person","startPosition":69,"endPosition":80},{"label":"M. Leaf","tag":"person","startPosition":142,"endPosition":149},{"label":"Syrup Production","tag":"organization","startPosition":160,"endPosition":176},{"label":"Old Sticky Pancake Company","tag":"organization","startPosition":178,"endPosition":204},{"label":"456 Maple Lane","tag":"organization","startPosition":206,"endPosition":220},{"label":"Let me begin by thanking you for your past contributions to our Little League baseball","tag":"misc","startPosition":287,"endPosition":373},{"label":"their past years of service and present employees for their","tag":"organization","startPosition":621,"endPosition":680},{"label":"Derek Jeter","tag":"person","startPosition":1128,"endPosition":1139},{"label":"Derek Jeter","tag":"person","startPosition":1141,"endPosition":1152},{"label":"Derek","tag":"person","startPosition":0,"endPosition":5},{"label":"Jeter","tag":"person","startPosition":6,"endPosition":11},{"label":"Elm","tag":"location","startPosition":17,"endPosition":20},{"label":"Derek","tag":"person","startPosition":69,"endPosition":74},{"label":"Jeter","tag":"person","startPosition":75,"endPosition":80},{"label":"Elm","tag":"location","startPosition":86,"endPosition":89},{"label":"M.","tag":"person","startPosition":142,"endPosition":144},{"label":"Leaf","tag":"person","startPosition":145,"endPosition":149},{"label":"Syrup","tag":"organization","startPosition":160,"endPosition":165},{"label":"Production","tag":"organization","startPosition":166,"endPosition":176},{"label":"Old","tag":"organization","startPosition":178,"endPosition":181},{"label":"Sticky","tag":"organization","startPosition":182,"endPosition":188},{"label":"Pancake","tag":"organization","startPosition":189,"endPosition":196},{"label":"Company","tag":"organization","startPosition":197,"endPosition":204},{"label":"456","tag":"organization","startPosition":206,"endPosition":209},{"label":"Maple","tag":"organization","startPosition":210,"endPosition":215},{"label":"Lane","tag":"organization","startPosition":216,"endPosition":220},{"label":"Forest","tag":"organization","startPosition":222,"endPosition":228},{"label":"Leaf","tag":"person","startPosition":280,"endPosition":284},{"label":"Let","tag":"misc","startPosition":287,"endPosition":290},{"label":"me","tag":"misc","startPosition":291,"endPosition":293},{"label":"begin","tag":"misc","startPosition":294,"endPosition":299},{"label":"by","tag":"misc","startPosition":300,"endPosition":302},{"label":"thanking","tag":"misc","startPosition":303,"endPosition":311},{"label":"you","tag":"misc","startPosition":312,"endPosition":315},{"label":"for","tag":"misc","startPosition":316,"endPosition":319},{"label":"your","tag":"misc","startPosition":320,"endPosition":324},{"label":"past","tag":"misc","startPosition":325,"endPosition":329},{"label":"contributions","tag":"misc","startPosition":330,"endPosition":343},{"label":"to","tag":"misc","startPosition":344,"endPosition":346},{"label":"our","tag":"misc","startPosition":347,"endPosition":350},{"label":"Little","tag":"misc","startPosition":351,"endPosition":357},{"label":"League","tag":"misc","startPosition":358,"endPosition":364},{"label":"baseball","tag":"misc","startPosition":365,"endPosition":373},{"label":"team","tag":"misc","startPosition":375,"endPosition":379},{"label":"company","tag":"organization","startPosition":524,"endPosition":531},{"label":"pancake","tag":"organization","startPosition":569,"endPosition":576},{"label":"their","tag":"organization","startPosition":621,"endPosition":626},{"label":"past","tag":"organization","startPosition":627,"endPosition":631},{"label":"years","tag":"organization","startPosition":632,"endPosition":637},{"label":"of","tag":"organization","startPosition":638,"endPosition":640},{"label":"service","tag":"organization","startPosition":641,"endPosition":648},{"label":"and","tag":"organization","startPosition":649,"endPosition":652},{"label":"present","tag":"organization","startPosition":653,"endPosition":660},{"label":"employees","tag":"organization","startPosition":661,"endPosition":670},{"label":"for","tag":"organization","startPosition":671,"endPosition":674},{"label":"their","tag":"organization","startPosition":675,"endPosition":680},{"label":"loyalty","tag":"organization","startPosition":682,"endPosition":689},{"label":"company","tag":"organization","startPosition":803,"endPosition":810},{"label":"pancake","tag":"organization","startPosition":828,"endPosition":835},{"label":"Derek","tag":"person","startPosition":1128,"endPosition":1133},{"label":"Jeter","tag":"person","startPosition":1134,"endPosition":1139},{"label":"Derek","tag":"person","startPosition":1141,"endPosition":1146},{"label":"Jeter","tag":"person","startPosition":1147,"endPosition":1152},{"label":"2016-11-07","tag":"date","startPosition":51,"endPosition":61},{"label":"2016-11-07","tag":"date","startPosition":120,"endPosition":130},{"label":"2019-09-03","tag":"date","startPosition":252,"endPosition":263},{"label":"2016-12-12","tag":"date","startPosition":1087,"endPosition":1098}]', '{"proposals":[{"proposalType":"corrperson","values":[{"ref":{"id":"83XuNaLvbMt-E3ocm83uYtt-VoLgToV7gxz-rYhG6ZDZmB6","name":"Marcus Leaf"},"origin":[{"label":"Leaf","tag":"person","startPosition":145,"endPosition":149}],"weight":0.024935511607910577}]},{"proposalType":"corrorg","values":[{"ref":{"id":"85CGijc6q6q-Vj1dZXCPGcK-rpDK7MKVrRz-xyNsSbEbuJy","name":"Pancake Company"},"origin":[{"label":"Company","tag":"organization","startPosition":197,"endPosition":204},{"label":"Pancake","tag":"organization","startPosition":189,"endPosition":196}],"weight":0.03250214961306965}]},{"proposalType":"concperson","values":[{"ref":{"id":"2vhk349kjyK-LYQWRjTPLro-E4hCRgJyGC3-BMqG3bcVw4y","name":"Derek Jeter"},"origin":[{"label":"Derek Jeter","tag":"person","startPosition":0,"endPosition":11}],"weight":0.0}]},{"proposalType":"docdate","values":[{"ref":{"id":"2016-11-07","name":"2016-11-07"},"origin":[{"label":"November 7, 2016","tag":"date","startPosition":51,"endPosition":61}],"weight":0.007308684436801376},{"ref":{"id":"2016-11-07","name":"2016-11-07"},"origin":[{"label":"November 7, 2016","tag":"date","startPosition":120,"endPosition":130}],"weight":0.017196904557179708},{"ref":{"id":"2019-09-03","name":"2019-09-03"},"origin":[{"label":"September 3, 2019","tag":"date","startPosition":252,"endPosition":263}],"weight":0.03611349957007738},{"ref":{"id":"2016-12-12","name":"2016-12-12"},"origin":[{"label":"December 12, 2016","tag":"date","startPosition":1087,"endPosition":1098}],"weight":0.3115505875609057}]}]}', 1, 'deu');
 CREATE CACHED TABLE "public"."classifier_setting"(
-    "cid" VARCHAR(254) NOT NULL,
-    "schedule" VARCHAR(254) NOT NULL,
-    "item_count" INT NOT NULL,
+    "cid" CHARACTER VARYING(254) NOT NULL,
+    "schedule" CHARACTER VARYING(254) NOT NULL,
+    "item_count" INTEGER NOT NULL,
     "created" TIMESTAMP NOT NULL,
-    "categories" TEXT NOT NULL,
-    "category_list_type" VARCHAR(254) NOT NULL
-);   
+    "categories" CHARACTER VARYING NOT NULL,
+    "category_list_type" CHARACTER VARYING(254) NOT NULL
+);    
 ALTER TABLE "public"."classifier_setting" ADD CONSTRAINT "public"."CONSTRAINT_B9" PRIMARY KEY("cid");          
 -- 1 +/- SELECT COUNT(*) FROM public.classifier_setting;       
 INSERT INTO "public"."classifier_setting" VALUES
 ('demo', '*-01/3-01 01:00:00', 0, TIMESTAMP '2021-01-03 21:35:17.933', '["doctype"]', 'whitelist');           
 CREATE CACHED TABLE "public"."periodic_task"(
-    "id" VARCHAR(254) NOT NULL,
+    "id" CHARACTER VARYING(254) NOT NULL,
     "enabled" BOOLEAN NOT NULL,
-    "task" VARCHAR(254) NOT NULL,
-    "group_" VARCHAR(254) NOT NULL,
-    "args" TEXT NOT NULL,
-    "subject" VARCHAR(254) NOT NULL,
-    "submitter" VARCHAR(254) NOT NULL,
-    "priority" INT NOT NULL,
-    "worker" VARCHAR(254),
+    "task" CHARACTER VARYING(254) NOT NULL,
+    "group_" CHARACTER VARYING(254) NOT NULL,
+    "args" CHARACTER VARYING NOT NULL,
+    "subject" CHARACTER VARYING(254) NOT NULL,
+    "submitter" CHARACTER VARYING(254) NOT NULL,
+    "priority" INTEGER NOT NULL,
+    "worker" CHARACTER VARYING(254),
     "marked" TIMESTAMP,
-    "timer" VARCHAR(254) NOT NULL,
+    "timer" CHARACTER VARYING(254) NOT NULL,
     "nextrun" TIMESTAMP NOT NULL,
     "created" TIMESTAMP NOT NULL,
-    "summary" VARCHAR(254)
-); 
+    "summary" CHARACTER VARYING(254)
+);
 ALTER TABLE "public"."periodic_task" ADD CONSTRAINT "public"."CONSTRAINT_2" PRIMARY KEY("id"); 
 -- 2 +/- SELECT COUNT(*) FROM public.periodic_task;            
 INSERT INTO "public"."periodic_task" VALUES
 ('docspell-houskeeping', TRUE, 'housekeeping', 'docspell-system', '{}', 'Docspell house-keeping', 'docspell-system', 0, NULL, TIMESTAMP '2021-07-13 21:06:09.222925', 'Sun *-*-* 00:00:00', TIMESTAMP '2021-07-18 00:00:00', TIMESTAMP '2021-01-03 20:49:33.897', NULL),
 ('CdqeBRkD5Ft-ubJkLhMDTa5-K7k2ix6mqRM-Yu2Y7CGuVK7', TRUE, 'learn-classifier', 'demo', '{"collective":"demo"}', 'learn-classifier: learn-classifier', 'learn-classifier', 0, NULL, TIMESTAMP '2021-07-13 21:02:59.231627', '*-01/3-01 01:00:00', TIMESTAMP '2021-10-01 01:00:00', TIMESTAMP '2021-01-03 21:35:17.958', NULL);              
-CREATE INDEX "public"."periodic_task_nextrun_idx" ON "public"."periodic_task"("nextrun");      
-CREATE INDEX "public"."periodic_task_worker_idx" ON "public"."periodic_task"("worker");        
-DROP TABLE IF EXISTS SYSTEM_LOB_STREAM;        
-CALL SYSTEM_COMBINE_BLOB(-1);  
-DROP ALIAS IF EXISTS SYSTEM_COMBINE_CLOB;      
-DROP ALIAS IF EXISTS SYSTEM_COMBINE_BLOB;      
+CREATE INDEX "public"."periodic_task_nextrun_idx" ON "public"."periodic_task"("nextrun" NULLS FIRST);          
+CREATE INDEX "public"."periodic_task_worker_idx" ON "public"."periodic_task"("worker" NULLS FIRST);            
 ALTER TABLE "public"."tagitem" ADD CONSTRAINT "public"."CONSTRAINT_A3" UNIQUE("itemid", "tid");
 ALTER TABLE "public"."custom_field_value" ADD CONSTRAINT "public"."CONSTRAINT_6FD5B" UNIQUE("item_id", "field");               
 ALTER TABLE "public"."classifier_model" ADD CONSTRAINT "public"."CONSTRAINT_BC7B9" UNIQUE("cid", "name");      
diff --git a/project/Dependencies.scala b/project/Dependencies.scala
index 62b26af7..5a4ab400 100644
--- a/project/Dependencies.scala
+++ b/project/Dependencies.scala
@@ -19,9 +19,9 @@ object Dependencies {
   val DoobieVersion = "1.0.0-RC2"
   val EmilVersion = "0.12.0"
   val FlexmarkVersion = "0.64.0"
-  val FlywayVersion = "8.5.13"
+  val FlywayVersion = "9.1.3"
   val Fs2Version = "3.2.12"
-  val H2Version = "1.4.200"
+  val H2Version = "2.1.214"
   val Http4sVersion = "0.23.14"
   val Icu4jVersion = "71.1"
   val JavaOtpVersion = "0.4.0"
diff --git a/tools/h2-util.sh b/tools/h2-util.sh
new file mode 100755
index 00000000..ba40059f
--- /dev/null
+++ b/tools/h2-util.sh
@@ -0,0 +1,131 @@
+#!/usr/bin/env bash
+#
+# Create and restore dumps from h2 databases.
+#
+# H2 dumps should be created using the same (or compatible) version of
+# h2 that is used to run the db.
+#
+# Docspell 0.38.0 and earlier uses H2 1.4.x. From Docspell 0.39.0
+# onwards it's 2.1.x.
+#
+# Set the H2 version via an environment variable 'H2_VERSION'.
+# Additionally a user and password are required, set these via env
+# variables H2_USER and H2_PASSWORD. (or modify this script)
+#
+# Creating/restoring a dump requires to specify the database file. H2
+# appends suffixes like '.mv.db' and '.trace.db', but here the base
+# file is required. So if you see a file 'mydb.mv.db', specify here
+# 'mydb' only or a complete JDBC url.
+#
+# The target file or target db must not exist.
+#
+# The dump file contains (H2 specific) SQL that recreates the
+# database. It can be modified if necessary. This SQL script can then
+# be used to restore the database even to a newer version of H2.
+
+set -e
+
+h2_user=${H2_USER:-"sa"}
+h2_password=${H2_PASSWORD:-""}
+h2_version=${H2_VERSION:-"1.4.200"}
+#h2_version="2.1.214"
+
+h2_jar_url="https://search.maven.org/remotecontent?filepath=com/h2database/h2/$h2_version/h2-$h2_version.jar"
+h2_jdbc_opts=";MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE"
+
+tempdir=$(mktemp -d "h2-util.XXXXX")
+trap "rm -rf $tempdir" EXIT
+
+
+prepare() {
+    echo "Prepare for h2 version: $h2_version"
+    curl -sSL -o $tempdir/h2.jar "$h2_jar_url"
+}
+
+create_dump() {
+    src_db_file="$1"
+    target_file="$2"
+
+    jdbc_url=""
+    if [[ "$src_db_file" =~ jdbc:h2:.* ]]; then
+        jdbc_url="$src_db_file"
+    elif [ -r "$src_db_file.mv.db" ]; then
+        jdbc_url="jdbc:h2://$(realpath "$src_db_file")$h2_jdbc_opts"
+    else
+        echo "Invalid database. Either specify the file or a full JDBC url."
+        echo "Usage: $0 dump <db-file|jdbc_url> <target-file>"
+        exit 1
+    fi
+
+    if [ -z "$target_file" ]; then
+        echo "No target file given"
+        echo "Usage: $0 dump <db-file|jdbc_url> <target-file>"
+        exit 1
+    fi
+    if [ -r "$target_file" ]; then
+        echo "The target file '$target_file' already exists!"
+        echo "Usage: $0 dump <db-file|jdbc_url> <target-file>"
+        exit 1
+    fi
+
+    echo "Creating a dump: $jdbc_url -> $target_file"
+    prepare
+    java -cp "$tempdir/h2.jar" org.h2.tools.Script \
+         -url "$jdbc_url" \
+         -user "$h2_user" \
+         -password "$h2_password" \
+         -script "$target_file"
+}
+
+restore_dump() {
+    backup_file="$1"
+    target_db_file="$2"
+
+    jdbc_url=""
+    if [[ "$target_db_file" =~ jdbc:h2:.* ]]; then
+        jdbc_url="$target_db_file"
+    elif ! [ -r "$target_db_file.mv.db" ]; then
+        jdbc_url="jdbc:h2://$(realpath "$target_db_file")$h2_jdbc_opts"
+    else
+        echo "Invalid database or it does already exist. Either specify the file or a full JDBC url."
+        echo "Usage: $0 restore <dump-file> <db-file|jdbc_url>"
+        exit 1
+    fi
+
+    if [ -z "$backup_file" ]; then
+        echo "No dump file given"
+        echo "Usage: $0 restore <dump-file> <db-file|jdbc_url>"
+        exit 1
+    fi
+    if ! [ -r "$backup_file" ]; then
+        echo "The dump file '$backup_file' doesn't exists!"
+        echo "Usage: $0 dump <db-file|jdbc_url> <target-file>"
+        exit 1
+    fi
+
+    echo "Restore a dump: $backup_file -> $jdbc_url"
+    prepare
+    java -cp "$tempdir/h2.jar" org.h2.tools.RunScript \
+         -url "$jdbc_url" \
+         -user "$h2_user" \
+         -password "$h2_password" \
+         -script "$backup_file" \
+         -options FROM_1X
+}
+
+case "$1" in
+    dump)
+        shift
+        create_dump "$@"
+        ;;
+
+    restore)
+        echo "Restoring from a file"
+        shift
+        restore_dump "$@"
+        ;;
+
+    *)
+        echo "Invalid command. One of: dump, restore"
+        exit 1
+esac

From e39ddc7c17600cfba142f7f3c995258f3d30a96d Mon Sep 17 00:00:00 2001
From: eikek <eike.kettner@posteo.de>
Date: Fri, 12 Aug 2022 12:59:13 +0200
Subject: [PATCH 2/6] Rename column 'value' to 'value_'

In sql 'value' is a reserved word and should not be used (unless
quoted). Postgresql and MariaDB are ok with it, but the new version of
h2 is now complaining.
---
 .../main/resources/db/migration/h2/V1.39.3__rename_value.sql    | 1 +
 .../resources/db/migration/mariadb/V1.39.3__rename_value.sql    | 1 +
 .../resources/db/migration/postgresql/V1.39.3__rename_value.sql | 1 +
 .../store/src/main/scala/docspell/store/records/RContact.scala  | 2 +-
 4 files changed, 4 insertions(+), 1 deletion(-)
 create mode 100644 modules/store/src/main/resources/db/migration/h2/V1.39.3__rename_value.sql
 create mode 100644 modules/store/src/main/resources/db/migration/mariadb/V1.39.3__rename_value.sql
 create mode 100644 modules/store/src/main/resources/db/migration/postgresql/V1.39.3__rename_value.sql

diff --git a/modules/store/src/main/resources/db/migration/h2/V1.39.3__rename_value.sql b/modules/store/src/main/resources/db/migration/h2/V1.39.3__rename_value.sql
new file mode 100644
index 00000000..3431ffd9
--- /dev/null
+++ b/modules/store/src/main/resources/db/migration/h2/V1.39.3__rename_value.sql
@@ -0,0 +1 @@
+alter table "contact" rename column "value" to "value_";
diff --git a/modules/store/src/main/resources/db/migration/mariadb/V1.39.3__rename_value.sql b/modules/store/src/main/resources/db/migration/mariadb/V1.39.3__rename_value.sql
new file mode 100644
index 00000000..d2744742
--- /dev/null
+++ b/modules/store/src/main/resources/db/migration/mariadb/V1.39.3__rename_value.sql
@@ -0,0 +1 @@
+alter table `contact` rename column `value` to `value_`;
diff --git a/modules/store/src/main/resources/db/migration/postgresql/V1.39.3__rename_value.sql b/modules/store/src/main/resources/db/migration/postgresql/V1.39.3__rename_value.sql
new file mode 100644
index 00000000..3431ffd9
--- /dev/null
+++ b/modules/store/src/main/resources/db/migration/postgresql/V1.39.3__rename_value.sql
@@ -0,0 +1 @@
+alter table "contact" rename column "value" to "value_";
diff --git a/modules/store/src/main/scala/docspell/store/records/RContact.scala b/modules/store/src/main/scala/docspell/store/records/RContact.scala
index e6e79734..350c9ef4 100644
--- a/modules/store/src/main/scala/docspell/store/records/RContact.scala
+++ b/modules/store/src/main/scala/docspell/store/records/RContact.scala
@@ -30,7 +30,7 @@ object RContact {
     val tableName = "contact"
 
     val contactId = Column[Ident]("contactid", this)
-    val value = Column[String]("value", this)
+    val value = Column[String]("value_", this)
     val kind = Column[ContactKind]("kind", this)
     val personId = Column[Ident]("pid", this)
     val orgId = Column[Ident]("oid", this)

From 0a3ac9f121c761f7c1b6cda591b5bb3cbd510bc3 Mon Sep 17 00:00:00 2001
From: eikek <eike.kettner@posteo.de>
Date: Fri, 12 Aug 2022 16:26:20 +0200
Subject: [PATCH 3/6] Add anonymous subselects to query builder

---
 .../main/scala/docspell/store/qb/Select.scala | 21 ++++++++++++-------
 .../scala/docspell/store/qb/SelectExpr.scala  |  2 ++
 .../store/qb/impl/SelectBuilder.scala         |  2 +-
 .../docspell/store/qb/QueryBuilderTest.scala  |  6 ++++--
 4 files changed, 21 insertions(+), 10 deletions(-)

diff --git a/modules/store/src/main/scala/docspell/store/qb/Select.scala b/modules/store/src/main/scala/docspell/store/qb/Select.scala
index 65ec0c6e..7f2e6916 100644
--- a/modules/store/src/main/scala/docspell/store/qb/Select.scala
+++ b/modules/store/src/main/scala/docspell/store/qb/Select.scala
@@ -7,6 +7,7 @@
 package docspell.store.qb
 
 import cats.data.{NonEmptyList => Nel}
+import cats.syntax.option._
 
 import docspell.store.qb.impl.SelectBuilder
 
@@ -23,6 +24,9 @@ sealed trait Select {
   def as(alias: String): SelectExpr.SelectQuery =
     SelectExpr.SelectQuery(this, Some(alias))
 
+  def asSubSelect: SelectExpr.SelectQuery =
+    SelectExpr.SelectQuery(this, None)
+
   /** Adds one or more order-by definitions */
   def orderBy(ob: OrderBy, obs: OrderBy*): Select
 
@@ -71,35 +75,38 @@ sealed trait Select {
 }
 
 object Select {
+  def apply(projection: SelectExpr) =
+    SimpleSelect(false, Nel.of(projection), None, Condition.unit, None)
+
   def apply(projection: Nel[SelectExpr], from: FromExpr) =
-    SimpleSelect(false, projection, from, Condition.unit, None)
+    SimpleSelect(false, projection, from.some, Condition.unit, None)
 
   def apply(projection: SelectExpr, from: FromExpr) =
-    SimpleSelect(false, Nel.of(projection), from, Condition.unit, None)
+    SimpleSelect(false, Nel.of(projection), from.some, Condition.unit, None)
 
   def apply(
       projection: Nel[SelectExpr],
       from: FromExpr,
       where: Condition
-  ) = SimpleSelect(false, projection, from, where, None)
+  ) = SimpleSelect(false, projection, from.some, where, None)
 
   def apply(
       projection: SelectExpr,
       from: FromExpr,
       where: Condition
-  ) = SimpleSelect(false, Nel.of(projection), from, where, None)
+  ) = SimpleSelect(false, Nel.of(projection), from.some, where, None)
 
   def apply(
       projection: Nel[SelectExpr],
       from: FromExpr,
       where: Condition,
       groupBy: GroupBy
-  ) = SimpleSelect(false, projection, from, where, Some(groupBy))
+  ) = SimpleSelect(false, projection, from.some, where, Some(groupBy))
 
   case class SimpleSelect(
       distinctFlag: Boolean,
       projection: Nel[SelectExpr],
-      from: FromExpr,
+      from: Option[FromExpr],
       where: Condition,
       groupBy: Option[GroupBy]
   ) extends Select {
@@ -125,7 +132,7 @@ object Select {
       copy(projection = es)
 
     def changeFrom(f: FromExpr => FromExpr): SimpleSelect =
-      copy(from = f(from))
+      copy(from = from.map(f))
 
     def changeWhere(f: Condition => Condition): SimpleSelect =
       copy(where = f(where))
diff --git a/modules/store/src/main/scala/docspell/store/qb/SelectExpr.scala b/modules/store/src/main/scala/docspell/store/qb/SelectExpr.scala
index 8c922522..1bba08ae 100644
--- a/modules/store/src/main/scala/docspell/store/qb/SelectExpr.scala
+++ b/modules/store/src/main/scala/docspell/store/qb/SelectExpr.scala
@@ -33,6 +33,8 @@ object SelectExpr {
   case class SelectLiteral(value: String, alias: Option[String]) extends SelectExpr {
     def as(a: String): SelectLiteral =
       copy(alias = Some(a))
+    def as(otherCol: Column[_]): SelectExpr =
+      copy(alias = Some(otherCol.name))
   }
 
   case class SelectQuery(query: Select, alias: Option[String]) extends SelectExpr {
diff --git a/modules/store/src/main/scala/docspell/store/qb/impl/SelectBuilder.scala b/modules/store/src/main/scala/docspell/store/qb/impl/SelectBuilder.scala
index e77bfe6f..2f6641dc 100644
--- a/modules/store/src/main/scala/docspell/store/qb/impl/SelectBuilder.scala
+++ b/modules/store/src/main/scala/docspell/store/qb/impl/SelectBuilder.scala
@@ -52,7 +52,7 @@ object SelectBuilder {
 
   def buildSimple(sq: Select.SimpleSelect): Fragment = {
     val f0 = sq.projection.map(selectExpr).reduceLeft(_ ++ comma ++ _)
-    val f1 = fromExpr(sq.from)
+    val f1 = sq.from.map(fromExpr).getOrElse(Fragment.empty)
     val f2 = cond(sq.where)
     val f3 = sq.groupBy.map(groupBy).getOrElse(Fragment.empty)
     f0 ++ f1 ++ f2 ++ f3
diff --git a/modules/store/src/test/scala/docspell/store/qb/QueryBuilderTest.scala b/modules/store/src/test/scala/docspell/store/qb/QueryBuilderTest.scala
index a36afeff..69a63410 100644
--- a/modules/store/src/test/scala/docspell/store/qb/QueryBuilderTest.scala
+++ b/modules/store/src/test/scala/docspell/store/qb/QueryBuilderTest.scala
@@ -50,9 +50,11 @@ class QueryBuilderTest extends FunSuite with TestLoggingConfig {
         )
         assertEquals(11, proj.size)
         from match {
-          case FromExpr.From(_) =>
+          case None =>
             fail("Unexpected from value")
-          case FromExpr.Joined(f, joins) =>
+          case Some(FromExpr.From(_)) =>
+            fail("Unexpected from value")
+          case Some(FromExpr.Joined(f, joins)) =>
             assertEquals(f, FromExpr.From(c))
             assertEquals(2, joins.size)
             joins.head match {

From 5bbe073bf37789d2d02ba4f34ea3412a52febd06 Mon Sep 17 00:00:00 2001
From: eikek <eike.kettner@posteo.de>
Date: Fri, 12 Aug 2022 16:30:32 +0200
Subject: [PATCH 4/6] Fix job query for H2

Unfortunately, the new h2 version has some regressions related to
CTEs. The query selecting the next group failed only for H2 after the
update. The query has been rewritten to not use union on CTE tables.
The weird thing was that the error only occured using bind values and
was not reproducible with "just string" SQL in the h2 console.

The QJobTest are now running on all databases.
---
 .../scala/docspell/scheduler/impl/QJob.scala  |  44 +++----
 .../docspell/scheduler/impl/QJobTest.scala    | 107 ++++++++++--------
 .../scala/docspell/store/records/RJob.scala   |   5 -
 .../scala/docspell/store/DatabaseTest.scala   |  25 +++-
 .../scala/docspell/store/StoreFixture.scala   |  14 ++-
 .../docspell/store/fts/TempFtsOpsTest.scala   |   2 +-
 6 files changed, 109 insertions(+), 88 deletions(-)

diff --git a/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/QJob.scala b/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/QJob.scala
index 91c37804..e56f88d0 100644
--- a/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/QJob.scala
+++ b/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/QJob.scala
@@ -9,13 +9,11 @@ package docspell.scheduler.impl
 import cats.effect.Async
 import cats.implicits._
 import fs2.Stream
-
 import docspell.common._
 import docspell.store.Store
 import docspell.store.qb.DSL._
 import docspell.store.qb._
 import docspell.store.records.{RJob, RJobGroupUse}
-
 import doobie.ConnectionIO
 
 object QJob {
@@ -89,7 +87,7 @@ object QJob {
       res <- job.traverse(j => markJob(j))
     } yield res.map(_.map(_.some)).getOrElse {
       if (group.isDefined)
-        Left(()) // if a group was found, but no job someone else was faster
+        Left(()) // if a group was found but no job, someone else was faster
       else Right(None)
     }
   }
@@ -115,33 +113,27 @@ object QJob {
       val selectAll = Select(JC.group.s, from(JC), stateCond).distinct
     }
 
-    val sql1 =
-      Select(
-        select(min(AllGroups.group).as("g"), lit("0 as n")),
-        from(AllGroups),
-        AllGroups.group > Select(G.group.s, from(G), G.worker === worker)
-      )
-
-    val sql2 =
-      Select(
-        select(min(AllGroups.group).as("g"), lit("1 as n")),
-        from(AllGroups)
-      )
-
-    val gcol = Column[String]("g", TableDef(""))
-    val gnum = Column[Int]("n", TableDef(""))
     val groups =
       withCte(AllGroups -> AllGroups.selectAll)
-        .select(Select(gcol.s, from(union(sql1, sql2), "t0"), gcol.isNull.negate))
-        .orderBy(gnum.asc)
-        .limit(1)
+        .select(
+          Select(
+            coalesce(
+              Select(
+                select(min(AllGroups.group)),
+                from(AllGroups),
+                AllGroups.group > Select(G.group.s, from(G), G.worker === worker)
+              ).asSubSelect,
+              Select(select(min(AllGroups.group)), from(AllGroups)).asSubSelect
+            ).s
+          )
+        )
 
     val frag = groups.build
-    cioLogger.trace(
-      s"nextGroupQuery: $frag  (now=${now.toMillis}, pause=${initialPause.millis})"
-    )
-
-    frag.query[Ident].option
+    cioLogger
+      .trace(
+        s"nextGroupQuery: $frag  (now=${now.toMillis}, pause=${initialPause.millis})"
+      ) *>
+      groups.build.query[Ident].option
   }
 
   private def stuckTriggerValue(t: RJob.Table, initialPause: Duration, now: Timestamp) =
diff --git a/modules/scheduler/impl/src/test/scala/docspell/scheduler/impl/QJobTest.scala b/modules/scheduler/impl/src/test/scala/docspell/scheduler/impl/QJobTest.scala
index 6c78a050..09ee6f1d 100644
--- a/modules/scheduler/impl/src/test/scala/docspell/scheduler/impl/QJobTest.scala
+++ b/modules/scheduler/impl/src/test/scala/docspell/scheduler/impl/QJobTest.scala
@@ -8,18 +8,12 @@ package docspell.scheduler.impl
 
 import java.time.Instant
 import java.util.concurrent.atomic.AtomicLong
-
-import cats.implicits._
-
+import cats.syntax.all._
 import docspell.common._
-import docspell.logging.TestLoggingConfig
-import docspell.store.StoreFixture
+import docspell.store.{DatabaseTest, Db}
 import docspell.store.records.{RJob, RJobGroupUse}
 
-import doobie.implicits._
-import munit._
-
-class QJobTest extends CatsEffectSuite with StoreFixture with TestLoggingConfig {
+class QJobTest extends DatabaseTest {
   private[this] val c = new AtomicLong(0)
 
   private val worker = Ident.unsafe("joex1")
@@ -28,6 +22,11 @@ class QJobTest extends CatsEffectSuite with StoreFixture with TestLoggingConfig
   private val group1 = Ident.unsafe("group1")
   private val group2 = Ident.unsafe("group2")
 
+  override def munitFixtures = h2File ++ mariaDbAll ++ postgresAll
+
+  def createStore(dbms: Db) =
+    dbms.fold(pgStore(), mariaStore(), h2FileStore())
+
   def createJob(group: Ident): RJob =
     RJob.fromJson[Unit](
       Ident.unsafe(s"job-${c.incrementAndGet()}"),
@@ -41,54 +40,66 @@ class QJobTest extends CatsEffectSuite with StoreFixture with TestLoggingConfig
       None
     )
 
-  xa.test("set group must insert or update") { tx =>
-    val res =
-      for {
-        _ <- RJobGroupUse.setGroup(RJobGroupUse(group1, worker)).transact(tx)
-        res <- RJobGroupUse.findGroup(worker).transact(tx)
-      } yield res
+  Db.all.toList.foreach { db =>
+    test(s"set group must insert or update ($db)") {
+      val store = createStore(db)
+      val res =
+        for {
+          _ <- store.transact(RJobGroupUse.setGroup(RJobGroupUse(group1, worker)))
+          res <- store.transact(RJobGroupUse.findGroup(worker))
+        } yield res
 
-    res.assertEquals(Some(group1))
+      res.assertEquals(Some(group1))
+    }
   }
 
-  xa.test("selectNextGroup should return first group on initial state") { tx =>
-    val nextGroup = for {
-      _ <- List(group1, group2, group1, group2, group2)
-        .map(createJob)
-        .map(RJob.insert)
-        .traverse(_.transact(tx))
-      _ <- RJobGroupUse.deleteAll.transact(tx)
-      next <- QJob.selectNextGroup(worker, nowTs, initialPause).transact(tx)
-    } yield next
+  Db.all.toList.foreach { db =>
+    test(s"selectNextGroup should return first group on initial state ($db)") {
+      val store = createStore(db)
+      val nextGroup = for {
+        _ <- List(group1, group2, group1, group2, group2)
+          .map(createJob)
+          .map(RJob.insert)
+          .traverse_(store.transact(_))
+        _ <- store.transact(RJobGroupUse.deleteAll)
+        next <- store.transact(QJob.selectNextGroup(worker, nowTs, initialPause))
+      } yield next
 
-    nextGroup.assertEquals(Some(group1))
+      nextGroup.assertEquals(Some(group1))
+    }
   }
 
-  xa.test("selectNextGroup should return second group on subsequent call (1)") { tx =>
-    val nextGroup = for {
-      _ <- List(group1, group2, group1, group2)
-        .map(createJob)
-        .map(RJob.insert)
-        .traverse(_.transact(tx))
-      _ <- RJobGroupUse.deleteAll.transact(tx)
-      _ <- RJobGroupUse.setGroup(RJobGroupUse(group1, worker)).transact(tx)
-      next <- QJob.selectNextGroup(worker, nowTs, initialPause).transact(tx)
-    } yield next
+  Db.all.toList.foreach { db =>
+    test(s"selectNextGroup should return second group on subsequent call ($db)") {
+      val store = createStore(db)
+      val nextGroup = for {
+        _ <- List(group1, group2, group1, group2)
+          .map(createJob)
+          .map(RJob.insert)
+          .traverse_(store.transact(_))
+        _ <- store.transact(RJobGroupUse.deleteAll)
+        _ <- store.transact(RJobGroupUse.setGroup(RJobGroupUse(group1, worker)))
+        next <- store.transact(QJob.selectNextGroup(worker, nowTs, initialPause))
+      } yield next
 
-    nextGroup.assertEquals(Some(group2))
+      nextGroup.assertEquals(Some(group2))
+    }
   }
 
-  xa.test("selectNextGroup should return second group on subsequent call (2)") { tx =>
-    val nextGroup = for {
-      _ <- List(group1, group2, group1, group2)
-        .map(createJob)
-        .map(RJob.insert)
-        .traverse(_.transact(tx))
-      _ <- RJobGroupUse.deleteAll.transact(tx)
-      _ <- RJobGroupUse.setGroup(RJobGroupUse(group2, worker)).transact(tx)
-      next <- QJob.selectNextGroup(worker, nowTs, initialPause).transact(tx)
-    } yield next
+  Db.all.toList.foreach { db =>
+    test(s"selectNextGroup should return first group on subsequent call ($db)") {
+      val store = createStore(db)
+      val nextGroup = for {
+        _ <- List(group1, group2, group1, group2)
+          .map(createJob)
+          .map(RJob.insert)
+          .traverse_(store.transact(_))
+        _ <- store.transact(RJobGroupUse.deleteAll)
+        _ <- store.transact(RJobGroupUse.setGroup(RJobGroupUse(group2, worker)))
+        next <- store.transact(QJob.selectNextGroup(worker, nowTs, initialPause))
+      } yield next
 
-    nextGroup.assertEquals(Some(group1))
+      nextGroup.assertEquals(Some(group1))
+    }
   }
 }
diff --git a/modules/store/src/main/scala/docspell/store/records/RJob.scala b/modules/store/src/main/scala/docspell/store/records/RJob.scala
index f8b00e8e..9177df06 100644
--- a/modules/store/src/main/scala/docspell/store/records/RJob.scala
+++ b/modules/store/src/main/scala/docspell/store/records/RJob.scala
@@ -300,11 +300,6 @@ object RJob {
   def setProgress(jobId: Ident, perc: Int): ConnectionIO[Int] =
     DML.update(T, T.id === jobId, DML.set(T.progress.setTo(perc)))
 
-  def selectWaiting: ConnectionIO[Option[RJob]] = {
-    val sql = run(select(T.all), from(T), T.state === JobState.waiting)
-    sql.query[RJob].to[Vector].map(_.headOption)
-  }
-
   def selectGroupInState(states: NonEmptyList[JobState]): ConnectionIO[Vector[Ident]] = {
     val sql =
       Select(select(T.group), from(T), T.state.in(states)).orderBy(T.group)
diff --git a/modules/store/src/test/scala/docspell/store/DatabaseTest.scala b/modules/store/src/test/scala/docspell/store/DatabaseTest.scala
index e2e9363e..0eed8ab7 100644
--- a/modules/store/src/test/scala/docspell/store/DatabaseTest.scala
+++ b/modules/store/src/test/scala/docspell/store/DatabaseTest.scala
@@ -7,12 +7,10 @@
 package docspell.store
 
 import java.util.UUID
-
 import cats.effect._
-
+import cats.syntax.option._
 import docspell.common._
 import docspell.logging.TestLoggingConfig
-
 import com.dimafeng.testcontainers.munit.fixtures.TestContainersFixtures
 import com.dimafeng.testcontainers.{
   JdbcDatabaseContainer,
@@ -20,6 +18,7 @@ import com.dimafeng.testcontainers.{
   PostgreSQLContainer
 }
 import doobie._
+import fs2.io.file.{Files, Path}
 import munit.CatsEffectSuite
 import org.testcontainers.utility.DockerImageName
 
@@ -55,6 +54,15 @@ trait DatabaseTest
     }
   )
 
+  lazy val h2FileDataSource = ResourceSuiteLocalFixture(
+    "h2FileDataSource",
+    for {
+      file <- Files[IO].tempFile(Path("target").some, "h2-test-", ".db", None)
+      jdbc = StoreFixture.fileDB(file)
+      res <- StoreFixture.dataSource(jdbc).map(ds => (jdbc, ds))
+    } yield res
+  )
+
   lazy val newH2DataSource = ResourceFixture(for {
     jdbc <- Resource.eval(IO(StoreFixture.memoryDB(UUID.randomUUID().toString)))
     ds <- StoreFixture.dataSource(jdbc)
@@ -84,9 +92,18 @@ trait DatabaseTest
     } yield store
   )
 
+  lazy val h2FileStore = ResourceSuiteLocalFixture(
+    "h2FileStore",
+    for {
+      t <- Resource.eval(IO(h2FileDataSource()))
+      store <- StoreFixture.store(t._2, t._1)
+    } yield store
+  )
+
   def postgresAll = List(postgresCnt, pgDataSource, pgStore)
   def mariaDbAll = List(mariadbCnt, mariaDataSource, mariaStore)
-  def h2All = List(h2DataSource, h2Store)
+  def h2Memory = List(h2DataSource, h2Store)
+  def h2File = List(h2FileDataSource, h2FileStore)
 }
 
 object DatabaseTest {
diff --git a/modules/store/src/test/scala/docspell/store/StoreFixture.scala b/modules/store/src/test/scala/docspell/store/StoreFixture.scala
index d90b8d93..f9631031 100644
--- a/modules/store/src/test/scala/docspell/store/StoreFixture.scala
+++ b/modules/store/src/test/scala/docspell/store/StoreFixture.scala
@@ -7,15 +7,13 @@
 package docspell.store
 
 import javax.sql.DataSource
-
 import cats.effect._
-
 import docspell.common.LenientUri
 import docspell.store.file.{FileRepository, FileRepositoryConfig}
 import docspell.store.impl.StoreImpl
 import docspell.store.migrate.FlywayMigrate
-
 import doobie._
+import fs2.io.file.Path
 import munit._
 import org.h2.jdbcx.{JdbcConnectionPool, JdbcDataSource}
 import org.mariadb.jdbc.MariaDbDataSource
@@ -55,6 +53,15 @@ object StoreFixture {
       ""
     )
 
+  def fileDB(file: Path): JdbcConfig =
+    JdbcConfig(
+      LenientUri.unsafe(
+        s"jdbc:h2:file://${file.absolute.toString};MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE"
+      ),
+      "sa",
+      ""
+    )
+
   def dataSource(jdbc: JdbcConfig): Resource[IO, JdbcConnectionPool] = {
     def jdbcConnPool =
       jdbc.dbms match {
@@ -115,5 +122,4 @@ object StoreFixture {
       case None =>
         IO.raiseError(new Exception(s"Resource not found: $resourceName"))
     }
-
 }
diff --git a/modules/store/src/test/scala/docspell/store/fts/TempFtsOpsTest.scala b/modules/store/src/test/scala/docspell/store/fts/TempFtsOpsTest.scala
index fdb06b2b..83d5006a 100644
--- a/modules/store/src/test/scala/docspell/store/fts/TempFtsOpsTest.scala
+++ b/modules/store/src/test/scala/docspell/store/fts/TempFtsOpsTest.scala
@@ -27,7 +27,7 @@ import doobie._
 class TempFtsOpsTest extends DatabaseTest {
   private[this] val logger = docspell.logging.getLogger[IO]
 
-  override def munitFixtures = postgresAll ++ mariaDbAll ++ h2All
+  override def munitFixtures = postgresAll ++ mariaDbAll ++ h2Memory
 
   def id(str: String): Ident = Ident.unsafe(str)
 

From e42794869f2f92d715b379c8b330a39a21b0e55d Mon Sep 17 00:00:00 2001
From: eikek <eike.kettner@posteo.de>
Date: Fri, 12 Aug 2022 17:28:30 +0200
Subject: [PATCH 5/6] Apply auto-formatting fixes

---
 .../impl/src/main/scala/docspell/scheduler/impl/QJob.scala   | 2 ++
 .../src/test/scala/docspell/scheduler/impl/QJobTest.scala    | 4 +++-
 .../store/src/test/scala/docspell/store/DatabaseTest.scala   | 5 ++++-
 .../store/src/test/scala/docspell/store/StoreFixture.scala   | 5 ++++-
 4 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/QJob.scala b/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/QJob.scala
index e56f88d0..c965fb48 100644
--- a/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/QJob.scala
+++ b/modules/scheduler/impl/src/main/scala/docspell/scheduler/impl/QJob.scala
@@ -9,11 +9,13 @@ package docspell.scheduler.impl
 import cats.effect.Async
 import cats.implicits._
 import fs2.Stream
+
 import docspell.common._
 import docspell.store.Store
 import docspell.store.qb.DSL._
 import docspell.store.qb._
 import docspell.store.records.{RJob, RJobGroupUse}
+
 import doobie.ConnectionIO
 
 object QJob {
diff --git a/modules/scheduler/impl/src/test/scala/docspell/scheduler/impl/QJobTest.scala b/modules/scheduler/impl/src/test/scala/docspell/scheduler/impl/QJobTest.scala
index 09ee6f1d..ff6151d8 100644
--- a/modules/scheduler/impl/src/test/scala/docspell/scheduler/impl/QJobTest.scala
+++ b/modules/scheduler/impl/src/test/scala/docspell/scheduler/impl/QJobTest.scala
@@ -8,10 +8,12 @@ package docspell.scheduler.impl
 
 import java.time.Instant
 import java.util.concurrent.atomic.AtomicLong
+
 import cats.syntax.all._
+
 import docspell.common._
-import docspell.store.{DatabaseTest, Db}
 import docspell.store.records.{RJob, RJobGroupUse}
+import docspell.store.{DatabaseTest, Db}
 
 class QJobTest extends DatabaseTest {
   private[this] val c = new AtomicLong(0)
diff --git a/modules/store/src/test/scala/docspell/store/DatabaseTest.scala b/modules/store/src/test/scala/docspell/store/DatabaseTest.scala
index 0eed8ab7..feaa994e 100644
--- a/modules/store/src/test/scala/docspell/store/DatabaseTest.scala
+++ b/modules/store/src/test/scala/docspell/store/DatabaseTest.scala
@@ -7,10 +7,14 @@
 package docspell.store
 
 import java.util.UUID
+
 import cats.effect._
 import cats.syntax.option._
+import fs2.io.file.{Files, Path}
+
 import docspell.common._
 import docspell.logging.TestLoggingConfig
+
 import com.dimafeng.testcontainers.munit.fixtures.TestContainersFixtures
 import com.dimafeng.testcontainers.{
   JdbcDatabaseContainer,
@@ -18,7 +22,6 @@ import com.dimafeng.testcontainers.{
   PostgreSQLContainer
 }
 import doobie._
-import fs2.io.file.{Files, Path}
 import munit.CatsEffectSuite
 import org.testcontainers.utility.DockerImageName
 
diff --git a/modules/store/src/test/scala/docspell/store/StoreFixture.scala b/modules/store/src/test/scala/docspell/store/StoreFixture.scala
index f9631031..a6696a39 100644
--- a/modules/store/src/test/scala/docspell/store/StoreFixture.scala
+++ b/modules/store/src/test/scala/docspell/store/StoreFixture.scala
@@ -7,13 +7,16 @@
 package docspell.store
 
 import javax.sql.DataSource
+
 import cats.effect._
+import fs2.io.file.Path
+
 import docspell.common.LenientUri
 import docspell.store.file.{FileRepository, FileRepositoryConfig}
 import docspell.store.impl.StoreImpl
 import docspell.store.migrate.FlywayMigrate
+
 import doobie._
-import fs2.io.file.Path
 import munit._
 import org.h2.jdbcx.{JdbcConnectionPool, JdbcDataSource}
 import org.mariadb.jdbc.MariaDbDataSource

From 7233f606afd67f298fbb40e81b6d475f2d7691f4 Mon Sep 17 00:00:00 2001
From: eikek <eike.kettner@posteo.de>
Date: Fri, 12 Aug 2022 17:30:57 +0200
Subject: [PATCH 6/6] Fix dockerfiles

---
 docker/dockerfiles/joex.dockerfile       | 2 +-
 docker/dockerfiles/restserver.dockerfile | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/docker/dockerfiles/joex.dockerfile b/docker/dockerfiles/joex.dockerfile
index 4798f292..f7ba272b 100644
--- a/docker/dockerfiles/joex.dockerfile
+++ b/docker/dockerfiles/joex.dockerfile
@@ -53,7 +53,7 @@ RUN JDKPKG="openjdk11-jre"; \
     qpdf-dev \
     openssl-dev \
     ocrmypdf \
-  && apk add 'zlib=1.2.12-r2' \
+  && apk add 'zlib=1.2.12-r3' \
   && pip3 install --upgrade pip \
   && pip3 install ocrmypdf \
   && curl -Ls $UNO_URL -o /usr/local/bin/unoconv \
diff --git a/docker/dockerfiles/restserver.dockerfile b/docker/dockerfiles/restserver.dockerfile
index d5c01822..362ea7ed 100644
--- a/docker/dockerfiles/restserver.dockerfile
+++ b/docker/dockerfiles/restserver.dockerfile
@@ -8,7 +8,7 @@ RUN JDKPKG="openjdk11-jre"; \
     if [[ $TARGETPLATFORM = linux/arm* ]]; then JDKPKG="openjdk8-jre"; fi; \
     apk update && \
     apk add --no-cache $JDKPKG bash tzdata && \
-    apk add 'zlib=1.2.12-r2'
+    apk add 'zlib=1.2.12-r3'
 
 WORKDIR /opt
 RUN wget ${restserver_url:-https://github.com/eikek/docspell/releases/download/v$version/docspell-restserver-$version.zip} && \