From 04b2867392454b67521a6ab663f68b3daa204133 Mon Sep 17 00:00:00 2001
From: Martin Weise <martin.weise@tuwien.ac.at>
Date: Sat, 5 Oct 2024 06:08:33 +0200
Subject: [PATCH] WIP

---
 dbrepo-metadata-db/1_setup-schema.sql      | 34 ++++-----
 dbrepo-ui/components/table/TableSchema.vue | 80 +++++++++++++++++++++-
 dbrepo-ui/composables/query-service.ts     | 46 ++++++-------
 3 files changed, 118 insertions(+), 42 deletions(-)

diff --git a/dbrepo-metadata-db/1_setup-schema.sql b/dbrepo-metadata-db/1_setup-schema.sql
index 090cc81739..80ff2240a1 100644
--- a/dbrepo-metadata-db/1_setup-schema.sql
+++ b/dbrepo-metadata-db/1_setup-schema.sql
@@ -19,7 +19,7 @@ CREATE TABLE IF NOT EXISTS `mdb_users`
 
 CREATE TABLE IF NOT EXISTS `mdb_images`
 (
-    id            bigint                 NOT NULL AUTO_INCREMENT,
+    id            SERIAL,
     registry      character varying(255) NOT NULL DEFAULT 'docker.io',
     name          character varying(255) NOT NULL,
     version       character varying(255) NOT NULL,
@@ -37,7 +37,7 @@ CREATE TABLE IF NOT EXISTS `mdb_images`
 
 CREATE TABLE IF NOT EXISTS `mdb_containers`
 (
-    id                  bigint                 NOT NULL AUTO_INCREMENT,
+    id                  SERIAL,
     internal_name       character varying(255) NOT NULL,
     name                character varying(255) NOT NULL,
     host                character varying(255) NOT NULL,
@@ -59,7 +59,7 @@ CREATE TABLE IF NOT EXISTS `mdb_containers`
 
 CREATE TABLE IF NOT EXISTS `mdb_data`
 (
-    ID           bigint NOT NULL AUTO_INCREMENT,
+    ID           SERIAL,
     PROVENANCE   text,
     FileEncoding text,
     FileType     character varying(100),
@@ -79,7 +79,7 @@ CREATE TABLE IF NOT EXISTS `mdb_licenses`
 
 CREATE TABLE IF NOT EXISTS `mdb_databases`
 (
-    id             bigint                 NOT NULL AUTO_INCREMENT,
+    id             SERIAL,
     cid            bigint                 NOT NULL,
     name           character varying(255) NOT NULL,
     internal_name  character varying(255) NOT NULL,
@@ -109,7 +109,7 @@ CREATE TABLE IF NOT EXISTS `mdb_databases_subjects`
 
 CREATE TABLE IF NOT EXISTS `mdb_tables`
 (
-    ID              bigint                NOT NULL AUTO_INCREMENT,
+    ID              SERIAL,
     tDBID           bigint                NOT NULL,
     tName           VARCHAR(64)           NOT NULL,
     internal_name   VARCHAR(64)           NOT NULL,
@@ -169,7 +169,7 @@ CREATE TABLE IF NOT EXISTS `mdb_columns`
 
 CREATE TABLE IF NOT EXISTS `mdb_columns_enums`
 (
-    id        bigint                 NOT NULL AUTO_INCREMENT,
+    id        SERIAL,
     column_id bigint                 NOT NULL,
     value     CHARACTER VARYING(255) NOT NULL,
     FOREIGN KEY (column_id) REFERENCES mdb_columns (ID) ON DELETE CASCADE,
@@ -178,7 +178,7 @@ CREATE TABLE IF NOT EXISTS `mdb_columns_enums`
 
 CREATE TABLE IF NOT EXISTS `mdb_columns_sets`
 (
-    id        bigint                 NOT NULL AUTO_INCREMENT,
+    id        SERIAL,
     column_id bigint                 NOT NULL,
     value     CHARACTER VARYING(255) NOT NULL,
     FOREIGN KEY (column_id) REFERENCES mdb_columns (ID) ON DELETE CASCADE,
@@ -277,7 +277,7 @@ CREATE TABLE IF NOT EXISTS `mdb_constraints_checks`
 
 CREATE TABLE IF NOT EXISTS `mdb_concepts`
 (
-    id          bigint       NOT NULL AUTO_INCREMENT,
+    id          SERIAL,
     uri         text         not null,
     name        VARCHAR(255) null,
     description TEXT         null,
@@ -288,7 +288,7 @@ CREATE TABLE IF NOT EXISTS `mdb_concepts`
 
 CREATE TABLE IF NOT EXISTS `mdb_units`
 (
-    id          bigint       NOT NULL AUTO_INCREMENT,
+    id          SERIAL,
     uri         text         not null,
     name        VARCHAR(255) null,
     description TEXT         null,
@@ -317,7 +317,7 @@ CREATE TABLE IF NOT EXISTS `mdb_columns_units`
 
 CREATE TABLE IF NOT EXISTS `mdb_view`
 (
-    id            bigint                NOT NULL AUTO_INCREMENT,
+    id            SERIAL,
     vdbid         bigint                NOT NULL,
     vName         VARCHAR(64)           NOT NULL,
     internal_name VARCHAR(64)           NOT NULL,
@@ -335,7 +335,7 @@ CREATE TABLE IF NOT EXISTS `mdb_view`
 
 CREATE TABLE IF NOT EXISTS `mdb_banner_messages`
 (
-    id            bigint                            NOT NULL AUTO_INCREMENT,
+    id            SERIAL,
     type          ENUM ('ERROR', 'WARNING', 'INFO') NOT NULL default 'INFO',
     message       TEXT                              NOT NULL,
     link          TEXT                              NULL,
@@ -347,7 +347,7 @@ CREATE TABLE IF NOT EXISTS `mdb_banner_messages`
 
 CREATE TABLE IF NOT EXISTS `mdb_ontologies`
 (
-    id              bigint     NOT NULL AUTO_INCREMENT,
+    id              SERIAL,
     prefix          VARCHAR(8) NOT NULL,
     uri             TEXT       NOT NULL,
     uri_pattern     TEXT,
@@ -417,7 +417,7 @@ CREATE TABLE IF NOT EXISTS `mdb_identifier_licenses`
 
 CREATE TABLE IF NOT EXISTS `mdb_identifier_titles`
 (
-    id         bigint NOT NULL AUTO_INCREMENT,
+    id         SERIAL,
     pid        bigint NOT NULL,
     title      text   NOT NULL,
     title_type ENUM ('ALTERNATIVE_TITLE', 'SUBTITLE', 'TRANSLATED_TITLE', 'OTHER'),
@@ -428,7 +428,7 @@ CREATE TABLE IF NOT EXISTS `mdb_identifier_titles`
 
 CREATE TABLE IF NOT EXISTS `mdb_identifier_funders`
 (
-    id                     bigint       NOT NULL AUTO_INCREMENT,
+    id                     SERIAL,
     pid                    bigint       NOT NULL,
     funder_name            VARCHAR(255) NOT NULL,
     funder_identifier      TEXT,
@@ -443,7 +443,7 @@ CREATE TABLE IF NOT EXISTS `mdb_identifier_funders`
 
 CREATE TABLE IF NOT EXISTS `mdb_identifier_descriptions`
 (
-    id               bigint NOT NULL AUTO_INCREMENT,
+    id               SERIAL,
     pid              bigint NOT NULL,
     description      text   NOT NULL,
     description_type ENUM ('ABSTRACT', 'METHODS', 'SERIES_INFORMATION', 'TABLE_OF_CONTENTS', 'TECHNICAL_INFO', 'OTHER'),
@@ -454,7 +454,7 @@ CREATE TABLE IF NOT EXISTS `mdb_identifier_descriptions`
 
 CREATE TABLE IF NOT EXISTS `mdb_related_identifiers`
 (
-    id       bigint       NOT NULL AUTO_INCREMENT,
+    id       SERIAL,
     pid      bigint       NOT NULL,
     value    varchar(255) NOT NULL,
     type     varchar(255) NOT NULL,
@@ -466,7 +466,7 @@ CREATE TABLE IF NOT EXISTS `mdb_related_identifiers`
 
 CREATE TABLE IF NOT EXISTS `mdb_identifier_creators`
 (
-    id                                bigint       NOT NULL AUTO_INCREMENT,
+    id                                SERIAL,
     pid                               bigint       NOT NULL,
     given_names                       text,
     family_name                       text,
diff --git a/dbrepo-ui/components/table/TableSchema.vue b/dbrepo-ui/components/table/TableSchema.vue
index da30905fa3..bacf321f9e 100644
--- a/dbrepo-ui/components/table/TableSchema.vue
+++ b/dbrepo-ui/components/table/TableSchema.vue
@@ -68,14 +68,20 @@
             @focusout="formatValues(c)" />
         </v-col>
         <v-col
-          v-if="defaultSize(c) !== false"
+          v-if="defaultSize(c) !== false || hasMinSize(c) || hasMaxSize(c)"
           cols="1">
           <v-text-field
             v-model.number="c.size"
             type="number"
             required
+            :min="hasMinSize(c) ? minSize(c) : null"
+            :max="hasMaxSize(c) ? maxSize(c) : null"
+            :step="sizeSteps(c)"
+            :hint="sizeHint(c)"
+            :clearable="!optionalSize(c)"
+            persistent-hint
             :variant="inputVariant"
-            :rules="[v => (v !== null && v !== '') || $t('validation.required')]"
+            :rules="[v => !(!defaultSize(c) && (v === null || v === '')) || $t('validation.required')]"
             :error-messages="sizeErrorMessages(c)"
             :label="$t('pages.table.subpages.schema.size.label')" />
         </v-col>
@@ -331,6 +337,76 @@ export default {
       }
       return filter[0].defaultSize
     },
+    requiredSize (column) {
+      const filter = this.columnTypes.filter(t => t.value === column.type)
+      if (!filter || filter.length === 0) {
+        return false
+      }
+      if (filter[0].requiredSize === undefined || filter[0].requiredSize === null) {
+        return false
+      }
+      return filter[0].requiredSize
+    },
+    hasMinSize (column) {
+      const filter = this.columnTypes.filter(t => t.value === column.type)
+      if (!filter || filter.length === 0) {
+        return false
+      }
+      return filter[0].minSize !== undefined
+    },
+    minSize (column) {
+      const filter = this.columnTypes.filter(t => t.value === column.type)
+      if (!filter || filter.length === 0) {
+        return false
+      }
+      if (filter[0].minSize === undefined || filter[0].minSize === null) {
+        return false
+      }
+      return filter[0].minSize
+    },
+    hasMaxSize (column) {
+      const filter = this.columnTypes.filter(t => t.value === column.type)
+      if (!filter || filter.length === 0) {
+        return false
+      }
+      return filter[0].maxSize !== undefined
+    },
+    maxSize (column) {
+      const filter = this.columnTypes.filter(t => t.value === column.type)
+      if (!filter || filter.length === 0) {
+        return false
+      }
+      if (filter[0].maxSize === undefined || filter[0].maxSize === null) {
+        return false
+      }
+      return filter[0].maxSize
+    },
+    sizeSteps (column) {
+      const filter = this.columnTypes.filter(t => t.value === column.type)
+      if (!filter || filter.length === 0) {
+        return null
+      }
+      if (filter[0].sizeSteps === undefined || filter[0].sizeSteps === null) {
+        return 1
+      }
+      return filter[0].sizeSteps
+    },
+    sizeHint (column) {
+      let hint = ''
+      if (this.hasMinSize(column)) {
+        hint += `min. ${this.minSize(column)}`
+      }
+      if (this.hasMaxSize(column)) {
+        if (hint.length > 0) {
+          hint += ', '
+        }
+        hint += `max. ${this.maxSize(column)}`
+      }
+      if (!this.defaultSize(column)) {
+        hint += ' (optional)'
+      }
+      return hint
+    },
     defaultD (column) {
       const filter = this.columnTypes.filter(t => t.value === column.type)
       if (!filter || filter.length === 0) {
diff --git a/dbrepo-ui/composables/query-service.ts b/dbrepo-ui/composables/query-service.ts
index 16d7c0cfac..a0b4427e01 100644
--- a/dbrepo-ui/composables/query-service.ts
+++ b/dbrepo-ui/composables/query-service.ts
@@ -198,35 +198,35 @@ export const useQueryService = (): any => {
 
   function mySql8DataTypes(): MySql8DataType[] {
     return [
-      {value: 'bigint', text: 'BIGINT(size)', defaultSize: null, defaultD: null, quoted: false, isBuildable: true},
-      {value: 'binary', text: 'BINARY(size)', defaultSize: null, defaultD: null, quoted: false, isBuildable: false},
-      {value: 'bit', text: 'BIT(size)', defaultSize: null, defaultD: null, quoted: false, isBuildable: true},
-      {value: 'blob', text: 'BLOB', defaultSize: null, defaultD: null, quoted: false, isBuildable: false},
+      {value: 'bigint', text: 'BIGINT(size)', defaultSize: null, defaultD: null, signed: null, zerofill: false, quoted: false, isBuildable: true, hint: null},
+      {value: 'binary', text: 'BINARY(size)', minSize: 0, maxSize: 255, defaultSize: 255, defaultD: null, quoted: false, isBuildable: false, hint: 'size in Bytes'},
+      {value: 'bit', text: 'BIT(size)', minSize: 1, maxSize: 64, defaultSize: null, defaultD: null, quoted: false, isBuildable: true, hint: null},
+      {value: 'blob', text: 'BLOB(size)', minSize: 0, maxSize: 65535, defaultSize: null, defaultD: null, quoted: false, isBuildable: false, hint: 'size in Bytes'},
       {value: 'bool', text: 'BOOL', defaultSize: null, defaultD: null, quoted: false, isBuildable: true},
-      {value: 'char', text: 'CHAR(size)', defaultSize: 1, defaultD: null, quoted: true, isBuildable: true},
-      {value: 'date', text: 'DATE', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
-      {value: 'datetime', text: 'DATETIME(fsp)', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
-      {value: 'decimal', text: 'DECIMAL(size, d)', defaultSize: null, defaultD: null, quoted: false, isBuildable: true},
-      {value: 'double', text: 'DOUBLE(size, d)', defaultSize: null, defaultD: null, quoted: false, isBuildable: true},
+      {value: 'char', text: 'CHAR(size)', minSize: 0, maxSize: 255, defaultSize: 255, defaultD: null, quoted: true, isBuildable: true},
+      {value: 'date', text: 'DATE', defaultSize: null, defaultD: null, quoted: true, isBuildable: true, hint: 'min. 1000-01-01, max. 9999-12-31'},
+      {value: 'datetime', text: 'DATETIME(fsp)', minSize: 0, maxSize: 6, defaultSize: null, defaultD: null, quoted: true, isBuildable: true, hint: 'fsp=microsecond precision, min. 1000-01-01 00:00:00.0, max. 9999-12-31 23:59:59.9'},
+      {value: 'decimal', text: 'DECIMAL(size, d)', minSize: 0, maxSize: 65, defaultSize: null, defaultD: null, minD: 0, maxD: 38, signed: null, quoted: false, isBuildable: true},
+      {value: 'double', text: 'DOUBLE(size, d)', defaultSize: null, defaultD: null, signed: null, quoted: false, isBuildable: true},
       {value: 'enum', text: 'ENUM(val1,val2,...)', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
-      {value: 'float', text: 'FLOAT(p)', defaultSize: null, defaultD: null, quoted: false, isBuildable: true},
-      {value: 'int', text: 'INT(size)', defaultSize: null, defaultD: null, quoted: false, isBuildable: true},
-      {value: 'longblob', text: 'LONGBLOB', defaultSize: null, defaultD: null, quoted: false, isBuildable: false},
-      {value: 'longtext', text: 'LONGTEXT', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
-      {value: 'mediumblob', text: 'MEDIUMBLOB', defaultSize: null, defaultD: null, quoted: false, isBuildable: false},
-      {value: 'mediumint', text: 'MEDIUMINT(size)', defaultSize: null, defaultD: null, quoted: false, isBuildable: true},
+      {value: 'float', text: 'FLOAT(p)', defaultSize: null, defaultD: null, signed: null, quoted: false, isBuildable: true},
+      {value: 'int', text: 'INT(size)', defaultSize: null, defaultD: null, signed: null, zerofill: false, quoted: false, isBuildable: true, hint: 'size in Bytes'},
+      {value: 'longblob', text: 'LONGBLOB', defaultSize: null, defaultD: null, quoted: false, isBuildable: false, hint: 'max. 3.999 GiB'},
+      {value: 'longtext', text: 'LONGTEXT', defaultSize: null, defaultD: null, quoted: true, isBuildable: true,  hint: 'max. 3.999 GiB'},
+      {value: 'mediumblob', text: 'MEDIUMBLOB', defaultSize: null, defaultD: null, quoted: false, isBuildable: false, hint: 'max. 15.999 MiB'},
+      {value: 'mediumint', text: 'MEDIUMINT(size)', defaultSize: null, defaultD: null, signed: null, zerofill: false, quoted: false, isBuildable: true, hint: 'size in Bytes'},
       {value: 'mediumtext', text: 'MEDIUMTEXT', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
       {value: 'set', text: 'SET(val1,val2,...)', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
-      {value: 'smallint', text: 'SMALLINT(size)', defaultSize: null, defaultD: null, quoted: false, isBuildable: true},
-      {value: 'text', text: 'TEXT', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
-      {value: 'time', text: 'TIME(fsp)', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
-      {value: 'timestamp', text: 'TIMESTAMP(fsp)', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
+      {value: 'smallint', text: 'SMALLINT(size)', defaultSize: null, defaultD: null, signed: null, zerofill: false, quoted: false, isBuildable: true, hint: 'size in Bytes'},
+      {value: 'text', text: 'TEXT(size)', minSize: 0, defaultSize: null, defaultD: null, quoted: true, isBuildable: true, hint: 'size in #characters'},
+      {value: 'time', text: 'TIME(fsp)', minSize: 0, maxSize: 6, defaultSize: 0, defaultD: null, quoted: true, isBuildable: true, hint: 'fsp=microsecond precision, min. 0, max. 6'},
+      {value: 'timestamp', text: 'TIMESTAMP(fsp)', minSize: 0, maxSize: 6, defaultSize: 0, defaultD: null, quoted: true, isBuildable: true, hint: 'fsp=microsecond precision, min. 0, max. 6'},
       {value: 'tinyblob', text: 'TINYBLOB', defaultSize: null, defaultD: null, quoted: false, isBuildable: false},
-      {value: 'tinyint', text: 'TINYINT(size)', defaultSize: null, defaultD: null, quoted: false, isBuildable: true},
-      {value: 'tinytext', text: 'TINYTEXT', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
-      {value: 'year', text: 'YEAR', defaultSize: null, defaultD: null, quoted: true, isBuildable: true},
+      {value: 'tinyint', text: 'TINYINT(size)', defaultSize: null, defaultD: null, quoted: false, isBuildable: true, hint: 'size in Bytes'},
+      {value: 'tinytext', text: 'TINYTEXT', defaultSize: null, defaultD: null, quoted: true, isBuildable: true, hint: 'max. 255 characters'},
+      {value: 'year', text: 'YEAR', minSize: 2, maxSize: 4, sizeSteps: 2, defaultSize: null, defaultD: null, quoted: true, isBuildable: true, hint: 'min. 1901, max. 2155'},
       {value: 'varbinary', text: 'VARBINARY(size)', defaultSize: null, defaultD: null, quoted: false, isBuildable: false},
-      {value: 'varchar', text: 'VARCHAR(size)', defaultSize: 255, defaultD: null, quoted: true, isBuildable: true}
+      {value: 'varchar', text: 'VARCHAR(size)', minSize: 0, maxSize: 65532, defaultSize: 255, defaultD: null, quoted: true, isBuildable: true, hint: 'max. characters depends on the encoding'}
     ]
   }
 
-- 
GitLab