| title | ObjectQL - Data Layer Architecture |
|---|---|
| description | Deep dive into the ObjectQL (Object Query Language) data protocol architecture |
Deep dive into the ObjectQL (Object Query Language) data protocol architecture
ObjectQL is the data abstraction layer of ObjectStack. It defines how data structures are expressed, queried, and manipulated across different storage backends.
Defines business entities (tables/collections):
const CustomerAccount = {
name: 'customer_account',
label: 'Customer Account',
fields: { /* field definitions */ },
enableHistory: true,
enableSharing: true,
};Defines data properties with 35 types:
- Basic: text, textarea, number, boolean, date, datetime
- Advanced: lookup, master_detail, formula, summary, autonumber
- Rich: email, phone, url, currency, percent, markdown, html, richtext
- Complex: address, location (aka geolocation), file, image, avatar
- Enhanced: code, color, rating, slider, signature, qrcode
Abstract Syntax Tree (AST) for unified data access:
const query = {
select: ['name', 'email', 'revenue'],
from: 'customer_account',
where: {
and: [
{ field: 'industry', operator: 'eq', value: 'technology' },
{ field: 'revenue', operator: 'gt', value: 500000 }
]
},
orderBy: [{ field: 'revenue', direction: 'desc' }],
limit: 10,
};Business logic validation:
- Format Validation: Email, phone, URL patterns
- Range Validation: Min/max for numbers and dates
- Uniqueness: Field-level and composite keys
- Cross-Field: Conditional validation based on other fields
- Custom: Script-based validation logic
State-based automation rules:
const workflowRule = {
name: 'high_value_alert',
object: 'customer_account',
triggerType: 'on_create_or_update',
criteria: { field: 'annual_revenue', operator: 'gt', value: 1000000 },
actions: [
{ type: 'email_alert', template: 'notify_sales_manager' },
{ type: 'field_update', field: 'priority', value: 'high' }
],
};Visual logic orchestration:
- Screen Flows: User-interactive wizards
- Autolaunched Flows: Backend automation
- Scheduled Flows: Time-based execution
Fine-grained access control:
const permissionSet = {
name: 'sales_user',
objectPermissions: {
customer_account: {
read: true,
create: true,
edit: true,
delete: false,
}
},
fieldPermissions: {
customer_account: {
annual_revenue: { read: true, edit: false }
}
}
};Row-level security:
- OWD Model: Organization-wide defaults
- Sharing Rules: Criteria-based sharing
- Manual Sharing: User-granted access
- Role Hierarchy: Inheritance-based access
┌─────────────────────────────────────────────────────────┐
│ Application Layer (UI, API, CLI) │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ ObjectQL Query Builder │
│ - Validates schema references │
│ - Checks permissions │
│ - Applies business rules │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Query Optimizer │
│ - Optimizes AST │
│ - Plans execution │
│ - Caches metadata │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Driver Layer │
│ - Translates AST to native queries │
│ - Handles driver-specific features │
│ - Manages connections │
└─────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────┐
│ Storage Backend (PostgreSQL, MongoDB, MySQL, etc.) │
└─────────────────────────────────────────────────────────┘
Drivers translate ObjectQL to native storage formats:
interface DriverInterface {
// CRUD Operations
create(object: string, data: Record<string, any>): Promise<Record>;
read(object: string, id: string): Promise<Record>;
update(object: string, id: string, data: Record<string, any>): Promise<Record>;
delete(object: string, id: string): Promise<void>;
// Query Operations
query(query: Query): Promise<Record[]>;
count(query: Query): Promise<number>;
// Schema Operations
describeObject(object: string): Promise<ObjectMetadata>;
listObjects(): Promise<string[]>;
}Computed fields with expression language:
{
name: 'total_value',
type: 'formula',
returnType: 'number',
expression: 'quantity * unit_price * (1 - discount_percent / 100)'
}Aggregate related records:
{
name: 'total_opportunities',
type: 'rollup',
relationshipField: 'account_id',
relatedObject: 'opportunity',
aggregateFunction: 'SUM',
aggregateField: 'amount'
}Reference other objects:
{
name: 'account_id',
type: 'lookup',
reference: 'customer_account',
displayField: 'account_name',
cascadeDelete: false
}Define indexes for query optimization:
const indexes = [
{ fields: ['email'], unique: true },
{ fields: ['industry', 'revenue'] },
{ fields: ['created_date'] }
];- Use field selection to limit data transfer
- Apply filters early in the query
- Use pagination for large result sets
- Leverage database indexes
- Cache object metadata
- Cache permission sets
- Use query result caching for reports
-
Schema Design
- Use appropriate field types
- Define relationships clearly
- Add validation rules early
- Index frequently queried fields
-
Query Design
- Select only needed fields
- Use efficient filters
- Implement pagination
- Avoid N+1 queries
-
Security
- Define OWD models
- Set field-level security
- Use sharing rules appropriately
- Audit access patterns
-
Performance
- Add database indexes
- Use formula fields sparingly
- Optimize rollup calculations
- Monitor query performance
For complete API reference, see Data Protocol References.