This is an automated email from the ASF dual-hosted git repository.

liuxun pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/gravitino.git


The following commit(s) were added to refs/heads/main by this push:
     new 85e9918ac [#5454] feat(web): different data table column types are 
supported depending on the provider (#5636)
85e9918ac is described below

commit 85e9918ac0058cc58fad87bc63716cb977c244e3
Author: JUN <oren....@gmail.com>
AuthorDate: Thu Nov 21 17:18:44 2024 +0800

    [#5454] feat(web): different data table column types are supported 
depending on the provider (#5636)
    
    ### What changes are proposed in this pull request?
    
    When creating or updating a table, the column types will vary depending
    on the provider.
    
    ### Why are these changes needed?
    
    Fixes: #5454
    
    ### Does this PR introduce _any_ user-facing changes?
    
    No.
    
    ### How was this patch tested?
    
    Tested by creating and updating tables with different providers to
    verify that the column types differ as expected and match the
    
[documentation](https://gravitino.apache.org/docs/0.6.1-incubating/lakehouse-iceberg-catalog/#table-column-types).
    
    Additionally, verified the success of the create/update operations.
---
 .../metalake/rightContent/CreateTableDialog.js     |  57 +++---
 web/web/src/lib/utils/initial.js                   | 196 ++++++++++++++++-----
 2 files changed, 181 insertions(+), 72 deletions(-)

diff --git 
a/web/web/src/app/metalakes/metalake/rightContent/CreateTableDialog.js 
b/web/web/src/app/metalakes/metalake/rightContent/CreateTableDialog.js
index df0091a26..547382dcd 100644
--- a/web/web/src/app/metalakes/metalake/rightContent/CreateTableDialog.js
+++ b/web/web/src/app/metalakes/metalake/rightContent/CreateTableDialog.js
@@ -72,7 +72,7 @@ import {
 import Icon from '@/components/Icon'
 
 // Import Redux hooks and actions
-import { useAppDispatch } from '@/lib/hooks/useStore'
+import { useAppDispatch, useAppSelector } from '@/lib/hooks/useStore'
 import { createTable, updateTable } from '@/lib/store/metalakes'
 
 // Import form validation libraries
@@ -85,7 +85,7 @@ import { groupBy } from 'lodash-es'
 import { genUpdates } from '@/lib/utils'
 import { nameRegex, nameRegexDesc, keyRegex } from '@/lib/utils/regex'
 import { useSearchParams } from 'next/navigation'
-import { tableColumnTypes } from '@/lib/utils/initial'
+import { getRelationalColumnTypeMap, getParameterizedColumnType } from 
'@/lib/utils/initial'
 
 // Default form values
 const defaultFormValues = {
@@ -138,6 +138,10 @@ const CreateTableDialog = props => {
   const catalogType = searchParams.get('type')
   const schemaName = searchParams.get('schema')
 
+  const store = useAppSelector(state => state.metalakes)
+  const currentCatalog = store.catalogs.find(ca => ca.name === catalog)
+  const columnTypes = getRelationalColumnTypeMap(currentCatalog?.provider)
+
   // Component state
   const [innerProps, setInnerProps] = useState([])
   const [tableColumns, setTableColumns] = useState([{ name: '', type: '', 
nullable: true, comment: '' }])
@@ -210,7 +214,8 @@ const CreateTableDialog = props => {
     if (field === 'type') {
       updatedColumns[index].typeSuffix = ''
       updatedColumns[index].paramErrors = ''
-      if (tableColumnTypes.find(type => type.key === value)?.params) {
+
+      if (getParameterizedColumnType(value)) {
         updatedColumns[index].paramValues = []
       }
     }
@@ -222,7 +227,7 @@ const CreateTableDialog = props => {
   const transformParamValues = index => {
     let updatedColumns = [...tableColumns]
 
-    const validateParams = tableColumnTypes.find(type => type.key === 
updatedColumns[index].type)?.validateParams
+    const validateParams = 
getParameterizedColumnType(updatedColumns[index].type)?.validateParams
     const paramValues = updatedColumns[index].paramValues.filter(param => 
param !== undefined).map(Number)
     const validateResult = validateParams(paramValues)
 
@@ -592,9 +597,9 @@ const CreateTableDialog = props => {
                                   data-refer={`column-type-${index}`}
                                   renderValue={selected => 
<Box>{`${selected}${column.typeSuffix || ''}`}</Box>}
                                 >
-                                  {tableColumnTypes.map(type => (
-                                    <MenuItem key={type.key} value={type.key}>
-                                      {type.key}
+                                  {columnTypes.map(type => (
+                                    <MenuItem key={type} value={type}>
+                                      {type}
                                     </MenuItem>
                                   ))}
                                 </Select>
@@ -621,28 +626,26 @@ const CreateTableDialog = props => {
                                     })
                                   }
 
-                                  return tableColumnTypes
-                                    .find(t => t.key === column.type)
-                                    ?.params?.map((param, paramIndex) => (
-                                      <TextField
-                                        key={paramIndex}
-                                        size='small'
-                                        type='number'
-                                        sx={{ minWidth: 60 }}
-                                        
value={column.paramValues?.[paramIndex] || ''}
-                                        onChange={e => {
-                                          const newParamValues = 
[...(column.paramValues || [])]
-                                          newParamValues[paramIndex] = 
e.target.value
-                                          handleColumnChange({ index, field: 
'paramValues', value: newParamValues })
-                                        }}
-                                        placeholder={`${param}`}
-                                        
data-refer={`column-param-${index}-${paramIndex}`}
-                                        inputProps={{ min: 0 }}
-                                      />
-                                    ))
+                                  return 
getParameterizedColumnType(column.type)?.params?.map((param, paramIndex) => (
+                                    <TextField
+                                      key={paramIndex}
+                                      size='small'
+                                      type='number'
+                                      sx={{ minWidth: 60 }}
+                                      value={column.paramValues?.[paramIndex] 
|| ''}
+                                      onChange={e => {
+                                        const newParamValues = 
[...(column.paramValues || [])]
+                                        newParamValues[paramIndex] = 
e.target.value
+                                        handleColumnChange({ index, field: 
'paramValues', value: newParamValues })
+                                      }}
+                                      placeholder={`${param}`}
+                                      
data-refer={`column-param-${index}-${paramIndex}`}
+                                      inputProps={{ min: 0 }}
+                                    />
+                                  ))
                                 })()}
                               {selectedColumnIndex !== index &&
-                                tableColumnTypes.find(type => type.key === 
column.type)?.params &&
+                                
getParameterizedColumnType(column.type)?.params &&
                                 column.paramValues &&
                                 transformParamValues(index)}
                             </Box>
diff --git a/web/web/src/lib/utils/initial.js b/web/web/src/lib/utils/initial.js
index 1ca2854da..6c599f9ee 100644
--- a/web/web/src/lib/utils/initial.js
+++ b/web/web/src/lib/utils/initial.js
@@ -347,37 +347,23 @@ export const providers = [
   }
 ]
 
-export const tableColumnTypes = [
-  { key: 'boolean' },
-  { key: 'byte' },
-  { key: 'short' },
-  { key: 'integer' },
-  { key: 'long' },
-  { key: 'float' },
-  { key: 'double' },
-  {
-    key: 'decimal',
-    params: ['precision', 'scale'],
+const parameterizedColumnTypes = {
+  char: {
+    params: ['length'],
     validateParams: params => {
-      if (params.length !== 2) {
+      if (params.length !== 1) {
         return {
           valid: false,
-          message: 'Please set precision and scale'
+          message: 'Please set length'
         }
       }
 
-      const [param1, param2] = params
-      if (param1 <= 0 || param1 > 38) {
-        return {
-          valid: false,
-          message: 'The precision must be between 1 and 38'
-        }
-      }
+      const length = params[0]
 
-      if (param2 < 0 || param2 > param1) {
+      if (length <= 0) {
         return {
           valid: false,
-          message: 'The scale must be between 0 and the precision'
+          message: 'The length must be greater than 0'
         }
       }
 
@@ -386,28 +372,28 @@ export const tableColumnTypes = [
       }
     }
   },
-  { key: 'date' },
-  { key: 'time' },
-  { key: 'timestamp' },
-  { key: 'timestamp_tz' },
-  { key: 'string' },
-  {
-    key: 'char',
-    params: ['length'],
+  decimal: {
+    params: ['precision', 'scale'],
     validateParams: params => {
-      if (params.length !== 1) {
+      if (params.length !== 2) {
         return {
           valid: false,
-          message: 'Please set length'
+          message: 'Please set precision and scale'
         }
       }
 
-      const length = params[0]
+      const [param1, param2] = params
+      if (param1 <= 0 || param1 > 38) {
+        return {
+          valid: false,
+          message: 'The precision must be between 1 and 38'
+        }
+      }
 
-      if (length <= 0) {
+      if (param2 < 0 || param2 > param1) {
         return {
           valid: false,
-          message: 'The length must be greater than 0'
+          message: 'The scale must be between 0 and the precision'
         }
       }
 
@@ -416,8 +402,7 @@ export const tableColumnTypes = [
       }
     }
   },
-  {
-    key: 'varchar',
+  fixed: {
     params: ['length'],
     validateParams: params => {
       if (params.length !== 1) {
@@ -441,10 +426,7 @@ export const tableColumnTypes = [
       }
     }
   },
-  { key: 'interval_day' },
-  { key: 'interval_year' },
-  {
-    key: 'fixed',
+  varchar: {
     params: ['length'],
     validateParams: params => {
       if (params.length !== 1) {
@@ -467,7 +449,131 @@ export const tableColumnTypes = [
         valid: true
       }
     }
-  },
-  { key: 'uuid' },
-  { key: 'binary' }
-]
+  }
+}
+
+export const getParameterizedColumnType = type => {
+  if (Object.keys(parameterizedColumnTypes).includes(type)) {
+    return parameterizedColumnTypes[type]
+  }
+}
+
+const relationalColumnTypeMap = {
+  'lakehouse-iceberg': [
+    'binary',
+    'boolean',
+    'date',
+    'decimal',
+    'double',
+    'fixed',
+    'float',
+    'integer',
+    'long',
+    'string',
+    'time',
+    'timestamp',
+    'timestamp_tz',
+    'uuid'
+  ],
+
+  hive: [
+    'binary',
+    'boolean',
+    'byte',
+    'char',
+    'date',
+    'decimal',
+    'double',
+    'float',
+    'integer',
+    'interval_day',
+    'interval_year',
+    'long',
+    'short',
+    'string',
+    'timestamp',
+    'varchar'
+  ],
+
+  'jdbc-mysql': [
+    'binary',
+    'byte',
+    'byte unsigned',
+    'char',
+    'date',
+    'decimal',
+    'double',
+    'float',
+    'integer',
+    'integer unsigned',
+    'long',
+    'long unsigned',
+    'short',
+    'short unsigned',
+    'string',
+    'time',
+    'timestamp',
+    'varchar'
+  ],
+  'jdbc-postgresql': [
+    'binary',
+    'boolean',
+    'char',
+    'date',
+    'decimal',
+    'double',
+    'float',
+    'integer',
+    'long',
+    'short',
+    'string',
+    'time',
+    'timestamp',
+    'timestamp_tz',
+    'varchar'
+  ],
+
+  'jdbc-doris': [
+    'boolean',
+    'byte',
+    'char',
+    'date',
+    'decimal',
+    'double',
+    'float',
+    'integer',
+    'long',
+    'short',
+    'string',
+    'timestamp',
+    'varchar'
+  ],
+
+  'lakehouse-paimon': [
+    'binary',
+    'boolean',
+    'byte',
+    'char',
+    'date',
+    'decimal',
+    'double',
+    'fixed',
+    'float',
+    'integer',
+    'long',
+    'short',
+    'string',
+    'time',
+    'timestamp',
+    'timestamp_tz',
+    'varchar'
+  ]
+}
+
+export const getRelationalColumnTypeMap = catalog => {
+  if (Object.keys(relationalColumnTypeMap).includes(catalog)) {
+    return relationalColumnTypeMap[catalog]
+  }
+
+  return []
+}

Reply via email to