logologo
Get Started
Tutorials
Guide
Development
Plugins
API
Home
English
简体中文
日本語
한국어
Español
Português
Deutsch
Français
Русский
Get Started
Tutorials
Guide
Development
Plugins
API
Home
logologo
RunJS Overview
Importing Modules
Rendering in Container

Global Variables

window
document
navigator

ctx

ctx.blockModel
ctx.collection
ctx.collectionField
ctx.dataSource
ctx.dataSourceManager
ctx.element
ctx.exit()
ctx.exitAll()
ctx.filterManager
ctx.form
ctx.getModel()
ctx.getValue()
ctx.getVar()
ctx.i18n
ctx.importAsync()
ctx.initResource()
ctx.libs
ctx.location
ctx.logger
ctx.makeResource()
ctx.message
ctx.modal
ctx.model
ctx.notification
ctx.off()
ctx.on()
ctx.openView()
ctx.render()
ctx.request()
ctx.requireAsync()
ctx.resource
ctx.route
ctx.router
ctx.setValue()
ctx.sql
ctx.t()
ctx.view
Previous Pagectx.setValue()
Next Pagectx.t()

#ctx.sql

ctx.sql provides SQL execution and management, often used in RunJS (e.g. JSBlock, event flow) to access the database directly. It supports ad-hoc SQL, running saved SQL templates by ID, parameter binding, template variables ({{ctx.xxx}}), and result type control.

#Use Cases

ScenarioDescription
JSBlockCustom reports, complex filtered lists, cross-table aggregation
Chart blockSaved SQL templates as chart data source
Event flow / linkageRun predefined SQL and use results in logic
SQLResourceWith ctx.initResource('SQLResource') for paginated lists, etc.

Note: ctx.sql uses the flowSql API to access the database; ensure the current user has execute permission on the target data source.

#Permissions

PermissionMethodDescription
Logged-in userrunByIdRun by configured SQL template ID
SQL config permissionrun, save, destroyAd-hoc SQL, save/update/delete SQL templates

Front-end logic for normal users can use ctx.sql.runById(uid, options); for dynamic SQL or template management, the current role must have SQL config permission.

#Type

sql: FlowSQLRepository;

interface FlowSQLRepository {
  run<T = any>(
    sql: string,
    options?: {
      bind?: Record<string, any> | any[];
      type?: 'selectRows' | 'selectRow' | 'selectVar';
      dataSourceKey?: string;
      filter?: Record<string, any>;
    },
  ): Promise<T>;

  save(options: { uid: string; sql: string; dataSourceKey?: string }): Promise<void>;

  runById<T = any>(
    uid: string,
    options?: {
      bind?: Record<string, any> | any[];
      type?: 'selectRows' | 'selectRow' | 'selectVar';
      dataSourceKey?: string;
      filter?: Record<string, any>;
    },
  ): Promise<T>;

  destroy(uid: string): Promise<void>;
}

#Common Methods

MethodDescriptionPermission
ctx.sql.run(sql, options?)Run ad-hoc SQL; supports parameter binding and template variablesSQL config
ctx.sql.save({ uid, sql, dataSourceKey? })Save/update SQL template by ID for reuseSQL config
ctx.sql.runById(uid, options?)Run saved SQL template by IDAny logged-in user
ctx.sql.destroy(uid)Delete SQL template by IDSQL config
  • run: for debugging SQL; requires config permission.
  • save, destroy: for managing SQL templates; require config permission.
  • runById: available to normal users; only runs saved templates.
  • Call save when a SQL template changes.

#Options

#run / runById options

OptionTypeDescription
bindRecord<string, any>Bound variables. Use $name in SQL and pass object { name: value }
type'selectRows' | 'selectRow' | 'selectVar'Result type: multiple rows, single row, single value; default selectRows
dataSourceKeystringData source key; default is main data source
filterRecord<string, any>Extra filter (if supported)

#save options

OptionTypeDescription
uidstringTemplate unique id; use with runById(uid, ...)
sqlstringSQL text; supports {{ctx.xxx}} and $name placeholders
dataSourceKeystringOptional data source key

#Template Variables and Parameter Binding

#Template variables {{ctx.xxx}}

In SQL you can use {{ctx.xxx}} to reference context variables; they are resolved before execution:

// Reference ctx.user.id
const user = await ctx.sql.run(
  'SELECT * FROM users WHERE id = {{ctx.user.id}}',
  { type: 'selectRow' }
);

Variable sources are the same as for ctx.getVar() (e.g. ctx.user.*, ctx.record.*, custom ctx.defineProperty, etc.).

#Parameter binding

  • Use $name in SQL and pass bind: { name: value }
const users = await ctx.sql.run(
  'SELECT * FROM users WHERE status = $status AND age > $minAge',
  { bind: { status: 'active', minAge: 18 }, type: 'selectRows' }
);

#Examples

#Ad-hoc SQL (requires SQL config permission)

// Multiple rows (default)
const rows = await ctx.sql.run('SELECT * FROM users LIMIT 10');

// Single row
const user = await ctx.sql.run(
  'SELECT * FROM users WHERE id = $id',
  { bind: { id: 1 }, type: 'selectRow' }
);

// Single value (e.g. COUNT, SUM)
const total = await ctx.sql.run(
  'SELECT COUNT(*) AS total FROM users',
  { type: 'selectVar' }
);

#Template variables

ctx.defineProperty('minId', { get: () => 1 });

const rows = await ctx.sql.run(
  'SELECT * FROM users WHERE id > {{ctx.minId}}',
  { type: 'selectRows' }
);

#Save template and reuse

// Save (requires SQL config permission)
await ctx.sql.save({
  uid: 'active-users-report',
  sql: 'SELECT * FROM users WHERE status = $status ORDER BY created_at DESC',
});

// Any logged-in user can run
const users = await ctx.sql.runById('active-users-report', {
  bind: { status: 'active' },
  type: 'selectRows',
});

// Delete template (requires SQL config permission)
await ctx.sql.destroy('active-users-report');

#Paginated list (SQLResource)

// For pagination and filters, use SQLResource
ctx.initResource('SQLResource');
ctx.resource.setFilterByTk('saved-sql-uid');  // Saved SQL template ID
ctx.resource.setBind({ status: 'active' });
await ctx.resource.refresh();
const data = ctx.resource.getData();
const meta = ctx.resource.getMeta();  // page, pageSize, etc.

#Relation to ctx.resource, ctx.request

UseRecommended
Run SQLctx.sql.run() or ctx.sql.runById()
SQL paginated list (block)ctx.initResource('SQLResource') + ctx.resource.refresh()
Generic HTTPctx.request()

ctx.sql wraps the flowSql API for SQL; ctx.request is for arbitrary API calls.

#Notes

  • Use parameter binding ($name) instead of string concatenation to avoid SQL injection.
  • With type: 'selectVar' the result is a scalar (e.g. for COUNT, SUM).
  • Template variables {{ctx.xxx}} are resolved before execution; ensure the context defines them.

#Related

  • ctx.resource: data resource; SQLResource uses flowSql internally
  • ctx.initResource(): initialize SQLResource for paginated lists
  • ctx.request(): generic HTTP requests