跳到主要内容

关系型数据库(PostgreSQL)

版本提示

@cloudbase/manager-node@5.4.0 起新增此模块。通过 app.database 访问,提供在 PostgreSQL 架构的云开发环境上执行 SQL 语句及管理数据的能力。


初始化

import CloudBase from '@cloudbase/manager-node'

const app = CloudBase.init({
secretId: 'Your SecretId',
secretKey: 'Your SecretKey',
envId: 'Your envId'
})

const { database } = app

executePGSql

1. 接口描述

接口功能:在 PostgreSQL 环境上执行任意 SQL 语句(DDL / DML / DQL 等),并返回结果集与受影响行数。

接口声明:app.database.executePGSql(options): Promise<IExecutePGSqlResult>

2. 输入参数

IExecutePGSqlOptions

字段必填类型说明
SqlString要执行的 SQL 语句
RoleString指定 role 执行 SQL,可传任意有效的 role(包括用户自定义 role)。云开发内置了 cloudbase_read_only_user 只读角色,使用该角色执行 SQL 可避免非预期的写操作执行成功
EnvIdString云开发环境 ID,不传则使用当前管理实例初始化时的 EnvId

3. 返回结果

IExecutePGSqlResult

字段类型说明
RequestIdString请求唯一标识
AffectedRowsNumber受影响行数(DML 类语句有效)
ColumnsString[] / null字段名列表(SELECT 类语句返回);无结果集时为 null
RowsString[] / null数据行列表,每一项是 JSON 串,反序列化后是 (string | null)[],按 Columns 顺序对齐;无结果集时为 null
ExecutionTimeMsNumberSQL 执行耗时(毫秒)

4. 示例代码

// 创建表
await database.executePGSql({
Sql: 'CREATE TABLE users (id SERIAL PRIMARY KEY, name TEXT NOT NULL, email TEXT UNIQUE)'
})

// 插入数据
const insertRes = await database.executePGSql({
Sql: "INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com')"
})
console.log('受影响行数:', insertRes.AffectedRows) // 1

// 查询并解析结果
const res = await database.executePGSql({
Sql: 'SELECT id, name, email FROM users WHERE id = 1'
})
console.log(res.Columns) // ['id', 'name', 'email']
const rows = (res.Rows || []).map(s => JSON.parse(s))
// rows: [['1', 'Alice', 'alice@example.com']]

// 使用云开发内置的只读 role 执行查询,避免非预期的写操作执行成功
const readonlyRes = await database.executePGSql({
Role: 'cloudbase_read_only_user',
Sql: 'SELECT id, name, email FROM users'
})
console.log(readonlyRes.Rows)

// 指定其他环境 ID 执行
await database.executePGSql({
EnvId: 'other-env-id',
Sql: 'SELECT NOW()'
})

数据库迁移(Migrations)

版本提示

@cloudbase/manager-node@5.6.5 起新增以下数据库迁移相关方法,用于在 PostgreSQL 架构的云开发环境中,以“版本化 SQL 脚本”的方式管理表结构与数据变更。

概念说明

  • Migration(迁移):一次带有版本号的 SQL 变更,包含 VersionNameQuery
    • Version:14 位数字时间串,例如 20260526000000。建议使用发生时间(YYYYMMDDHHMMSS)保证全局有序、唯一。
    • Name:仅允许小写字母和下划线,如 create_users_table
    • Query:本次要执行的 SQL。
  • cloudbase_migrations.schema_migrations:云开发在目标 PG 环境中维护的迁移历史表,记录已成功应用的 migration。
  • 典型流程
    1. previewPGUserMigrations 预览计划、检查 checksum 冲突。
    2. 无冲突后调用 pushPGUserMigrations,得到 TaskId
    3. 通过 describeTaskResult 轮询任务状态直至 Succeed / Failed
    4. 需要时用 listPGUserMigrations / listAllPGUserMigrations / describePGUserMigration 查询已应用记录。
    5. 出现历史与实际不一致时,用 repairPGUserMigrationHistory 仅修复 history 记录(不执行 SQL)。

previewPGUserMigrations

1. 接口描述

接口功能:预览一批用户 migration 的远端执行计划(不实际执行 SQL),并返回 Pending(待执行)、Applied(已应用)、Conflicts(checksum 冲突)、Executable(是否可直接执行)。

接口声明:app.database.previewPGUserMigrations(options): Promise<IPreviewPGUserMigrationsResult>

2. 输入参数

IPreviewPGUserMigrationsOptions

字段必填类型说明
EnvIdString云开发环境 ID,不传则使用管理实例初始化时的 EnvId
MigrationsIPGUserMigrationInput[]migration 列表,至少 1 条;每条需通过下方入参校验
IncludeAllBoolean是否允许 out-of-order 本地 migration(在已应用版本之前插入新版本),默认 false

IPGUserMigrationInput

字段必填类型说明
VersionStringmigration 版本,14 位数字时间串(如 20260526000000
NameStringmigration 名称,仅允许小写字母和下划线
QueryString要执行的 SQL,不能为空字符串

3. 返回结果

IPreviewPGUserMigrationsResult

字段类型说明
PendingIPGUserMigrationPlanItem[] | null将要执行的 migration 列表
AppliedIPGUserMigrationPlanItem[] | null已经应用过的 migration 列表
ConflictsIPGUserMigrationConflict[] | null冲突列表:版本号相同但 checksum 不一致的 migration,非空即表示本地 SQL 与已应用记录不一致
ExecutableBoolean是否可直接执行(当前主要表示无 checksum 冲突)
RequestIdString请求唯一标识

IPGUserMigrationPlanItem 主要字段:VersionNameStatus(如 applied / pending)、Reason(如 checksum_matched)、ChecksumSource

IPGUserMigrationConflict 主要字段:VersionNameRemoteNameLocalChecksumRemoteChecksumReason(如 checksum_mismatch)、Message

4. 示例代码

const preview = await database.previewPGUserMigrations({
Migrations: [
{
Version: '20260526000000',
Name: 'create_users_table',
Query:
'CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name TEXT NOT NULL);'
}
]
})

if (!preview.Executable || (preview.Conflicts || []).length > 0) {
console.error('存在 checksum 冲突,需要处理:', preview.Conflicts)
return
}

console.log('待执行:', preview.Pending)
console.log('已应用:', preview.Applied)

pushPGUserMigrations

1. 接口描述

接口功能:批量应用一组用户 migration。该接口是异步任务,成功调用后返回 TaskId,需要用 describeTaskResult 查询最终结果。

接口声明:app.database.pushPGUserMigrations(options): Promise<IPushPGUserMigrationsResult>

2. 输入参数

IPushPGUserMigrationsOptions

字段必填类型说明
EnvIdString云开发环境 ID,不传则使用管理实例初始化时的 EnvId
MigrationsIPGUserMigrationInput[]migration 列表,至少 1 条;字段校验规则同 previewPGUserMigrations
LockTimeoutMsNumber获取数据库锁的最长等待时间(毫秒),不能小于 0,默认 5000
StatementTimeoutMsNumber单条 SQL 最长执行时间(毫秒),不能小于 0,默认 300000
IncludeAllBoolean是否允许 out-of-order 本地 migration,默认 false

3. 返回结果

IPushPGUserMigrationsResult

字段类型说明
RequestIdString请求唯一标识
TaskIdString异步任务 ID,可用于查询任务进度与状态

4. 示例代码

// 1. 提交异步任务
const { TaskId } = await database.pushPGUserMigrations({
Migrations: [
{
Version: '20260526000000',
Name: 'create_users_table',
Query:
'CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name TEXT NOT NULL);'
}
],
LockTimeoutMs: 5000,
StatementTimeoutMs: 60000
})

// 2. 轮询任务状态
async function waitTask(taskId) {
while (true) {
const task = await database.describeTaskResult({ TaskId: taskId })
if (task.Status === 'Succeed' || task.Status === 'Failed') {
return task
}
await new Promise(r => setTimeout(r, 1000))
}
}

const result = await waitTask(TaskId)
console.log('任务结束:', result.Status, result.Phase, result.Reason)

repairPGUserMigrationHistory

1. 接口描述

接口功能:仅维护 cloudbase_migrations.schema_migrations 表中的历史记录,不执行任何 SQL。适用于以下场景:

  • 线下手动执行过 SQL,但历史表中没有对应记录(用 applied 补录)。
  • 需要将某条已记录的 migration 从历史中撤回(用 reverted 删除记录)。

接口声明:app.database.repairPGUserMigrationHistory(options): Promise<IResponseInfo>

2. 输入参数

IRepairPGUserMigrationHistoryOptions

字段必填类型说明
EnvIdString云开发环境 ID,不传则使用管理实例初始化时的 EnvId
MigrationVersionStringmigration 版本,14 位数字时间串
NameStringmigration 名称,仅允许小写字母和下划线
Status'applied' | 'reverted'修复方式:applied 写入 history,reverted 从 history 删除
ReasonString修复原因,不能为空
QueryStringStatus=applied必填,建议填对应的 SQL;Status=reverted 时可不传

3. 返回结果

IResponseInfo:包含 RequestId 等通用字段。

4. 示例代码

// 补录一条已线下执行的 migration
await database.repairPGUserMigrationHistory({
MigrationVersion: '20260526000000',
Name: 'create_users_table',
Status: 'applied',
Reason: '线下手动执行完成,补录历史',
Query: 'CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name TEXT NOT NULL);'
})

// 将一条错误记录的 migration 从 history 中撤回
await database.repairPGUserMigrationHistory({
MigrationVersion: '20260526000000',
Name: 'create_users_table',
Status: 'reverted',
Reason: '误记录,需从 history 中删除'
})

listPGUserMigrations

1. 接口描述

接口功能:分页查询目标环境已应用的 migration 列表。

接口声明:app.database.listPGUserMigrations(options?): Promise<IListPGUserMigrationsResult>

2. 输入参数

IListPGUserMigrationsOptions(全部可选)

字段必填类型说明
EnvIdString云开发环境 ID,不传则使用管理实例初始化时的 EnvId
LimitNumber查询条数,取值范围 [1, 500],默认 100
OffsetNumber分页偏移,>= 0,默认 0

3. 返回结果

IListPGUserMigrationsResult

字段类型说明
TotalNumber总数量
LatestVersionString已应用的最新版本号(14 位数字时间串)
MigrationsIPGUserMigrationSummary[]已应用 migration 列表,每项包含 VersionName
RequestIdString请求唯一标识

4. 示例代码

const page = await database.listPGUserMigrations({ Limit: 100, Offset: 0 })
console.log('总数:', page.Total, '最新版本:', page.LatestVersion)
page.Migrations.forEach(m => {
console.log(m.Version, m.Name)
})

listAllPGUserMigrations

1. 接口描述

接口功能:自动翻页查询目标环境全部已应用的 migration 列表。内部按 PageSize 反复调用 listPGUserMigrations 直到取完。

接口声明:app.database.listAllPGUserMigrations(options?): Promise<IListPGUserMigrationsResult>

2. 输入参数

IListAllPGUserMigrationsOptions(全部可选)

字段必填类型说明
EnvIdString云开发环境 ID,不传则使用管理实例初始化时的 EnvId
PageSizeNumber内部翻页每页大小,取值范围 [1, 500],默认 500

3. 返回结果

listPGUserMigrationsIListPGUserMigrationsResult。返回的 Migrations全量列表

4. 示例代码

const all = await database.listAllPGUserMigrations()
console.log('已应用总数:', all.Migrations.length)
console.log('最新版本:', all.LatestVersion)

describePGUserMigration

1. 接口描述

接口功能:查询目标环境指定 migration 的详情(包含 SQL 内容)。

接口声明:app.database.describePGUserMigration(options): Promise<IDescribePGUserMigrationResult>

2. 输入参数

IDescribePGUserMigrationOptions

字段必填类型说明
EnvIdString云开发环境 ID,不传则使用管理实例初始化时的 EnvId
MigrationVersionStringmigration 版本,14 位数字时间串

3. 返回结果

IDescribePGUserMigrationResult

字段类型说明
VersionStringmigration 版本号
NameStringmigration 名称
QueryStringmigration 对应的 SQL
RequestIdString请求唯一标识

4. 示例代码

const detail = await database.describePGUserMigration({
MigrationVersion: '20260526000000'
})
console.log(detail.Version, detail.Name)
console.log(detail.Query)

describeTaskResult

1. 接口描述

接口功能:查询异步任务(如 pushPGUserMigrations 返回的任务)的执行状态。可用于轮询直至任务终态。

接口声明:app.database.describeTaskResult(options): Promise<IDescribeTaskResultResult>

2. 输入参数

IDescribeTaskResultOptions

字段必填类型说明
EnvIdString云开发环境 ID,不传则使用管理实例初始化时的 EnvId
TaskIdString任务 ID,不能为空

3. 返回结果

IDescribeTaskResultResult

字段类型说明
TaskIdString任务 ID
TaskTypeString任务类型(如 PGUserMigration
StatusString任务状态:Accepted / Running / Succeed / Failed
PhaseString当前步骤
ReasonString失败原因(成功时可能为空)
CreatedAtString创建时间(ISO 8601)
UpdatedAtString最后更新时间(ISO 8601)
RequestIdString请求唯一标识

4. 示例代码

const task = await database.describeTaskResult({ TaskId: 'task-xxxxxx' })
if (task.Status === 'Succeed') {
console.log('任务成功,耗时至', task.UpdatedAt)
} else if (task.Status === 'Failed') {
console.error('任务失败:', task.Phase, task.Reason)
} else {
console.log('任务进行中:', task.Status, task.Phase)
}