412 lines
No EOL
9.3 KiB
Markdown
412 lines
No EOL
9.3 KiB
Markdown
# Data Operations
|
|
|
|
This section covers keywords for working with structured data in databases, spreadsheets, and in-memory collections. These keywords enable bots to query, transform, and persist data across various storage backends.
|
|
|
|
---
|
|
|
|
## Overview
|
|
|
|
General Bots provides a complete set of data operation keywords:
|
|
|
|
| Keyword | Purpose |
|
|
|---------|---------|
|
|
| [SAVE](keyword-save.md) | Persist data to storage |
|
|
| [INSERT](keyword-insert.md) | Add new records to tables |
|
|
| [UPDATE](keyword-update.md) | Modify existing records |
|
|
| [DELETE](keyword-delete.md) | Remove records from tables |
|
|
| [MERGE](keyword-merge.md) | Upsert (insert or update) records |
|
|
| [FILL](keyword-fill.md) | Populate templates with data |
|
|
| [MAP](keyword-map.md) | Transform collections |
|
|
| [FILTER](keyword-filter.md) | Select matching items |
|
|
| [AGGREGATE](keyword-aggregate.md) | Sum, count, average operations |
|
|
| [JOIN](keyword-join.md) | Combine related datasets |
|
|
| [PIVOT](keyword-pivot.md) | Reshape data tables |
|
|
| [GROUP BY](keyword-group-by.md) | Group records by field |
|
|
|
|
---
|
|
|
|
## Quick Examples
|
|
|
|
### Database Operations
|
|
|
|
```basic
|
|
' Insert a new record
|
|
INSERT INTO "customers" WITH
|
|
name = "John Doe",
|
|
email = "john@example.com",
|
|
created_at = NOW()
|
|
|
|
' Update existing records
|
|
UPDATE "customers" SET status = "active" WHERE email = "john@example.com"
|
|
|
|
' Delete records
|
|
DELETE FROM "customers" WHERE status = "inactive" AND last_login < "2024-01-01"
|
|
|
|
' Merge (upsert) - insert or update based on key
|
|
MERGE INTO "products" ON sku = "SKU-001" WITH
|
|
sku = "SKU-001",
|
|
name = "Widget",
|
|
price = 29.99,
|
|
stock = 100
|
|
```
|
|
|
|
### Collection Transformations
|
|
|
|
```basic
|
|
' Map - transform each item
|
|
prices = [10, 20, 30, 40]
|
|
with_tax = MAP prices WITH item * 1.1
|
|
' Result: [11, 22, 33, 44]
|
|
|
|
' Filter - select matching items
|
|
orders = FIND "orders"
|
|
large_orders = FILTER orders WHERE total > 100
|
|
' Returns only orders with total > 100
|
|
|
|
' Aggregate - calculate summaries
|
|
total_sales = AGGREGATE orders SUM total
|
|
order_count = AGGREGATE orders COUNT
|
|
avg_order = AGGREGATE orders AVERAGE total
|
|
```
|
|
|
|
### Data Analysis
|
|
|
|
```basic
|
|
' Group by category
|
|
sales_by_category = GROUP BY "sales" ON category
|
|
FOR EACH group IN sales_by_category
|
|
TALK group.category + ": $" + group.total
|
|
NEXT
|
|
|
|
' Join related tables
|
|
order_details = JOIN "orders" WITH "customers" ON customer_id = id
|
|
FOR EACH detail IN order_details
|
|
TALK detail.customer_name + " ordered " + detail.product
|
|
NEXT
|
|
|
|
' Pivot data for reports
|
|
monthly_pivot = PIVOT "sales" ROWS month COLUMNS product VALUES SUM(amount)
|
|
```
|
|
|
|
---
|
|
|
|
## Data Sources
|
|
|
|
### Supported Backends
|
|
|
|
| Backend | Use Case | Configuration |
|
|
|---------|----------|---------------|
|
|
| PostgreSQL | Primary database | `database-url` in config.csv |
|
|
| SQLite | Local/embedded | `database-provider,sqlite` |
|
|
| In-memory | Temporary data | Default for collections |
|
|
| CSV files | Import/export | Via READ/WRITE AS TABLE |
|
|
| Excel | Spreadsheet data | Via READ AS TABLE |
|
|
|
|
### Connection Configuration
|
|
|
|
```csv
|
|
name,value
|
|
database-provider,postgres
|
|
database-url,postgres://user:pass@localhost/botdb
|
|
database-pool-size,10
|
|
database-timeout,30
|
|
```
|
|
|
|
### Multiple Connections
|
|
|
|
```basic
|
|
' Use default connection
|
|
customers = FIND "customers"
|
|
|
|
' Use named connection
|
|
legacy_data = FIND "orders" ON "legacy_db"
|
|
warehouse_stock = FIND "inventory" ON "warehouse_db"
|
|
```
|
|
|
|
---
|
|
|
|
## Common Patterns
|
|
|
|
### CRUD Operations
|
|
|
|
```basic
|
|
' CREATE
|
|
customer_id = INSERT INTO "customers" WITH
|
|
name = customer_name,
|
|
email = customer_email,
|
|
phone = customer_phone
|
|
|
|
TALK "Customer created with ID: " + customer_id
|
|
|
|
' READ
|
|
customer = FIND "customers" WHERE id = customer_id
|
|
TALK "Found: " + customer.name
|
|
|
|
' UPDATE
|
|
UPDATE "customers" SET
|
|
last_contact = NOW(),
|
|
contact_count = contact_count + 1
|
|
WHERE id = customer_id
|
|
|
|
' DELETE
|
|
DELETE FROM "customers" WHERE id = customer_id AND confirmed = true
|
|
```
|
|
|
|
### Batch Operations
|
|
|
|
```basic
|
|
' Insert multiple records from data source
|
|
new_orders = READ "imports/orders.csv" AS TABLE
|
|
|
|
FOR EACH order IN new_orders
|
|
INSERT INTO "orders" WITH
|
|
product = order.product,
|
|
quantity = order.quantity,
|
|
price = order.price
|
|
NEXT
|
|
|
|
' Bulk update
|
|
UPDATE "products" SET on_sale = true WHERE category = "electronics"
|
|
```
|
|
|
|
### Data Transformation Pipeline
|
|
|
|
```basic
|
|
' Load raw data
|
|
raw_sales = READ "imports/sales-data.csv" AS TABLE
|
|
|
|
' Clean and transform
|
|
cleaned = FILTER raw_sales WHERE amount > 0 AND date IS NOT NULL
|
|
|
|
' Enrich with calculations
|
|
enriched = MAP cleaned WITH
|
|
tax = item.amount * 0.1,
|
|
total = item.amount * 1.1,
|
|
quarter = QUARTER(item.date)
|
|
|
|
' Aggregate for reporting
|
|
quarterly_totals = GROUP BY enriched ON quarter
|
|
summary = AGGREGATE quarterly_totals SUM total
|
|
|
|
' Save results
|
|
WRITE summary TO "reports/quarterly-summary.csv" AS TABLE
|
|
INSERT INTO "sales_reports" VALUES summary
|
|
```
|
|
|
|
### Lookup and Reference
|
|
|
|
```basic
|
|
' Simple lookup
|
|
product = FIND "products" WHERE sku = user_sku
|
|
IF product THEN
|
|
TALK "Price: $" + product.price
|
|
ELSE
|
|
TALK "Product not found"
|
|
END IF
|
|
|
|
' Lookup with join
|
|
order_with_customer = FIND "orders"
|
|
JOIN "customers" ON orders.customer_id = customers.id
|
|
WHERE orders.id = order_id
|
|
|
|
TALK "Order for " + order_with_customer.customer_name
|
|
```
|
|
|
|
---
|
|
|
|
## Query Syntax
|
|
|
|
### WHERE Clauses
|
|
|
|
```basic
|
|
' Equality
|
|
FIND "users" WHERE status = "active"
|
|
|
|
' Comparison
|
|
FIND "orders" WHERE total > 100
|
|
FIND "products" WHERE stock <= 10
|
|
|
|
' Multiple conditions
|
|
FIND "customers" WHERE country = "US" AND created_at > "2024-01-01"
|
|
FIND "items" WHERE category = "electronics" OR category = "accessories"
|
|
|
|
' NULL checks
|
|
FIND "leads" WHERE assigned_to IS NULL
|
|
FIND "orders" WHERE shipped_at IS NOT NULL
|
|
|
|
' Pattern matching
|
|
FIND "products" WHERE name LIKE "%widget%"
|
|
|
|
' IN lists
|
|
FIND "orders" WHERE status IN ["pending", "processing", "shipped"]
|
|
```
|
|
|
|
### ORDER BY
|
|
|
|
```basic
|
|
' Single column sort
|
|
FIND "products" ORDER BY price ASC
|
|
|
|
' Multiple column sort
|
|
FIND "orders" ORDER BY priority DESC, created_at ASC
|
|
|
|
' With limit
|
|
recent_orders = FIND "orders" ORDER BY created_at DESC LIMIT 10
|
|
```
|
|
|
|
### Aggregations
|
|
|
|
```basic
|
|
' Count records
|
|
total_customers = AGGREGATE "customers" COUNT
|
|
|
|
' Sum values
|
|
total_revenue = AGGREGATE "orders" SUM total
|
|
|
|
' Average
|
|
avg_order_value = AGGREGATE "orders" AVERAGE total
|
|
|
|
' Min/Max
|
|
cheapest = AGGREGATE "products" MIN price
|
|
most_expensive = AGGREGATE "products" MAX price
|
|
|
|
' With grouping
|
|
sales_by_region = AGGREGATE "sales" SUM amount GROUP BY region
|
|
```
|
|
|
|
---
|
|
|
|
## Error Handling
|
|
|
|
```basic
|
|
ON ERROR RESUME NEXT
|
|
|
|
result = INSERT INTO "orders" VALUES order_data
|
|
|
|
IF ERROR THEN
|
|
PRINT "Database error: " + ERROR_MESSAGE
|
|
|
|
IF INSTR(ERROR_MESSAGE, "duplicate") > 0 THEN
|
|
TALK "This order already exists."
|
|
ELSE IF INSTR(ERROR_MESSAGE, "constraint") > 0 THEN
|
|
TALK "Invalid data. Please check all fields."
|
|
ELSE
|
|
TALK "Sorry, I couldn't save your order. Please try again."
|
|
END IF
|
|
ELSE
|
|
TALK "Order saved successfully!"
|
|
END IF
|
|
```
|
|
|
|
### Transaction Handling
|
|
|
|
```basic
|
|
' Start transaction
|
|
BEGIN TRANSACTION
|
|
|
|
' Multiple operations
|
|
INSERT INTO "orders" VALUES order_data
|
|
UPDATE "inventory" SET stock = stock - quantity WHERE product_id = product_id
|
|
INSERT INTO "order_items" VALUES items
|
|
|
|
' Commit if all succeeded
|
|
IF NOT ERROR THEN
|
|
COMMIT
|
|
TALK "Order completed!"
|
|
ELSE
|
|
ROLLBACK
|
|
TALK "Order failed. All changes reverted."
|
|
END IF
|
|
```
|
|
|
|
---
|
|
|
|
## Performance Tips
|
|
|
|
### Use Indexes
|
|
|
|
Ensure database tables have appropriate indexes for frequently queried columns:
|
|
|
|
```sql
|
|
-- In database setup
|
|
CREATE INDEX idx_orders_customer ON orders(customer_id);
|
|
CREATE INDEX idx_orders_date ON orders(created_at);
|
|
CREATE INDEX idx_products_sku ON products(sku);
|
|
```
|
|
|
|
### Limit Results
|
|
|
|
```basic
|
|
' Avoid loading entire tables
|
|
' Bad:
|
|
all_orders = FIND "orders"
|
|
|
|
' Good:
|
|
recent_orders = FIND "orders" WHERE created_at > date_limit LIMIT 100
|
|
```
|
|
|
|
### Batch Operations
|
|
|
|
```basic
|
|
' Process large datasets in batches
|
|
page = 0
|
|
batch_size = 100
|
|
|
|
WHILE true
|
|
batch = FIND "records" LIMIT batch_size OFFSET page * batch_size
|
|
|
|
IF LEN(batch) = 0 THEN
|
|
EXIT WHILE
|
|
END IF
|
|
|
|
FOR EACH record IN batch
|
|
' Process record
|
|
NEXT
|
|
|
|
page = page + 1
|
|
WEND
|
|
```
|
|
|
|
---
|
|
|
|
## Configuration
|
|
|
|
Configure data operations in `config.csv`:
|
|
|
|
```csv
|
|
name,value
|
|
database-provider,postgres
|
|
database-url,postgres://localhost/botdb
|
|
database-pool-size,10
|
|
database-timeout,30
|
|
database-log-queries,false
|
|
database-max-rows,10000
|
|
```
|
|
|
|
---
|
|
|
|
## Security Considerations
|
|
|
|
1. **Parameterized queries** — All keywords use parameterized queries to prevent SQL injection
|
|
2. **Row limits** — Default limit on returned rows prevents memory exhaustion
|
|
3. **Access control** — Bots can only access their own data by default
|
|
4. **Audit logging** — All data modifications logged for compliance
|
|
5. **Encryption** — Sensitive data encrypted at rest
|
|
|
|
---
|
|
|
|
## See Also
|
|
|
|
- [SAVE](keyword-save.md) — Persist data
|
|
- [INSERT](keyword-insert.md) — Add records
|
|
- [UPDATE](keyword-update.md) — Modify records
|
|
- [DELETE](keyword-delete.md) — Remove records
|
|
- [MERGE](keyword-merge.md) — Upsert operations
|
|
- [FILL](keyword-fill.md) — Template population
|
|
- [MAP](keyword-map.md) — Transform collections
|
|
- [FILTER](keyword-filter.md) — Select items
|
|
- [AGGREGATE](keyword-aggregate.md) — Summaries
|
|
- [JOIN](keyword-join.md) — Combine datasets
|
|
- [PIVOT](keyword-pivot.md) — Reshape data
|
|
- [GROUP BY](keyword-group-by.md) — Group records
|
|
- [TABLE](keyword-table.md) — Create tables |