Initial implementation of generating SQS junction table definitions.

This commit is contained in:
mike12345567 2024-04-11 18:19:47 +01:00
parent 0a54396f66
commit 6e4a66b2e1
6 changed files with 72 additions and 18 deletions

View File

@ -17,6 +17,7 @@ APP_PORT=4002
WORKER_PORT=4003 WORKER_PORT=4003
MINIO_PORT=4004 MINIO_PORT=4004
COUCH_DB_PORT=4005 COUCH_DB_PORT=4005
COUCH_DB_SQS_PORT=4006
REDIS_PORT=6379 REDIS_PORT=6379
WATCHTOWER_PORT=6161 WATCHTOWER_PORT=6161
BUDIBASE_ENVIRONMENT=PRODUCTION BUDIBASE_ENVIRONMENT=PRODUCTION
@ -28,4 +29,4 @@ BB_ADMIN_USER_PASSWORD=
# A path that is watched for plugin bundles. Any bundles found are imported automatically/ # A path that is watched for plugin bundles. Any bundles found are imported automatically/
PLUGINS_DIR= PLUGINS_DIR=
ROLLING_LOG_MAX_SIZE= ROLLING_LOG_MAX_SIZE=

View File

@ -42,12 +42,13 @@ services:
couchdb-service: couchdb-service:
container_name: budi-couchdb3-dev container_name: budi-couchdb3-dev
restart: on-failure restart: on-failure
image: budibase/couchdb image: budibase/couchdb:v3.2.1-sqs
environment: environment:
- COUCHDB_PASSWORD=${COUCH_DB_PASSWORD} - COUCHDB_PASSWORD=${COUCH_DB_PASSWORD}
- COUCHDB_USER=${COUCH_DB_USER} - COUCHDB_USER=${COUCH_DB_USER}
ports: ports:
- "${COUCH_DB_PORT}:5984" - "${COUCH_DB_PORT}:5984"
- "${COUCH_DB_SQS_PORT}:4984"
volumes: volumes:
- couchdb_data:/data - couchdb_data:/data

View File

@ -107,7 +107,7 @@ const environment = {
ENCRYPTION_KEY: process.env.ENCRYPTION_KEY, ENCRYPTION_KEY: process.env.ENCRYPTION_KEY,
API_ENCRYPTION_KEY: getAPIEncryptionKey(), API_ENCRYPTION_KEY: getAPIEncryptionKey(),
COUCH_DB_URL: process.env.COUCH_DB_URL || "http://localhost:4005", COUCH_DB_URL: process.env.COUCH_DB_URL || "http://localhost:4005",
COUCH_DB_SQL_URL: process.env.COUCH_DB_SQL_URL || "http://localhost:4984", COUCH_DB_SQL_URL: process.env.COUCH_DB_SQL_URL || "http://localhost:4006",
COUCH_DB_USERNAME: process.env.COUCH_DB_USER, COUCH_DB_USERNAME: process.env.COUCH_DB_USER,
COUCH_DB_PASSWORD: process.env.COUCH_DB_PASSWORD, COUCH_DB_PASSWORD: process.env.COUCH_DB_PASSWORD,
GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID, GOOGLE_CLIENT_ID: process.env.GOOGLE_CLIENT_ID,

View File

@ -28,6 +28,7 @@ const DEFAULTS = {
PLUGINS_DIR: "/plugins", PLUGINS_DIR: "/plugins",
FORKED_PROCESS_NAME: "main", FORKED_PROCESS_NAME: "main",
JS_RUNNER_MEMORY_LIMIT: 64, JS_RUNNER_MEMORY_LIMIT: 64,
COUCH_DB_SQL_URL: "http://localhost:4006",
} }
const QUERY_THREAD_TIMEOUT = const QUERY_THREAD_TIMEOUT =
@ -39,6 +40,7 @@ const environment = {
// important - prefer app port to generic port // important - prefer app port to generic port
PORT: process.env.APP_PORT || process.env.PORT, PORT: process.env.APP_PORT || process.env.PORT,
COUCH_DB_URL: process.env.COUCH_DB_URL, COUCH_DB_URL: process.env.COUCH_DB_URL,
COUCH_DB_SQL_URL: process.env.COUCH_DB_SQL_URL || DEFAULTS.COUCH_DB_SQL_URL,
MINIO_URL: process.env.MINIO_URL, MINIO_URL: process.env.MINIO_URL,
WORKER_URL: process.env.WORKER_URL, WORKER_URL: process.env.WORKER_URL,
AWS_REGION: process.env.AWS_REGION, AWS_REGION: process.env.AWS_REGION,

View File

@ -1,8 +1,19 @@
import { context, SQLITE_DESIGN_DOC_ID } from "@budibase/backend-core" import { context, SQLITE_DESIGN_DOC_ID } from "@budibase/backend-core"
import { FieldType, SQLiteDefinition, SQLiteType, Table } from "@budibase/types" import {
FieldType,
RelationshipFieldMetadata,
SQLiteDefinition,
SQLiteTable,
SQLiteTables,
SQLiteType,
Table,
} from "@budibase/types"
import { cloneDeep } from "lodash" import { cloneDeep } from "lodash"
import tablesSdk from "../" import tablesSdk from "../"
import { CONSTANT_INTERNAL_ROW_COLS } from "../../../../db/utils" import {
CONSTANT_INTERNAL_ROW_COLS,
generateJunctionTableID,
} from "../../../../db/utils"
const BASIC_SQLITE_DOC: SQLiteDefinition = { const BASIC_SQLITE_DOC: SQLiteDefinition = {
_id: SQLITE_DESIGN_DOC_ID, _id: SQLITE_DESIGN_DOC_ID,
@ -36,9 +47,38 @@ const FieldTypeMap: Record<FieldType, SQLiteType> = {
[FieldType.BB_REFERENCE]: SQLiteType.TEXT, [FieldType.BB_REFERENCE]: SQLiteType.TEXT,
} }
function mapTable(table: Table): { [key: string]: SQLiteType } { function buildRelationshipDefinitions(
table: Table,
relationshipColumn: RelationshipFieldMetadata
): {
tableId: string
definition: SQLiteTable
} {
const tableId = table._id!,
relatedTableId = relationshipColumn.tableId
return {
tableId: generateJunctionTableID(tableId, relatedTableId),
definition: {
doc1: SQLiteType.BLOB,
doc2: SQLiteType.BLOB,
tableId: SQLiteType.TEXT,
},
}
}
// this can generate relationship tables as part of the mapping
function mapTable(table: Table): SQLiteTables {
const tables: SQLiteTables = {}
const fields: Record<string, SQLiteType> = {} const fields: Record<string, SQLiteType> = {}
for (let [key, column] of Object.entries(table.schema)) { for (let [key, column] of Object.entries(table.schema)) {
// relationships should be handled differently
if (column.type === FieldType.LINK) {
const { tableId, definition } = buildRelationshipDefinitions(
table,
column
)
tables[tableId] = { fields: definition }
}
if (!FieldTypeMap[column.type]) { if (!FieldTypeMap[column.type]) {
throw new Error(`Unable to map type "${column.type}" to SQLite type`) throw new Error(`Unable to map type "${column.type}" to SQLite type`)
} }
@ -49,10 +89,12 @@ function mapTable(table: Table): { [key: string]: SQLiteType } {
CONSTANT_INTERNAL_ROW_COLS.forEach(col => { CONSTANT_INTERNAL_ROW_COLS.forEach(col => {
constantMap[col] = SQLiteType.TEXT constantMap[col] = SQLiteType.TEXT
}) })
return { const thisTable: SQLiteTable = {
...constantMap, ...constantMap,
...fields, ...fields,
} }
tables[table._id!] = { fields: thisTable }
return tables
} }
// nothing exists, need to iterate though existing tables // nothing exists, need to iterate though existing tables
@ -60,8 +102,9 @@ async function buildBaseDefinition(): Promise<SQLiteDefinition> {
const tables = await tablesSdk.getAllInternalTables() const tables = await tablesSdk.getAllInternalTables()
const definition = cloneDeep(BASIC_SQLITE_DOC) const definition = cloneDeep(BASIC_SQLITE_DOC)
for (let table of tables) { for (let table of tables) {
definition.sql.tables[table._id!] = { definition.sql.tables = {
fields: mapTable(table), ...definition.sql.tables,
...mapTable(table),
} }
} }
return definition return definition
@ -75,8 +118,9 @@ export async function addTableToSqlite(table: Table) {
} catch (err) { } catch (err) {
definition = await buildBaseDefinition() definition = await buildBaseDefinition()
} }
definition.sql.tables[table._id!] = { definition.sql.tables = {
fields: mapTable(table), ...definition.sql.tables,
...mapTable(table),
} }
await db.put(definition) await db.put(definition)
} }

View File

@ -6,17 +6,23 @@ export enum SQLiteType {
NUMERIC = "NUMERIC", NUMERIC = "NUMERIC",
} }
export type SQLiteTable = Record<
string,
SQLiteType | { field: string; type: SQLiteType }
>
export type SQLiteTables = Record<
string,
{
fields: SQLiteTable
}
>
export interface SQLiteDefinition { export interface SQLiteDefinition {
_id: string _id: string
language: string language: string
sql: { sql: {
tables: { tables: SQLiteTables
[tableName: string]: {
fields: {
[key: string]: SQLiteType | { field: string; type: SQLiteType }
}
}
}
options: { options: {
table_name: string table_name: string
} }