@ -21,7 +21,8 @@ The `db` object is the main entry point for all data operations.
```javascript
// Immutable pattern — each call creates a new builder
var baseQuery = db.query('Entity').where(x => x.Active);
var entityTable = await db.query('Entity');
var baseQuery = await entityTable.where(x => x.Active);
var cheap = baseQuery.where(x => x.Price < 100 ) ; / / baseQuery unchanged
var expensive = baseQuery.where(x => x.Price > 500); // baseQuery unchanged
```
@ -31,13 +32,15 @@ var expensive = baseQuery.where(x => x.Price > 500); // baseQuery unchanged
### Basic Queries
```javascript
var products = await db.query('LowCodeDemo.Products.Product')
var productTable = await db.query('LowCodeDemo.Products.Product');
var products = await productTable
.where(x => x.Price > 100)
.orderBy(x => x.Price)
.take(10)
.toList();
var result = await db.query('LowCodeDemo.Products.Product')
var resultTable = await db.query('LowCodeDemo.Products.Product');
var result = await resultTable
.where(x => x.Price > 100 & & x.Price < 500 )
.where(x => x.StockCount > 0)
.orderByDescending(x => x.Price)
@ -63,9 +66,12 @@ var result = await db.query('LowCodeDemo.Products.Product')
| `all(x => condition)` | Check if all records match | `Promise<boolean>` |
| `isEmpty()` | Check if no results | `Promise<boolean>` |
| `isSingle()` | Check if exactly one result | `Promise<boolean>` |
| `first()` / `firstOrDefault()` | Return first match or null | `Promise<object\|null>` |
| `last()` / `lastOrDefault()` | Return last match or null | `Promise<object\|null>` |
| `single()` / `singleOrDefault()` | Return single match or null | `Promise<object\|null>` |
| `first()` | Return first match, throws if empty | `Promise<object>` |
| `firstOrDefault()` | Return first match or null | `Promise<object\|null>` |
| `last()` | Return last match, throws if empty | `Promise<object>` |
| `lastOrDefault()` | Return last match or null | `Promise<object\|null>` |
| `single()` | Return single match, throws if empty/multiple | `Promise<object>` |
| `singleOrDefault()` | Return single match or null (throws if multiple) | `Promise<object\|null>` |
| `elementAt(index)` | Return element at index | `Promise<object\|null>` |
| `select(x => projection)` | Project to custom shape | `QueryBuilder` |
| `join(entity, alias, condition)` | Inner join | `QueryBuilder` |
@ -92,16 +98,18 @@ var minPrice = 100;
var config = { minStock: 10 };
var nested = { range: { min: 50, max: 200 } };
var result = await db.query('Entity').where(x => x.Price > minPrice).toList();
var result2 = await db.query('Entity').where(x => x.StockCount > config.minStock).toList();
var result3 = await db.query('Entity').where(x => x.Price >= nested.range.min).toList();
var entityTable = await db.query('Entity');
var result = await entityTable.where(x => x.Price > minPrice).toList();
var result2 = await entityTable.where(x => x.StockCount > config.minStock).toList();
var result3 = await entityTable.where(x => x.Price >= nested.range.min).toList();
```
### Contains / IN Operator
```javascript
var targetPrices = [50, 100, 200];
var products = await db.query('Entity')
var entityTable = await db.query('Entity');
var products = await entityTable
.where(x => targetPrices.includes(x.Price))
.toList();
```
@ -109,7 +117,8 @@ var products = await db.query('Entity')
### Select Projection
```javascript
var projected = await db.query('LowCodeDemo.Products.Product')
var productTable = await db.query('LowCodeDemo.Products.Product');
var projected = await productTable
.where(x => x.Price > 0)
.select(x => ({ ProductName: x.Name, ProductPrice: x.Price }))
.toList();
@ -120,7 +129,8 @@ var projected = await db.query('LowCodeDemo.Products.Product')
### Explicit Joins
```javascript
var orderLines = await db.query('LowCodeDemo.Orders.OrderLine')
var orderLineTable = await db.query('LowCodeDemo.Orders.OrderLine');
var orderLines = await orderLineTable
.join('LowCodeDemo.Products.Product', 'p', (ol, p) => ol.ProductId === p.Id)
.take(10)
.toList();
@ -135,7 +145,8 @@ orderLines.forEach(line => {
### Left Join
```javascript
var orders = await db.query('LowCodeDemo.Orders.Order')
var orderTable = await db.query('LowCodeDemo.Orders.Order');
var orders = await orderTable
.leftJoin('LowCodeDemo.Products.Product', 'p', (o, p) => o.CustomerId === p.Id)
.toList();
@ -149,18 +160,22 @@ orders.forEach(order => {
### LINQ-Style Join
```javascript
db.query('Order')
.join('LowCodeDemo.Products.Product',
o => o.ProductId,
p => p.Id)
var orderTable = await db.query('Order');
await orderTable.join(
'LowCodeDemo.Products.Product',
o => o.ProductId,
p => p.Id
);
```
### Join with Filtered Query
```javascript
var expensiveProducts = db.query('Product').where(p => p.Price > 100);
var productTable = await db.query('Product');
var expensiveProducts = await productTable.where(p => p.Price > 100);
var orders = await db.query('OrderLine')
var orderLineTable = await db.query('OrderLine');
var orders = await orderLineTable
.join(expensiveProducts,
ol => ol.ProductId,
p => p.Id)
@ -179,8 +194,9 @@ Set operations execute at the database level using SQL:
| `except(query)` | `EXCEPT` | Elements in first, not second |
```javascript
var cheap = db.query('Product').where(x => x.Price < = 100);
var popular = db.query('Product').where(x => x.Rating > 4);
var productTable = await db.query('Product');
var cheap = await productTable.where(x => x.Price < = 100);
var popular = await productTable.where(x => x.Rating > 4);
var bestDeals = await cheap.intersect(popular).toList();
var underrated = await cheap.except(popular).toList();
@ -200,15 +216,17 @@ All aggregations execute as SQL statements:
| `groupBy(x => x.Property)` | `GROUP BY ...` | `Promise<GroupResult[]>` |
```javascript
var totalValue = await db.query('Product').sum(x => x.Price);
var avgPrice = await db.query('Product').where(x => x.InStock).average(x => x.Price);
var cheapest = await db.query('Product').min(x => x.Price);
var productTable = await db.query('Product');
var totalValue = await productTable.sum(x => x.Price);
var avgPrice = await (await productTable.where(x => x.InStock)).average(x => x.Price);
var cheapest = await productTable.min(x => x.Price);
```
### GroupBy with Select
```javascript
var grouped = await db.query('Product')
var productTable = await db.query('Product');
var grouped = await productTable
.groupBy(x => x.Category)
.select(g => ({
Category: g.Key,
@ -237,7 +255,8 @@ var grouped = await db.query('Product')
### GroupBy with Items
```javascript
var grouped = await db.query('Product')
var productTable = await db.query('Product');
var grouped = await productTable
.groupBy(x => x.Category)
.select(g => ({
Category: g.Key,
@ -258,11 +277,12 @@ var grouped = await db.query('Product')
Math functions translate to SQL functions (ROUND, FLOOR, CEILING, ABS, etc.):
```javascript
var products = await db.query('Product')
var productTable = await db.query('Product');
var products = await productTable
.where(x => Math.round(x.Price) > 100)
.toList();
var result = await db.query('Product')
var result = await productTable
.where(x => Math.abs(x.Balance) < 10 & & Math . floor ( x . Rating ) > = 4)
.toList();
```
@ -380,7 +400,8 @@ All values are parameterized:
```javascript
var malicious = "'; DROP TABLE Products;--";
// Safely treated as a literal string — no injection
var result = await db.query('Entity').where(x => x.Name.includes(malicious)).count();
var entityTable = await db.query('Entity');
var result = await (await entityTable.where(x => x.Name.includes(malicious))).count();
```
### Blocked Features
@ -397,7 +418,8 @@ if (!context.commandArgs.getValue('Email').includes('@')) {
// Try-catch for safe execution
try {
var products = await db.query('Entity').where(x => x.Price > 0).toList();
var entityTable = await db.query('Entity');
var products = await entityTable.where(x => x.Price > 0).toList();
} catch (error) {
context.log('Query failed: ' + error.message);
}
@ -422,7 +444,8 @@ try {
var productId = context.commandArgs.getValue('ProductId');
var quantity = context.commandArgs.getValue('Quantity');
var product = await db.query('LowCodeDemo.Products.Product')
var productTable = await db.query('LowCodeDemo.Products.Product');
var product = await productTable
.where(x => x.Id === productId)
.first();
@ -435,11 +458,10 @@ context.commandArgs.setValue('TotalAmount', product.Price * quantity);
### Sales Dashboard (Custom Endpoint)
```javascript
var totalOrders = await db.query('LowCodeDemo.Orders.Order').count();
var delivered = await db.query('LowCodeDemo.Orders.Order')
.where(x => x.IsDelivered === true).count();
var revenue = await db.query('LowCodeDemo.Orders.Order')
.where(x => x.IsDelivered === true).sum(x => x.TotalAmount);
var orderTable = await db.query('LowCodeDemo.Orders.Order');
var totalOrders = await orderTable.count();
var delivered = await (await orderTable.where(x => x.IsDelivered === true)).count();
var revenue = await (await orderTable.where(x => x.IsDelivered === true)).sum(x => x.TotalAmount);
return ok({
orders: totalOrders,