adaptus2-orm
Version:
A multi-database ORM supporting MySQL, PostgreSQL, MongoDB, and Snowflake
869 lines (722 loc) • 29 kB
JavaScript
// examples/advanced-usage.js
const ORM = require('../index');
const { QueryBuilder } = require('../src/core/QueryBuilder');
const { MigrationManager } = require('../src/core/MigrationManager');
const { ConfigManager } = require('../src/utils/ConfigManager');
async function runAdvancedExamples() {
console.log('=== Advanced ORM Usage Examples ===\n');
const configManager = new ConfigManager();
// Example configurations for different databases
const configs = {
mysql: configManager.getConfig('mysql', {
host: 'localhost',
port: 3306,
user: 'root',
password: 'password',
database: 'advanced_orm_demo'
}),
postgresql: configManager.getConfig('postgresql', {
host: 'localhost',
port: 5432,
user: 'postgres',
password: 'password',
database: 'advanced_orm_demo'
}),
mongodb: configManager.getConfig('mongodb', {
uri: 'mongodb://localhost:27017/advanced_orm_demo',
database: 'advanced_orm_demo'
}),
snowflake: configManager.getConfig('snowflake', {
account: 'your_account',
user: 'your_user',
password: 'your_password',
warehouse: 'COMPUTE_WH',
database: 'ADVANCED_ORM_DEMO',
schema: 'PUBLIC'
})
};
// Example 1: Advanced Query Building
console.log('Example 1: Advanced Query Building\n');
await advancedQueryBuilding(configs.mysql);
// Example 2: Transaction Management
console.log('\nExample 2: Transaction Management\n');
await transactionManagement(configs.postgresql);
// Example 3: Schema Management
console.log('\nExample 3: Schema Management\n');
await schemaManagement(configs.mysql);
// Example 4: Migration System
console.log('\nExample 4: Migration System\n');
await migrationSystem(configs.mysql);
// Example 5: Bulk Operations
console.log('\nExample 5: Bulk Operations\n');
await bulkOperations(configs.postgresql);
// Example 6: Database-Specific Features
console.log('\nExample 6: Database-Specific Features\n');
await databaseSpecificFeatures(configs);
// Example 7: Connection Pooling
console.log('\nExample 7: Connection Pooling Management\n');
await connectionPooling(configs.mysql);
// Example 8: Error Handling & Recovery
console.log('\nExample 8: Error Handling & Recovery\n');
await errorHandlingExample(configs.mysql);
// Cleanup
console.log('\nCleaning up...');
await ORM.cleanup();
console.log('✅ Cleanup completed');
console.log('\n=== Advanced Examples Completed ===');
}
// Advanced Query Building
async function advancedQueryBuilding(config) {
try {
// Create complex query with joins, subqueries, and grouping
const queryBuilder = QueryBuilder.create(config.type)
.table('orders')
.select([
'orders.id',
'orders.total',
'customers.name',
'customers.email',
'COUNT(order_items.id) as item_count'
])
.join('customers', 'orders.customer_id', 'customers.id')
.leftJoin('order_items', 'orders.id', 'order_items.order_id')
.where('orders.status', 'completed')
.whereIn('orders.created_at', ['>=', new Date(Date.now() - 30 * 24 * 60 * 60 * 1000)])
.groupBy(['orders.id', 'customers.name', 'customers.email'])
.having('COUNT(order_items.id)', '>', 0)
.orderBy('orders.total', 'DESC')
.limit(10);
const { sql, params } = queryBuilder.toSQL();
console.log('Generated SQL:');
console.log(sql);
console.log('Parameters:', params);
// Execute the complex query
const result = await ORM.query(config, sql, params);
console.log('Query results:', result.data);
// Dynamic query building based on conditions
const dynamicQuery = buildDynamicQuery({
table: 'products',
filters: {
category: 'electronics',
priceRange: { min: 100, max: 500 },
inStock: true,
brand: ['Sony', 'Samsung', 'Apple']
},
sort: { field: 'price', direction: 'ASC' },
pagination: { page: 2, pageSize: 20 }
});
console.log('Dynamic SQL:', dynamicQuery.sql);
console.log('Dynamic Parameters:', dynamicQuery.params);
} catch (error) {
console.error('Query building error:', error);
}
}
// Helper function for dynamic query building
function buildDynamicQuery(options) {
let query = QueryBuilder.create('mysql')
.table(options.table)
.select('*');
// Apply filters dynamically
if (options.filters) {
for (const [key, value] of Object.entries(options.filters)) {
if (key === 'priceRange' && value.min && value.max) {
query = query.where('price', '>=', value.min)
.where('price', '<=', value.max);
} else if (Array.isArray(value)) {
query = query.whereIn(key, value);
} else if (typeof value === 'boolean') {
query = query.where(key, value);
} else {
query = query.where(key, value);
}
}
}
// Apply sorting
if (options.sort) {
query = query.orderBy(options.sort.field, options.sort.direction);
}
// Apply pagination
if (options.pagination) {
const offset = (options.pagination.page - 1) * options.pagination.pageSize;
query = query.limit(options.pagination.pageSize).offset(offset);
}
return query.toSQL();
}
// Transaction Management
async function transactionManagement(config) {
try {
const connection = await ORM.getDbConnection(config);
const adapter = ORM.databaseManager.getAdapter(config.type);
// Begin transaction
const txResult = await adapter.beginTransaction(connection);
console.log('Transaction started:', txResult.success);
try {
// Perform multiple operations in transaction
// Transfer funds between accounts
await ORM.update(config, 'accounts', {
where: { id: 1 },
data: { balance: { $dec: 100 } }
});
await ORM.update(config, 'accounts', {
where: { id: 2 },
data: { balance: { $inc: 100 } }
});
// Log the transaction
await ORM.create(config, 'transaction_logs', {
from_account: 1,
to_account: 2,
amount: 100,
type: 'transfer',
timestamp: new Date()
});
// Commit transaction
await adapter.commit(connection);
console.log('✅ Transaction committed successfully');
} catch (error) {
// Rollback on error
await adapter.rollback(connection);
console.error('❌ Transaction rolled back:', error);
throw error;
}
// Nested transaction example (savepoints)
await nestedTransactionExample(config);
} catch (error) {
console.error('Transaction management error:', error);
}
}
// Nested Transaction (Savepoint) Example
async function nestedTransactionExample(config) {
try {
console.log('\nNested Transaction Example:');
// This would use savepoints for databases that support them
const connection = await ORM.getDbConnection(config);
// Begin main transaction
await ORM.query(config, 'BEGIN');
try {
// Create an order
const order = await ORM.create(config, 'orders', {
customer_id: 1,
total: 0,
status: 'pending'
});
console.log('Order created:', order.data);
// Create savepoint
await ORM.query(config, 'SAVEPOINT order_items');
try {
// Add order items
const items = [
{ order_id: order.data.insertId, product_id: 1, quantity: 2, price: 50 },
{ order_id: order.data.insertId, product_id: 2, quantity: 1, price: 100 }
];
for (const item of items) {
await ORM.create(config, 'order_items', item);
}
// Update order total
const total = items.reduce((sum, item) => sum + (item.quantity * item.price), 0);
await ORM.update(config, 'orders', {
where: { id: order.data.insertId },
data: { total, status: 'confirmed' }
});
// Release savepoint (commit nested)
await ORM.query(config, 'RELEASE SAVEPOINT order_items');
} catch (error) {
// Rollback to savepoint
await ORM.query(config, 'ROLLBACK TO SAVEPOINT order_items');
console.error('Rolled back to savepoint');
throw error;
}
// Commit main transaction
await ORM.query(config, 'COMMIT');
console.log('✅ Nested transaction completed');
} catch (error) {
await ORM.query(config, 'ROLLBACK');
console.error('❌ Main transaction rolled back');
throw error;
}
} catch (error) {
console.error('Nested transaction error:', error);
}
}
// Schema Management
async function schemaManagement(config) {
try {
// Create tables with complex relationships
await createComplexSchema(config);
// Schema introspection
const tables = await introspectSchema(config);
console.log('Database tables:', tables);
// Schema modifications
await modifySchema(config);
// Index management
await manageIndexes(config);
} catch (error) {
console.error('Schema management error:', error);
}
}
// Create Complex Schema
async function createComplexSchema(config) {
console.log('Creating complex schema...');
// Users table
await ORM.createTable(config, 'users', {
columns: {
id: { type: 'integer', primaryKey: true, autoIncrement: true },
email: { type: 'string', required: true, unique: true },
password: { type: 'string', required: true },
profile: { type: 'json' },
created_at: { type: 'timestamp', default: 'CURRENT_TIMESTAMP' },
updated_at: { type: 'timestamp', default: 'CURRENT_TIMESTAMP' }
},
indexes: {
idx_email: { columns: ['email'], unique: true },
idx_created_at: { columns: ['created_at'] }
}
});
// Posts table with relationships
await ORM.createTable(config, 'posts', {
columns: {
id: { type: 'integer', primaryKey: true, autoIncrement: true },
user_id: { type: 'integer', required: true },
title: { type: 'string', required: true },
content: { type: 'text' },
status: { type: 'enum', values: ['draft', 'published', 'archived'] },
tags: { type: 'json' },
published_at: { type: 'timestamp' },
created_at: { type: 'timestamp', default: 'CURRENT_TIMESTAMP' }
},
foreignKeys: [
{
column: 'user_id',
references: { table: 'users', column: 'id' },
onDelete: 'CASCADE',
onUpdate: 'CASCADE'
}
],
indexes: {
idx_user_id: { columns: ['user_id'] },
idx_status: { columns: ['status'] },
idx_published_at: { columns: ['published_at'] }
}
});
console.log('✅ Complex schema created');
}
// Schema Introspection
async function introspectSchema(config) {
console.log('Introspecting schema...');
const tables = [];
// Get all tables
const tablesResult = await ORM.query(config, `
SELECT table_name
FROM information_schema.tables
WHERE table_schema = DATABASE()
AND table_type = 'BASE TABLE'
`);
if (tablesResult.success) {
for (const table of tablesResult.data) {
const tableName = table.table_name || table.TABLE_NAME;
// Get table structure
const structure = await ORM.schemaManager.describeTable(connection, config.type, tableName);
if (structure.success) {
tables.push({
name: tableName,
columns: structure.data
});
}
}
}
return tables;
}
// Modify Schema
async function modifySchema(config) {
console.log('Modifying schema...');
// Add new column
await ORM.schemaManager.addColumn(await ORM.getDbConnection(config), config.type, 'users', 'phone', {
type: 'string',
nullable: true,
length: 20
});
// Modify existing column
await ORM.query(config, `
ALTER TABLE posts
MODIFY COLUMN content LONGTEXT
`);
console.log('✅ Schema modified');
}
// Index Management
async function manageIndexes(config) {
console.log('Managing indexes...');
// Create composite index
await ORM.schemaManager.createIndex(
await ORM.getDbConnection(config),
config.type,
'posts',
'idx_user_status',
{
columns: ['user_id', 'status'],
unique: false
}
);
// Create partial index (PostgreSQL)
if (config.type === 'postgresql') {
await ORM.query(config, `
CREATE INDEX idx_published_posts
ON posts (published_at)
WHERE status = 'published'
`);
}
console.log('✅ Indexes managed');
}
// Migration System
async function migrationSystem(config) {
try {
const migrationManager = new MigrationManager(ORM, {
...config,
migrationsPath: './migrations/advanced_demo'
});
// Initialize migration system
await migrationManager.initialize();
console.log('Migration system initialized');
// Create migrations programmatically
await createAdvancedMigrations(migrationManager);
// Run migrations
const migrateResult = await migrationManager.migrate();
console.log('Migration result:', migrateResult);
// Show migration status
const status = await migrationManager.status();
console.log('\nMigration Status:');
console.log('Total:', status.data.summary.total);
console.log('Executed:', status.data.summary.executed);
console.log('Pending:', status.data.summary.pending);
// Demonstrate rollback
const rollbackResult = await migrationManager.rollback();
console.log('Rollback result:', rollbackResult);
} catch (error) {
console.error('Migration system error:', error);
}
}
// Create Advanced Migrations
async function createAdvancedMigrations(migrationManager) {
// Create initial schema migration
await migrationManager.create('create_advanced_schema');
// Create data migration
await migrationManager.create('seed_initial_data');
// Create transformation migration
await migrationManager.create('transform_user_profiles');
console.log('✅ Advanced migrations created');
}
// Bulk Operations
async function bulkOperations(config) {
try {
const adapter = ORM.databaseManager.getAdapter(config.type);
const connection = await ORM.getDbConnection(config);
// Bulk insert
const bulkData = Array.from({ length: 1000 }, (_, i) => ({
name: `Bulk User ${i}`,
email: `bulk${i}@example.com`,
created_at: new Date()
}));
console.time('Bulk Insert');
const bulkInsertResult = await adapter.bulkInsert(connection, 'users', bulkData);
console.timeEnd('Bulk Insert');
console.log('Bulk insert result:', bulkInsertResult);
// Bulk update using raw query
console.time('Bulk Update');
const bulkUpdateResult = await ORM.query(config, `
UPDATE users
SET updated_at = NOW()
WHERE created_at > ?
`, [new Date(Date.now() - 24 * 60 * 60 * 1000)]);
console.timeEnd('Bulk Update');
console.log('Bulk update result:', bulkUpdateResult);
// Bulk upsert
const upsertData = Array.from({ length: 100 }, (_, i) => ({
id: i + 1,
name: `Updated User ${i}`,
email: `updated${i}@example.com`,
profile: JSON.stringify({ plan: 'premium' })
}));
console.time('Bulk Upsert');
const results = [];
for (const item of upsertData) {
const result = await adapter.upsert(
connection,
'users',
item,
['id'],
['name', 'email', 'profile']
);
results.push(result);
}
console.timeEnd('Bulk Upsert');
console.log('Bulk upsert completed:', results.length);
} catch (error) {
console.error('Bulk operations error:', error);
}
}
// Database-Specific Features
async function databaseSpecificFeatures(configs) {
try {
// MySQL-specific features
if (configs.mysql) {
console.log('MySQL-specific features:');
await mysqlSpecificFeatures(configs.mysql);
}
// PostgreSQL-specific features
if (configs.postgresql) {
console.log('\nPostgreSQL-specific features:');
await postgresqlSpecificFeatures(configs.postgresql);
}
// MongoDB-specific features
if (configs.mongodb) {
console.log('\nMongoDB-specific features:');
await mongodbSpecificFeatures(configs.mongodb);
}
// Snowflake-specific features
if (configs.snowflake) {
console.log('\nSnowflake-specific features:');
await snowflakeSpecificFeatures(configs.snowflake);
}
} catch (error) {
console.error('Database-specific features error:', error);
}
}
// MySQL-specific features
async function mysqlSpecificFeatures(config) {
try {
const adapter = ORM.databaseManager.getAdapter(config.type);
const connection = await ORM.getDbConnection(config);
// JSON column operations
await ORM.create(config, 'user_preferences', {
user_id: 1,
preferences: JSON.stringify({
theme: 'dark',
notifications: true,
language: 'en'
})
});
// Query JSON column
const jsonQuery = await ORM.query(config, `
SELECT * FROM user_preferences
WHERE JSON_EXTRACT(preferences, '$.theme') = 'dark'
`);
console.log('JSON query result:', jsonQuery.data);
// Full-text search
await ORM.query(config, `
ALTER TABLE posts
ADD FULLTEXT(title, content)
`);
const fullTextResult = await ORM.query(config, `
SELECT *, MATCH(title, content) AGAINST(? IN NATURAL LANGUAGE MODE) as score
FROM posts
WHERE MATCH(title, content) AGAINST(? IN NATURAL LANGUAGE MODE)
ORDER BY score DESC
`, ['javascript tutorial', 'javascript tutorial']);
console.log('Full-text search result:', fullTextResult.data);
} catch (error) {
console.error('MySQL-specific error:', error);
}
}
// PostgreSQL-specific features
async function postgresqlSpecificFeatures(config) {
try {
const adapter = ORM.databaseManager.getAdapter(config.type);
const connection = await ORM.getDbConnection(config);
// JSONB operations
await adapter.jsonbQuery(connection, 'users', 'profile', '{"plan": "premium"}');
// Array operations
await ORM.create(config, 'products', {
name: 'Multi-tool',
tags: ['tools', 'hardware', 'outdoor'],
categories: [1, 2, 3]
});
const arrayResult = await adapter.arrayContains(connection, 'products', 'tags', 'tools');
console.log('Array query result:', arrayResult.data);
// Full-text search with ranking
const searchResult = await adapter.fullTextSearch(
connection,
'posts',
'content',
'javascript & tutorial',
{ ranked: true }
);
console.log('Full-text search with ranking:', searchResult.data);
// Create extension
await adapter.createExtension(connection, 'uuid-ossp');
// Use UUID
await ORM.query(config, `
CREATE TABLE sessions (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY,
user_id INTEGER,
created_at TIMESTAMP DEFAULT NOW()
)
`);
} catch (error) {
console.error('PostgreSQL-specific error:', error);
}
}
// MongoDB-specific features
async function mongodbSpecificFeatures(config) {
try {
const adapter = ORM.databaseManager.getAdapter(config.type);
const connection = await ORM.getDbConnection(config);
// Aggregation pipeline
const aggregationResult = await adapter.query(connection, [
{ $match: { status: 'active' } },
{ $group: {
_id: '$category',
count: { $sum: 1 },
totalValue: { $sum: '$value' }
}},
{ $sort: { totalValue: -1 } }
], { collection: 'products' });
console.log('Aggregation result:', aggregationResult.data);
// Create compound index
await adapter.createIndex(connection, 'products',
{ category: 1, status: 1, value: -1 },
{ name: 'idx_compound' }
);
// Text search
await adapter.createIndex(connection, 'products',
{ name: 'text', description: 'text' },
{ name: 'idx_text_search' }
);
const textSearchResult = await adapter.query(connection, [
{ $match: { $text: { $search: 'javascript tutorial' } } },
{ $addFields: { score: { $meta: 'textScore' } } },
{ $sort: { score: -1 } }
], { collection: 'products' });
console.log('Text search result:', textSearchResult.data);
} catch (error) {
console.error('MongoDB-specific error:', error);
}
}
// Snowflake-specific features
async function snowflakeSpecificFeatures(config) {
try {
const adapter = ORM.databaseManager.getAdapter(config.type);
const connection = await ORM.getDbConnection(config);
// Warehouse management
await adapter.switchWarehouse(connection, 'ANALYTICS_WH');
const currentWarehouse = await adapter.getCurrentWarehouse(connection);
console.log('Current warehouse:', currentWarehouse.data);
// Time travel
const timeTravelResult = await adapter.queryTimeTravelBefore(
connection,
'orders',
'2024-01-01 00:00:00'
);
console.log('Time travel result:', timeTravelResult.data);
// Clone table
await adapter.cloneTable(connection, 'users', 'users_backup');
console.log('Table cloned successfully');
// VARIANT operations
await adapter.queryVariant(connection, 'events', 'data', 'user_id');
// Bulk loading from stage
await adapter.createStage(connection, 'my_stage', 's3://mybucket/data/', {
aws_key_id: 'your_key',
aws_secret_key: 'your_secret'
});
await adapter.copyInto(connection, 'bulk_data', 'my_stage', '*.csv', {
fileFormat: '(TYPE = CSV)',
onError: 'CONTINUE'
});
// Query history
const queryHistory = await adapter.getQueryHistory(connection, {
startTime: '2024-01-01',
limit: 10
});
console.log('Query history:', queryHistory.data);
} catch (error) {
console.error('Snowflake-specific error:', error);
}
}
// Connection Pooling
async function connectionPooling(config) {
try {
console.log('Connection pooling demo...');
// Multiple simultaneous connections
const connections = await Promise.all([
ORM.getDbConnection(config),
ORM.getDbConnection(config),
ORM.getDbConnection(config),
ORM.getDbConnection(config),
ORM.getDbConnection(config)
]);
console.log('Created 5 connections (should reuse pool)');
// Perform concurrent operations
const operations = connections.map(async (conn, index) => {
return ORM.query(config, `SELECT ${index + 1} as connection_id`);
});
const results = await Promise.all(operations);
console.log('Concurrent operation results:', results.map(r => r.data));
// Check pool status (implementation specific)
console.log('Pool connections active');
// Close specific connections (if needed)
await ORM.closeAllMysqlPools();
console.log('MySQL pools closed');
} catch (error) {
console.error('Connection pooling error:', error);
}
}
// Error Handling & Recovery
async function errorHandlingExample(config) {
try {
console.log('Error handling demo...');
// Handling connection errors
try {
const badConfig = { ...config, password: 'wrong_password' };
await ORM.getDbConnection(badConfig);
} catch (error) {
console.log('✅ Caught connection error:', error.message);
}
// Handling constraint violations
try {
await ORM.create(config, 'users', {
email: 'duplicate@example.com',
password: 'password'
});
// This should fail due to unique constraint
await ORM.create(config, 'users', {
email: 'duplicate@example.com',
password: 'password'
});
} catch (error) {
console.log('✅ Caught constraint violation:', error.message);
}
// Query timeout handling
try {
await ORM.query(config, 'SELECT SLEEP(10)'); // This might timeout
} catch (error) {
console.log('✅ Caught timeout error:', error.message);
}
// Transaction error handling
const connection = await ORM.getDbConnection(config);
const adapter = ORM.databaseManager.getAdapter(config.type);
await adapter.beginTransaction(connection);
try {
await ORM.create(config, 'test_table', { name: 'Test' });
// This will fail if column doesn't exist
await ORM.create(config, 'test_table', { nonexistent_column: 'Value' });
await adapter.commit(connection);
} catch (error) {
console.log('✅ Transaction error handled, rolling back...');
await adapter.rollback(connection);
}
} catch (error) {
console.error('Error handling example error:', error);
}
}
// Run all examples
if (require.main === module) {
runAdvancedExamples().catch(console.error);
}
module.exports = {
runAdvancedExamples,
advancedQueryBuilding,
transactionManagement,
schemaManagement,
migrationSystem,
bulkOperations,
databaseSpecificFeatures,
connectionPooling,
errorHandlingExample
};