diff --git a/content/docs/references/system/DriverCapabilities.mdx b/content/docs/references/system/DriverCapabilities.mdx index 8d3bc4bfc..1bad92a9b 100644 --- a/content/docs/references/system/DriverCapabilities.mdx +++ b/content/docs/references/system/DriverCapabilities.mdx @@ -8,6 +8,12 @@ description: DriverCapabilities Schema Reference | Property | Type | Required | Description | | :--- | :--- | :--- | :--- | | **transactions** | `boolean` | ✅ | Supports transactions | +| **queryFilters** | `boolean` | ✅ | Supports WHERE clause filtering | +| **queryAggregations** | `boolean` | ✅ | Supports GROUP BY and aggregation functions | +| **querySorting** | `boolean` | ✅ | Supports ORDER BY sorting | +| **queryPagination** | `boolean` | ✅ | Supports LIMIT/OFFSET pagination | +| **queryWindowFunctions** | `boolean` | ✅ | Supports window functions with OVER clause | +| **querySubqueries** | `boolean` | ✅ | Supports subqueries | | **joins** | `boolean` | ✅ | Supports SQL joins | | **fullTextSearch** | `boolean` | ✅ | Supports full-text search | | **jsonFields** | `boolean` | ✅ | Supports JSON field types | diff --git a/content/docs/references/system/integration/DatasourceCapabilities.mdx b/content/docs/references/system/integration/DatasourceCapabilities.mdx index 1aed27769..c1e512544 100644 --- a/content/docs/references/system/integration/DatasourceCapabilities.mdx +++ b/content/docs/references/system/integration/DatasourceCapabilities.mdx @@ -7,9 +7,14 @@ description: DatasourceCapabilities Schema Reference | Property | Type | Required | Description | | :--- | :--- | :--- | :--- | -| **joins** | `boolean` | optional | | | **transactions** | `boolean` | optional | | +| **queryFilters** | `boolean` | optional | | +| **queryAggregations** | `boolean` | optional | | +| **querySorting** | `boolean` | optional | | +| **queryPagination** | `boolean` | optional | | +| **queryWindowFunctions** | `boolean` | optional | | +| **querySubqueries** | `boolean` | optional | | +| **joins** | `boolean` | optional | | | **fullTextSearch** | `boolean` | optional | | -| **aggregation** | `boolean` | optional | | -| **dynamicSchema** | `boolean` | optional | | | **readOnly** | `boolean` | optional | | +| **dynamicSchema** | `boolean` | optional | | diff --git a/packages/driver-memory/src/memory-driver.ts b/packages/driver-memory/src/memory-driver.ts index 407148caa..4f8c75edd 100644 --- a/packages/driver-memory/src/memory-driver.ts +++ b/packages/driver-memory/src/memory-driver.ts @@ -23,11 +23,22 @@ export class InMemoryDriver implements DriverInterface { } supports = { + // Transaction & Connection Management transactions: false, - joins: false, - fullTextSearch: false, - jsonFields: true, - arrayFields: true, + + // Query Operations + queryFilters: false, // TODO: Not implemented - basic find() doesn't handle filters + queryAggregations: false, // TODO: Not implemented - count() only returns total + querySorting: false, // TODO: Not implemented - find() doesn't handle sorting + queryPagination: true, // Basic pagination via 'top' is implemented + queryWindowFunctions: false, // TODO: Not implemented + querySubqueries: false, // TODO: Not implemented + joins: false, // TODO: Not implemented + + // Advanced Features + fullTextSearch: false, // TODO: Not implemented + jsonFields: true, // Native JS object support + arrayFields: true, // Native JS array support }; /** diff --git a/packages/spec/json-schema/Datasource.json b/packages/spec/json-schema/Datasource.json index df5e6b07a..e87509082 100644 --- a/packages/spec/json-schema/Datasource.json +++ b/packages/spec/json-schema/Datasource.json @@ -25,29 +25,49 @@ "capabilities": { "type": "object", "properties": { - "joins": { + "transactions": { "type": "boolean", "default": false }, - "transactions": { + "queryFilters": { "type": "boolean", "default": false }, - "fullTextSearch": { + "queryAggregations": { "type": "boolean", "default": false }, - "aggregation": { + "querySorting": { "type": "boolean", "default": false }, - "dynamicSchema": { + "queryPagination": { + "type": "boolean", + "default": false + }, + "queryWindowFunctions": { + "type": "boolean", + "default": false + }, + "querySubqueries": { + "type": "boolean", + "default": false + }, + "joins": { + "type": "boolean", + "default": false + }, + "fullTextSearch": { "type": "boolean", "default": false }, "readOnly": { "type": "boolean", "default": false + }, + "dynamicSchema": { + "type": "boolean", + "default": false } }, "additionalProperties": false, diff --git a/packages/spec/json-schema/DatasourceCapabilities.json b/packages/spec/json-schema/DatasourceCapabilities.json index 99b3a9c14..a25ff44a4 100644 --- a/packages/spec/json-schema/DatasourceCapabilities.json +++ b/packages/spec/json-schema/DatasourceCapabilities.json @@ -4,29 +4,49 @@ "DatasourceCapabilities": { "type": "object", "properties": { - "joins": { + "transactions": { "type": "boolean", "default": false }, - "transactions": { + "queryFilters": { "type": "boolean", "default": false }, - "fullTextSearch": { + "queryAggregations": { "type": "boolean", "default": false }, - "aggregation": { + "querySorting": { "type": "boolean", "default": false }, - "dynamicSchema": { + "queryPagination": { + "type": "boolean", + "default": false + }, + "queryWindowFunctions": { + "type": "boolean", + "default": false + }, + "querySubqueries": { + "type": "boolean", + "default": false + }, + "joins": { + "type": "boolean", + "default": false + }, + "fullTextSearch": { "type": "boolean", "default": false }, "readOnly": { "type": "boolean", "default": false + }, + "dynamicSchema": { + "type": "boolean", + "default": false } }, "additionalProperties": false diff --git a/packages/spec/json-schema/DriverCapabilities.json b/packages/spec/json-schema/DriverCapabilities.json index 4da7f6732..77d5e5c84 100644 --- a/packages/spec/json-schema/DriverCapabilities.json +++ b/packages/spec/json-schema/DriverCapabilities.json @@ -8,6 +8,30 @@ "type": "boolean", "description": "Supports transactions" }, + "queryFilters": { + "type": "boolean", + "description": "Supports WHERE clause filtering" + }, + "queryAggregations": { + "type": "boolean", + "description": "Supports GROUP BY and aggregation functions" + }, + "querySorting": { + "type": "boolean", + "description": "Supports ORDER BY sorting" + }, + "queryPagination": { + "type": "boolean", + "description": "Supports LIMIT/OFFSET pagination" + }, + "queryWindowFunctions": { + "type": "boolean", + "description": "Supports window functions with OVER clause" + }, + "querySubqueries": { + "type": "boolean", + "description": "Supports subqueries" + }, "joins": { "type": "boolean", "description": "Supports SQL joins" @@ -27,6 +51,12 @@ }, "required": [ "transactions", + "queryFilters", + "queryAggregations", + "querySorting", + "queryPagination", + "queryWindowFunctions", + "querySubqueries", "joins", "fullTextSearch", "jsonFields", diff --git a/packages/spec/json-schema/DriverDefinition.json b/packages/spec/json-schema/DriverDefinition.json index 0a40567be..d88b9c222 100644 --- a/packages/spec/json-schema/DriverDefinition.json +++ b/packages/spec/json-schema/DriverDefinition.json @@ -26,29 +26,49 @@ "capabilities": { "type": "object", "properties": { - "joins": { + "transactions": { "type": "boolean", "default": false }, - "transactions": { + "queryFilters": { "type": "boolean", "default": false }, - "fullTextSearch": { + "queryAggregations": { "type": "boolean", "default": false }, - "aggregation": { + "querySorting": { "type": "boolean", "default": false }, - "dynamicSchema": { + "queryPagination": { + "type": "boolean", + "default": false + }, + "queryWindowFunctions": { + "type": "boolean", + "default": false + }, + "querySubqueries": { + "type": "boolean", + "default": false + }, + "joins": { + "type": "boolean", + "default": false + }, + "fullTextSearch": { "type": "boolean", "default": false }, "readOnly": { "type": "boolean", "default": false + }, + "dynamicSchema": { + "type": "boolean", + "default": false } }, "additionalProperties": false diff --git a/packages/spec/json-schema/DriverInterface.json b/packages/spec/json-schema/DriverInterface.json index 09706e54c..b0a420a45 100644 --- a/packages/spec/json-schema/DriverInterface.json +++ b/packages/spec/json-schema/DriverInterface.json @@ -19,6 +19,30 @@ "type": "boolean", "description": "Supports transactions" }, + "queryFilters": { + "type": "boolean", + "description": "Supports WHERE clause filtering" + }, + "queryAggregations": { + "type": "boolean", + "description": "Supports GROUP BY and aggregation functions" + }, + "querySorting": { + "type": "boolean", + "description": "Supports ORDER BY sorting" + }, + "queryPagination": { + "type": "boolean", + "description": "Supports LIMIT/OFFSET pagination" + }, + "queryWindowFunctions": { + "type": "boolean", + "description": "Supports window functions with OVER clause" + }, + "querySubqueries": { + "type": "boolean", + "description": "Supports subqueries" + }, "joins": { "type": "boolean", "description": "Supports SQL joins" @@ -38,6 +62,12 @@ }, "required": [ "transactions", + "queryFilters", + "queryAggregations", + "querySorting", + "queryPagination", + "queryWindowFunctions", + "querySubqueries", "joins", "fullTextSearch", "jsonFields", diff --git a/packages/spec/src/system/datasource.zod.ts b/packages/spec/src/system/datasource.zod.ts index 80efdfebc..5ac9e5a80 100644 --- a/packages/spec/src/system/datasource.zod.ts +++ b/packages/spec/src/system/datasource.zod.ts @@ -51,18 +51,50 @@ export const DriverDefinitionSchema = z.object({ * and what to compute in memory. */ export const DatasourceCapabilities = z.object({ - /** Can execute SQL-like joins natively? */ - joins: z.boolean().default(false), + // ============================================================================ + // Transaction & Connection Management + // ============================================================================ + /** Can handle ACID transactions? */ transactions: z.boolean().default(false), + + // ============================================================================ + // Query Operations + // ============================================================================ + + /** Can execute WHERE clause filters natively? */ + queryFilters: z.boolean().default(false), + + /** Can perform aggregation (group by, sum, avg)? */ + queryAggregations: z.boolean().default(false), + + /** Can perform ORDER BY sorting? */ + querySorting: z.boolean().default(false), + + /** Can perform LIMIT/OFFSET pagination? */ + queryPagination: z.boolean().default(false), + + /** Can perform window functions? */ + queryWindowFunctions: z.boolean().default(false), + + /** Can perform subqueries? */ + querySubqueries: z.boolean().default(false), + + /** Can execute SQL-like joins natively? */ + joins: z.boolean().default(false), + + // ============================================================================ + // Advanced Features + // ============================================================================ + /** Can perform full-text search? */ fullTextSearch: z.boolean().default(false), - /** Can perform aggregation (group by, sum, avg)? */ - aggregation: z.boolean().default(false), - /** Is scheme-less (needs schema inference)? */ - dynamicSchema: z.boolean().default(false), + /** Is read-only? */ readOnly: z.boolean().default(false), + + /** Is scheme-less (needs schema inference)? */ + dynamicSchema: z.boolean().default(false), }); /** diff --git a/packages/spec/src/system/driver.test.ts b/packages/spec/src/system/driver.test.ts index 849fae3e3..0260fa78b 100644 --- a/packages/spec/src/system/driver.test.ts +++ b/packages/spec/src/system/driver.test.ts @@ -10,6 +10,12 @@ describe('DriverCapabilitiesSchema', () => { it('should accept valid capabilities', () => { const capabilities: DriverCapabilities = { transactions: true, + queryFilters: true, + queryAggregations: true, + querySorting: true, + queryPagination: true, + queryWindowFunctions: true, + querySubqueries: true, joins: true, fullTextSearch: true, jsonFields: true, @@ -22,6 +28,12 @@ describe('DriverCapabilitiesSchema', () => { it('should accept minimal capabilities', () => { const capabilities: DriverCapabilities = { transactions: false, + queryFilters: false, + queryAggregations: false, + querySorting: false, + queryPagination: false, + queryWindowFunctions: false, + querySubqueries: false, joins: false, fullTextSearch: false, jsonFields: false, @@ -35,6 +47,7 @@ describe('DriverCapabilitiesSchema', () => { const incomplete = { transactions: true, joins: true, + queryFilters: true, // missing other fields }; @@ -79,6 +92,12 @@ describe('DriverInterfaceSchema', () => { dropTable: async () => {}, supports: { transactions: true, + queryFilters: true, + queryAggregations: true, + querySorting: true, + queryPagination: true, + queryWindowFunctions: true, + querySubqueries: true, joins: true, fullTextSearch: true, jsonFields: true, @@ -114,6 +133,12 @@ describe('DriverInterfaceSchema', () => { dropTable: async (object: string) => {}, supports: { transactions: false, + queryFilters: false, + queryAggregations: false, + querySorting: false, + queryPagination: false, + queryWindowFunctions: false, + querySubqueries: false, joins: false, fullTextSearch: false, jsonFields: false, @@ -212,6 +237,12 @@ describe('DriverInterfaceSchema', () => { dropTable: async () => {}, supports: { transactions: false, + queryFilters: false, + queryAggregations: false, + querySorting: false, + queryPagination: false, + queryWindowFunctions: false, + querySubqueries: false, joins: false, fullTextSearch: false, jsonFields: false, @@ -285,6 +316,12 @@ describe('DriverInterfaceSchema', () => { dropTable: async () => {}, supports: { transactions: false, + queryFilters: false, + queryAggregations: false, + querySorting: false, + queryPagination: false, + queryWindowFunctions: false, + querySubqueries: false, joins: false, fullTextSearch: false, jsonFields: false, @@ -341,6 +378,12 @@ describe('DriverInterfaceSchema', () => { dropTable: async () => {}, supports: { transactions: false, + queryFilters: false, + queryAggregations: false, + querySorting: false, + queryPagination: false, + queryWindowFunctions: false, + querySubqueries: false, joins: false, fullTextSearch: false, jsonFields: false, @@ -375,6 +418,12 @@ describe('DriverInterfaceSchema', () => { dropTable: async () => {}, supports: { transactions: true, + queryFilters: true, + queryAggregations: true, + querySorting: true, + queryPagination: true, + queryWindowFunctions: false, + querySubqueries: true, joins: true, fullTextSearch: false, jsonFields: true, @@ -411,6 +460,12 @@ describe('DriverInterfaceSchema', () => { dropTable: async (object) => {}, supports: { transactions: true, + queryFilters: true, + queryAggregations: true, + querySorting: true, + queryPagination: true, + queryWindowFunctions: true, + querySubqueries: true, joins: true, fullTextSearch: true, jsonFields: true, @@ -445,6 +500,12 @@ describe('DriverInterfaceSchema', () => { dropTable: async (object) => {}, supports: { transactions: true, + queryFilters: true, + queryAggregations: true, + querySorting: true, + queryPagination: true, + queryWindowFunctions: false, // MongoDB has limited window function support + querySubqueries: true, joins: false, // MongoDB has limited join support fullTextSearch: true, jsonFields: true, // Native JSON support @@ -479,6 +540,12 @@ describe('DriverInterfaceSchema', () => { dropTable: async (object) => {}, supports: { transactions: false, // Salesforce doesn't support transactions + queryFilters: true, // SOQL WHERE clause + queryAggregations: true, // SOQL GROUP BY + querySorting: true, // SOQL ORDER BY + queryPagination: true, // SOQL LIMIT/OFFSET + queryWindowFunctions: false, // No window functions + querySubqueries: true, // SOQL supports subqueries joins: true, // SOQL supports relationships fullTextSearch: true, // SOSL jsonFields: false, // No native JSON type @@ -513,6 +580,12 @@ describe('DriverInterfaceSchema', () => { dropTable: async (object) => {}, supports: { transactions: true, // Redis supports transactions + queryFilters: false, // Limited query support - key-based lookup + queryAggregations: false, // No aggregation support + querySorting: false, // No native sorting + queryPagination: false, // No pagination support + queryWindowFunctions: false, // No window functions + querySubqueries: false, // No subqueries joins: false, // No join support fullTextSearch: false, // No native full-text search jsonFields: true, // RedisJSON module @@ -522,5 +595,45 @@ describe('DriverInterfaceSchema', () => { expect(() => DriverInterfaceSchema.parse(redisDriver)).not.toThrow(); }); + + it('should accept memory-like driver with limited query support', () => { + const memoryDriver: DriverInterface = { + name: 'memory', + version: '1.0.0', + connect: async () => {}, + disconnect: async () => {}, + checkHealth: async () => true, + execute: async () => ({}), + find: async (object, query) => [], + findOne: async (object, query) => null, + create: async (object, data) => data, + update: async (object, id, data) => data, + delete: async (object, id) => true, + count: async () => 0, + bulkCreate: async (object, data) => data, + bulkUpdate: async (object, updates) => updates, + bulkDelete: async (object, ids) => {}, + beginTransaction: async () => ({}), + commit: async (tx) => {}, + rollback: async (tx) => {}, + syncSchema: async (object, schema) => {}, + dropTable: async (object) => {}, + supports: { + transactions: false, // No transactions in memory + queryFilters: false, // Memory driver doesn't support query conditions - all filtering done in memory + queryAggregations: false, // No aggregation support + querySorting: false, // No native sorting + queryPagination: false, // No pagination support + queryWindowFunctions: false, // No window functions + querySubqueries: false, // No subqueries + joins: false, // No join support - joins done in memory + fullTextSearch: false, // No full-text search + jsonFields: true, // Memory can store any type + arrayFields: true, // Memory can store any type + }, + }; + + expect(() => DriverInterfaceSchema.parse(memoryDriver)).not.toThrow(); + }); }); }); diff --git a/packages/spec/src/system/driver.zod.ts b/packages/spec/src/system/driver.zod.ts index 57af5fa70..f4e303911 100644 --- a/packages/spec/src/system/driver.zod.ts +++ b/packages/spec/src/system/driver.zod.ts @@ -30,18 +30,68 @@ export const DriverOptionsSchema = z.object({ * This allows ObjectQL to adapt its behavior based on underlying database capabilities. */ export const DriverCapabilitiesSchema = z.object({ + // ============================================================================ + // Transaction & Connection Management + // ============================================================================ + /** * Whether the driver supports database transactions. * If true, beginTransaction, commit, and rollback must be implemented. */ transactions: z.boolean().describe('Supports transactions'), + // ============================================================================ + // Query Operations + // ============================================================================ + + /** + * Whether the driver supports WHERE clause filters. + * If false, ObjectQL will fetch all records and filter in memory. + * + * Example: Memory driver might not support complex filter conditions. + */ + queryFilters: z.boolean().describe('Supports WHERE clause filtering'), + + /** + * Whether the driver supports aggregation functions (COUNT, SUM, AVG, etc.). + * If false, ObjectQL will compute aggregations in memory. + */ + queryAggregations: z.boolean().describe('Supports GROUP BY and aggregation functions'), + + /** + * Whether the driver supports ORDER BY sorting. + * If false, ObjectQL will sort results in memory. + */ + querySorting: z.boolean().describe('Supports ORDER BY sorting'), + + /** + * Whether the driver supports LIMIT/OFFSET pagination. + * If false, ObjectQL will fetch all records and paginate in memory. + */ + queryPagination: z.boolean().describe('Supports LIMIT/OFFSET pagination'), + + /** + * Whether the driver supports window functions (ROW_NUMBER, RANK, LAG, LEAD, etc.). + * If false, ObjectQL will compute window functions in memory. + */ + queryWindowFunctions: z.boolean().describe('Supports window functions with OVER clause'), + + /** + * Whether the driver supports subqueries (nested SELECT statements). + * If false, ObjectQL will execute queries separately and combine results. + */ + querySubqueries: z.boolean().describe('Supports subqueries'), + /** * Whether the driver supports SQL-style joins. * If false, ObjectQL will fetch related data separately and join in memory. */ joins: z.boolean().describe('Supports SQL joins'), + // ============================================================================ + // Advanced Features + // ============================================================================ + /** * Whether the driver supports full-text search. * If true, text search queries can be pushed to the database.