### Install Inquire Core and Adapters Source: https://github.com/stackpress/inquire/blob/main/packages/inquire/README.md Installs the main Inquire library and specific database adapters for MySQL, PostgreSQL, and SQLite. ```bash npm install @stackpress/inquire # For MySQL npm install @stackpress/inquire-mysql2 mysql2 # For PostgreSQL npm install @stackpress/inquire-pg pg # For SQLite npm install @stackpress/inquire-sqlite3 better-sqlite3 ``` -------------------------------- ### Install Inquire Core and Adapters Source: https://github.com/stackpress/inquire/blob/main/README.md Installs the main Inquire library and specific database adapters for MySQL, PostgreSQL, and SQLite. ```bash npm install @stackpress/inquire # For MySQL npm install @stackpress/inquire-mysql2 mysql2 # For PostgreSQL npm install @stackpress/inquire-pg pg # For SQLite npm install @stackpress/inquire-sqlite3 better-sqlite3 ``` -------------------------------- ### Insert Data with Inquire Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Shows how to insert single and multiple records into a table, including examples of using the 'returning' clause for PostgreSQL and SQLite. ```typescript // Insert single record await engine.insert('users') .values({ name: 'John Doe', email: 'john@example.com' }); // Insert multiple records await engine.insert('users') .values([ { name: 'Alice Smith', email: 'alice@example.com' }, { name: 'Bob Johnson', email: 'bob@example.com' }, { name: 'Carol Williams', email: 'carol@example.com' } ]); // Insert with returning (PostgreSQL/SQLite) const newUsers = await engine.insert('users') .values({ name: 'Jane Doe', email: 'jane@example.com' }) .returning('*'); ``` -------------------------------- ### Blog Application Schema and Data Retrieval Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Provides a real-world example of creating database schemas for a blog application, including 'categories' and 'posts' tables with relationships, indexes, and foreign keys. It also shows how to select published posts with their categories using an inner join and ordering. ```typescript // Create blog schema await engine.create('categories') .addField('id', { type: 'INTEGER', autoIncrement: true }) .addField('name', { type: 'VARCHAR', length: 100 }) .addField('slug', { type: 'VARCHAR', length: 100 }) .addPrimaryKey('id') .addUniqueKey('unique_slug', ['slug']); await engine.create('posts') .addField('id', { type: 'INTEGER', autoIncrement: true }) .addField('title', { type: 'VARCHAR', length: 255 }) .addField('slug', { type: 'VARCHAR', length: 255 }) .addField('content', { type: 'TEXT' }) .addField('excerpt', { type: 'TEXT' }) .addField('category_id', { type: 'INTEGER' }) .addField('published', { type: 'BOOLEAN', default: false }) .addField('created_at', { type: 'TIMESTAMP', default: 'CURRENT_TIMESTAMP' }) .addField('updated_at', { type: 'TIMESTAMP', default: 'CURRENT_TIMESTAMP' }) .addPrimaryKey('id') .addUniqueKey('unique_slug', ['slug']) .addIndex('idx_category', ['category_id']) .addIndex('idx_published', ['published']) .addForeignKey('fk_category', { local: ['category_id'], foreign: { table: 'categories', columns: ['id'] } }); // Get published posts with categories const publishedPosts = await engine.select([ 'p.id', 'p.title', 'p.slug', 'p.excerpt', 'p.created_at', 'c.name as category_name', 'c.slug as category_slug' ]) .from('posts p') .innerJoin('categories c', 'p.category_id = c.id') .where('p.published = ?', [true]) .orderBy('p.created_at', 'DESC') .limit(10); ``` -------------------------------- ### Install @stackpress/inquire-pg Source: https://github.com/stackpress/inquire/blob/main/packages/inquire-pg/README.md Installs the '@stackpress/inquire-pg' package using npm. This is the first step to integrate PostgreSQL connectivity with the Inquire library. ```bash $ npm i @stackpress/inquire-pg ``` -------------------------------- ### Basic Database Transactions Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Provides an example of executing multiple database operations within a single transaction. If any operation within the transaction fails, all changes are rolled back. This example inserts a user, their profile, and initial posts. ```typescript const result = await engine.transaction(async (trx) => { // Insert user const userResult = await trx.insert('users') .values({ name: 'Alice', email: 'alice@example.com' }); // Insert user profile await trx.insert('profiles') .values({ user_id: userResult.insertId, bio: 'Software developer', website: 'https://alice.dev' }); // Insert initial posts await trx.insert('posts') .values([ { user_id: userResult.insertId, title: 'Hello World', content: 'My first post!' }, { user_id: userResult.insertId, title: 'About Me', content: 'Learn more about me...' } ]); return { userId: userResult.insertId, success: true }; }); ``` -------------------------------- ### Complete Table Creation Example Source: https://github.com/stackpress/inquire/blob/main/docs/builders/Create.md A comprehensive example demonstrating the creation of a complex 'blog_posts' table with various field types, constraints, indexes, and foreign keys. ```typescript await engine.create('blog_posts') .addField('id', { type: 'INTEGER', autoIncrement: true, unsigned: true }) .addField('user_id', { type: 'INTEGER', unsigned: true, nullable: false }) .addField('category_id', { type: 'INTEGER', unsigned: true, nullable: true }) .addField('title', { type: 'VARCHAR', length: 255, nullable: false }) .addField('slug', { type: 'VARCHAR', length: 255, nullable: false }) .addField('excerpt', { type: 'TEXT', nullable: true }) .addField('content', { type: 'LONGTEXT', nullable: false }) .addField('featured_image', { type: 'VARCHAR', length: 500, nullable: true }) .addField('published', { type: 'BOOLEAN', default: false }) .addField('views', { type: 'INTEGER', unsigned: true, default: 0 }) .addField('created_at', { type: 'TIMESTAMP', default: 'CURRENT_TIMESTAMP' }) .addField('updated_at', { type: 'TIMESTAMP', default: 'CURRENT_TIMESTAMP' }) .addPrimaryKey('id') .addUniqueKey('unique_slug', ['slug']) .addIndex('idx_user_published', ['user_id', 'published']) .addIndex('idx_category', ['category_id']) .addIndex('idx_created_at', ['created_at']) .addForeignKey('fk_user', { local: ['user_id'], foreign: { table: 'users', columns: ['id'] }, onUpdate: 'CASCADE', onDelete: 'CASCADE' }) .addForeignKey('fk_category', { local: ['category_id'], foreign: { table: 'categories', columns: ['id'] }, onUpdate: 'CASCADE', onDelete: 'SET NULL' }); ``` -------------------------------- ### Create Tables with Inquire Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Demonstrates how to create tables with primary and unique keys, and how to define foreign key constraints with cascading deletes using the Inquire SQL library. ```typescript await engine.create('users') .addField('id', { type: 'INTEGER', autoIncrement: true }) .addField('name', { type: 'VARCHAR', length: 255 }) .addField('email', { type: 'VARCHAR', length: 255 }) .addField('created_at', { type: 'TIMESTAMP', default: 'CURRENT_TIMESTAMP' }) .addPrimaryKey('id') .addUniqueKey('unique_email', ['email']); // Table with foreign keys await engine.create('posts') .addField('id', { type: 'INTEGER', autoIncrement: true }) .addField('user_id', { type: 'INTEGER' }) .addField('title', { type: 'VARCHAR', length: 255 }) .addField('content', { type: 'TEXT' }) .addField('published', { type: 'BOOLEAN', default: false }) .addPrimaryKey('id') .addForeignKey('fk_user', { local: ['user_id'], foreign: { table: 'users', columns: ['id'] }, onDelete: 'CASCADE' }); ``` -------------------------------- ### Update Data with Inquire Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Provides examples for updating single or multiple records in a table, including setting new values and applying conditions. ```typescript // Update single record await engine.update('users') .set({ email: 'newemail@example.com' }) .where('id = ?', [1]); // Update multiple fields await engine.update('users') .set({ name: 'John Smith', email: 'johnsmith@example.com', updated_at: new Date() }) .where('id = ?', [1]); // Update with conditions await engine.update('posts') .set({ published: true }) .where('user_id = ?', [1]) .where('created_at > ?', [new Date('2024-01-01')]); ``` -------------------------------- ### Aggregations with Inquire Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Shows how to perform aggregations like COUNT, MAX, and MIN, and how to use GROUP BY and HAVING clauses to filter aggregated results. ```typescript // Group by with aggregations const userStats = await engine.select([ 'user_id', 'COUNT(*) as post_count', 'MAX(created_at) as latest_post', 'MIN(created_at) as first_post' ]) .from('posts') .where('published = ?', [true]) .groupBy('user_id') .having('COUNT(*) > ?', [5]) .orderBy('post_count', 'DESC'); ``` -------------------------------- ### Select Data with Inquire Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Illustrates various ways to select data, including selecting all columns, specific columns, filtering with WHERE clauses, ordering, limiting results, and performing joins. ```typescript // Basic select const allUsers = await engine.select('*').from('users'); // Select specific columns const userNames = await engine.select(['id', 'name']).from('users'); // Select with conditions const activeUsers = await engine.select('*') .from('users') .where('active = ?', [true]) .where('created_at > ?', [new Date('2024-01-01')]); // Select with ordering and limiting const recentUsers = await engine.select('*') .from('users') .orderBy('created_at', 'DESC') .limit(10) .offset(20); // Select with joins const usersWithPosts = await engine.select([ 'u.id', 'u.name', 'u.email', 'p.title', 'p.content' ]) .from('users u') .leftJoin('posts p', 'u.id = p.user_id') .where('u.active = ?', [true]); ``` -------------------------------- ### Generic Migration Example Source: https://github.com/stackpress/inquire/blob/main/docs/dialects/README.md Presents a generic migration script for creating a 'users' table that is compatible across different database dialects. ```typescript // Generic migration that works across dialects await engine.create('users') .field('id', { type: 'int', autoIncrement: true }) .field('name', { type: 'varchar', length: 255 }) .field('active', { type: 'boolean', default: true }) .field('data', { type: 'json' }) .primary('id'); ``` -------------------------------- ### Complex Joins with Inquire Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Shows how to perform complex queries involving multiple joins with aliases to retrieve data from related tables. ```typescript // Multiple joins with aliases const complexQuery = await engine.select([ 'u.id as user_id', 'u.name as user_name', 'p.title as post_title', 'c.content as comment_content', 'cat.name as category_name' ]) .from('users u') .innerJoin('posts p', 'u.id = p.user_id') .leftJoin('comments c', 'p.id = c.post_id') .leftJoin('categories cat', 'p.category_id = cat.id') .where('u.active = ?', [true]) .where('p.published = ?', [true]) .orderBy('p.created_at', 'DESC'); ``` -------------------------------- ### PGLite Schema Creation and Querying Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Demonstrates using PGLite with '@stackpress/inquire-pglite' for in-memory PostgreSQL-like database operations. It includes creating a 'users' table and executing SQL queries with date filtering and ordering. ```typescript import { PGlite } from '@electric-sql/pglite'; import connect from '@stackpress/inquire-pglite'; // Connection setup (in-memory) const db = new PGlite(); const engine = connect(db); // PGLite works like PostgreSQL await engine.create('users') .addField('id', { type: 'SERIAL', primaryKey: true }) .addField('name', { type: 'VARCHAR', length: 255 }) .addField('email', { type: 'VARCHAR', length: 255 }) .addField('created_at', { type: 'TIMESTAMP', default: 'NOW()' }); // All PostgreSQL features work const users = await engine.sql` SELECT * FROM users WHERE created_at > ${new Date('2024-01-01')} ORDER BY created_at DESC `; ``` -------------------------------- ### Create Product Schema with Inquire Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Defines a 'products' table schema using the Inquire library. It includes fields for product details, sets primary keys, and adds indexes for efficient querying. This is a foundational step for managing product data. ```typescript await engine.create('products') .addField('id', { type: 'INTEGER', autoIncrement: true }) .addField('name', { type: 'VARCHAR', length: 255 }) .addField('description', { type: 'TEXT' }) .addField('price', { type: 'DECIMAL', precision: 10, scale: 2 }) .addField('stock_quantity', { type: 'INTEGER', default: 0 }) .addField('active', { type: 'BOOLEAN', default: true }) .addField('created_at', { type: 'TIMESTAMP', default: 'CURRENT_TIMESTAMP' }) .addPrimaryKey('id') .addIndex('idx_active', ['active']) .addIndex('idx_price', ['price']); ``` -------------------------------- ### Subqueries with Inquire Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Demonstrates how to use subqueries within SQL statements, including using template strings for dynamic query construction and type safety. ```typescript // Using template strings for subqueries const usersWithPostCount = await engine.sql<{ id: number; name: string; post_count: number; }>` SELECT u.id, u.name, (SELECT COUNT(*) FROM posts p WHERE p.user_id = u.id) as post_count FROM users u WHERE u.active = ${true} ORDER BY post_count DESC `; ``` -------------------------------- ### Complex SELECT Query Example Source: https://github.com/stackpress/inquire/blob/main/docs/builders/Select.md Provides a comprehensive example of a complex SELECT query using the Inquire builder. This snippet showcases multiple joins, WHERE clauses, GROUP BY, HAVING, ORDER BY, and LIMIT clauses for advanced data retrieval. ```typescript type PostWithDetails = { id: number; title: string; excerpt: string; author_name: string; author_email: string; category_name: string; tag_count: number; comment_count: number; view_count: number; published_at: Date; is_featured: boolean; }; const featuredPosts: PostWithDetails[] = await engine.select([ 'p.id', 'p.title', 'p.excerpt', 'u.name as author_name', 'u.email as author_email', 'c.name as category_name', 'COUNT(DISTINCT pt.tag_id) as tag_count', 'COUNT(DISTINCT cm.id) as comment_count', 'p.views as view_count', 'p.published_at', 'p.featured as is_featured' ]) .from('posts p') .innerJoin('users u', 'p.user_id = u.id') .innerJoin('categories c', 'p.category_id = c.id') .leftJoin('post_tags pt', 'p.id = pt.post_id') .leftJoin('comments cm', 'p.id = cm.post_id AND cm.approved = ?', [true]) .where('p.published = ?', [true]) .where('p.published_at <= ?', [new Date()]) .where('u.active = ?', [true]) .where('(p.featured = ? OR p.views > ?)', [true, 1000]) .groupBy('p.id', 'u.name', 'u.email', 'c.name') .having('COUNT(DISTINCT pt.tag_id) > ?', [0]) .orderBy('p.featured', 'DESC') .orderBy('p.published_at', 'DESC') .orderBy('p.views', 'DESC') .limit(20); ``` -------------------------------- ### Delete Data with Inquire Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Demonstrates how to delete records from a table based on specific conditions or to delete all records. ```typescript // Delete specific record await engine.delete('users') .where('id = ?', [1]); // Delete with multiple conditions await engine.delete('posts') .where('published = ?', [false]) .where('created_at < ?', [new Date('2023-01-01')]); // Delete all records (use with caution) await engine.delete('temp_data'); ``` -------------------------------- ### Compare Schemas and Generate Migrations Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Shows how to define and compare database schemas to generate migration scripts. This involves creating representations of old and new table structures, including fields, types, constraints, and primary/unique keys, and then diffing them. ```typescript // Define old schema const oldSchema = engine.create('users') .addField('id', { type: 'INTEGER', autoIncrement: true }) .addField('name', { type: 'VARCHAR', length: 100 }) .addPrimaryKey('id'); // Define new schema const newSchema = engine.create('users') .addField('id', { type: 'INTEGER', autoIncrement: true }) .addField('name', { type: 'VARCHAR', length: 255 }) .addField('email', { type: 'VARCHAR', length: 255 }) .addField('created_at', { type: 'TIMESTAMP', default: 'CURRENT_TIMESTAMP' }) .addPrimaryKey('id') .addUniqueKey('unique_email', ['email']); // Generate migration const migration = engine.diff(oldSchema, newSchema); await migration; ``` -------------------------------- ### Execute PGLite Queries Source: https://github.com/stackpress/inquire/blob/main/docs/Connections.md Provides an example of executing a query against a PGLite database. The query is typed to return an array of 'User' objects. ```typescript const users = await connection.query({ query: 'SELECT * FROM users WHERE age > $1', values: [18] }); // Returns User[] from the rows property ``` -------------------------------- ### MySQL Schema Creation and Insertion Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Demonstrates how to connect to a MySQL database using 'mysql2/promise' and '@stackpress/inquire-mysql2'. It shows creating a 'users' table with various field types, primary keys, and engine/charset options, followed by inserting data and accessing the last inserted ID. ```typescript import mysql from 'mysql2/promise'; import connect from '@stackpress/inquire-mysql2'; // Connection setup const connection = await mysql.createConnection({ host: 'localhost', user: 'root', password: 'password', database: 'myapp' }); const engine = connect(connection); // MySQL-specific features await engine.create('users') .addField('id', { type: 'INT', autoIncrement: true, unsigned: true }) .addField('name', { type: 'VARCHAR', length: 255, charset: 'utf8mb4' }) .addField('created_at', { type: 'TIMESTAMP', default: 'CURRENT_TIMESTAMP' }) .addPrimaryKey('id') .engine('InnoDB') .charset('utf8mb4'); // Using last insert ID await engine.insert('users').values({ name: 'John' }); console.log('Last inserted ID:', engine.connection.lastId); ``` -------------------------------- ### PostgreSQL Window Functions Source: https://github.com/stackpress/inquire/blob/main/docs/dialects/README.md Provides an example of using window functions in PostgreSQL to assign a rank based on salary. ```typescript // Window functions await engine.sql` SELECT name, salary, ROW_NUMBER() OVER (ORDER BY salary DESC) as rank FROM employees `; ``` -------------------------------- ### SQLite Schema Creation and Data Handling Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Shows how to connect to an SQLite database using 'better-sqlite3' and '@stackpress/inquire-sqlite3'. It details creating a 'users' table, handling JSON as TEXT, inserting data with boolean represented as integers, and retrieving the last inserted row ID. ```typescript import Database from 'better-sqlite3'; import connect from '@stackpress/inquire-sqlite3'; // Connection setup const db = new Database('myapp.db'); const engine = connect(db); // SQLite-specific features await engine.create('users') .addField('id', { type: 'INTEGER', primaryKey: true, autoIncrement: true }) .addField('name', { type: 'TEXT' }) .addField('data', { type: 'TEXT' }) // JSON as TEXT .addField('created_at', { type: 'DATETIME', default: 'CURRENT_TIMESTAMP' }); // SQLite doesn't support boolean, so use INTEGER await engine.insert('users') .values({ name: 'Bob', active: 1, // boolean as integer data: JSON.stringify({ role: 'user' }) }); // Using last insert row ID await engine.insert('users').values({ name: 'Carol' }); console.log('Last inserted row ID:', engine.connection.lastId); ``` -------------------------------- ### Search Products with Filters using Inquire Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Implements a function to search for products based on provided filters. It allows searching by name, filtering by minimum and maximum price, and checking stock availability. The function returns active products, ordered by name. ```typescript const searchProducts = async (filters: { search?: string; minPrice?: number; maxPrice?: number; inStock?: boolean; }) => { let query = engine.select('*').from('products').where('active = ?', [true]); if (filters.search) { query = query.where('name LIKE ?', [`%${filters.search}%`]); } if (filters.minPrice !== undefined) { query = query.where('price >= ?', [filters.minPrice]); } if (filters.maxPrice !== undefined) { query = query.where('price <= ?', [filters.maxPrice]); } if (filters.inStock) { query = query.where('stock_quantity > ?', [0]); } return await query.orderBy('name', 'ASC'); }; // Usage const results = await searchProducts({ search: 'laptop', minPrice: 500, maxPrice: 2000, inStock: true }); ``` -------------------------------- ### Full-Text Search (FTS5) Setup in SQLite Source: https://github.com/stackpress/inquire/blob/main/docs/dialects/SQLite.md Demonstrates creating a virtual FTS5 table for full-text search capabilities and populating it from an existing 'posts' table. ```sql CREATE VIRTUAL TABLE posts_fts USING fts5(title, content, content='posts', content_rowid='id') ``` ```sql INSERT INTO posts_fts(rowid, title, content) SELECT id, title, content FROM posts ``` -------------------------------- ### Manage Tables: Drop, Rename, Truncate Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Demonstrates common table management operations: dropping a table, renaming a table, and truncating a table (emptying all its rows). It also shows how to perform a truncate with cascade option, typically used in PostgreSQL. ```typescript // Drop table await engine.drop('old_table'); // Rename table await engine.rename('old_name', 'new_name'); // Truncate table await engine.truncate('temp_data'); // Truncate with cascade (PostgreSQL) await engine.truncate('parent_table', true); ``` -------------------------------- ### Fluent Query Building Example Source: https://github.com/stackpress/inquire/blob/main/docs/builders/README.md Demonstrates the fluent, chainable API for constructing a SQL SELECT query. It shows how to specify columns, table, filtering, ordering, and limiting results. ```typescript import { engine } from '@stackpress/inquire'; // Example: Fluent query building const users = await engine.select(['id', 'name', 'email']) .from('users') .where('active = ?', [true]) .orderBy('created_at', 'DESC') .limit(10); ``` -------------------------------- ### PostgreSQL Window Functions with ROW_NUMBER Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Demonstrates how to use the ROW_NUMBER() window function in PostgreSQL to rank posts by creation date for each user. This is useful for tasks like finding the latest post per user. ```typescript const rankedPosts = await engine.sql<{ id: number; title: string; user_id: number; rank: number; }>` SELECT id, title, user_id, ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) as rank FROM posts WHERE published = ${true} `; ``` -------------------------------- ### Managing Database Transactions Source: https://github.com/stackpress/inquire/blob/main/docs/Engine.md Provides an example of executing multiple database queries within a transaction using Stackpress Inquire. It shows how to perform inserts and ensures atomicity for related operations. ```typescript const result = await engine.transaction(async (trx) => { // Insert user const userResult = await trx.insert('users') .values({ name: 'Alice', email: 'alice@example.com' }); // Insert related data await trx.insert('profiles') .values({ user_id: userResult.insertId, bio: 'Hello world' }); return { success: true, userId: userResult.insertId }; }); ``` -------------------------------- ### Execute BetterSqlite3 Queries Source: https://github.com/stackpress/inquire/blob/main/docs/Connections.md Provides an example of executing a query against a SQLite database using BetterSqlite3. The results are typed to return an array of 'User' objects, and the last inserted ID is tracked. ```typescript const users = await connection.query({ query: 'SELECT * FROM users WHERE age > ?', values: [18] }); // Returns User[] with last inserted row ID tracked ``` -------------------------------- ### TypeScript: Update with Multiple Joins Source: https://github.com/stackpress/inquire/blob/main/docs/builders/Update.md Applies a discount to order items for 'vip' customers' 'electronics' products. This example demonstrates performing updates involving multiple joined tables. ```typescript // Update with multiple joins await engine.update('order_items oi') .innerJoin('orders o', 'oi.order_id = o.id') .innerJoin('products p', 'oi.product_id = p.id') .set({ 'oi.discount_applied': true }) .where('o.customer_type = ?', ['vip']) .where('p.category = ?', ['electronics']); ``` -------------------------------- ### Handle Inquire Database Exceptions Source: https://github.com/stackpress/inquire/blob/main/docs/Connections.md Shows how to handle database-related errors using the `InquireException`. The example demonstrates a `try...catch` block that specifically catches `InquireException` instances, allowing for targeted error logging and management. ```typescript import { InquireException } from '@stackpress/inquire'; try { await connection.query({ query: 'INVALID SQL', values: [] }); } catch (error) { if (error instanceof InquireException) { console.log('Database error:', error.message); } } ``` -------------------------------- ### Recursive Common Table Expression (CTE) in SQLite Source: https://github.com/stackpress/inquire/blob/main/docs/dialects/SQLite.md Provides an example of a recursive CTE in SQLite to generate a category tree structure, starting from parentless categories and traversing down. ```sql WITH RECURSIVE category_tree(id, name, parent_id, level) AS ( SELECT id, name, parent_id, 0 FROM categories WHERE parent_id IS NULL UNION ALL SELECT c.id, c.name, c.parent_id, ct.level + 1 FROM categories c JOIN category_tree ct ON c.parent_id = ct.id ) SELECT * FROM category_tree ORDER BY level, name ``` -------------------------------- ### Transaction Error Handling and Rollback Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Demonstrates how to handle errors within a database transaction. If an error occurs during any of the operations inside the `transaction` callback, the entire transaction is automatically rolled back, ensuring data consistency. The `catch` block logs the error message. ```typescript try { const result = await engine.transaction(async (trx) => { await trx.insert('users') .values({ name: 'Bob', email: 'existing@example.com' }); // This might fail await trx.insert('posts') .values({ user_id: 999, title: 'Test' }); // This might also fail return 'success'; }); } catch (error) { console.log('Transaction failed and was rolled back:', error.message); } ``` -------------------------------- ### Stackpress Inquire: Alter Table - Initial Example Source: https://github.com/stackpress/inquire/blob/main/docs/builders/Alter.md Demonstrates the initial setup of an Alter builder to modify the 'users' table by adding a 'phone' field, changing the 'email' field, and adding an index on 'phone'. ```typescript const alter = engine.alter('users') .addField('phone', { type: 'VARCHAR', length: 20 }) .changeField('email', { type: 'VARCHAR', length: 320 }) .addIndex('idx_phone', ['phone']); await alter; ``` -------------------------------- ### Transaction Management Source: https://github.com/stackpress/inquire/blob/main/README.md Illustrates how to perform multiple database operations atomically using Inquire's transaction functionality. This example shows inserting data into 'users' and 'posts' tables within a single transaction. ```typescript const result = await engine.transaction(async (trx) => { await trx.insert('users').values({ name: 'Alice' }); await trx.insert('posts').values({ title: 'Hello World', user_id: 1 }); return 'success'; }); ``` -------------------------------- ### Error Handling with InquireException Source: https://github.com/stackpress/inquire/blob/main/docs/builders/Insert.md Demonstrates how to handle errors during insert operations using the `InquireException`. The example shows a try-catch block to capture exceptions, log general error messages, and specifically identify issues like duplicate entries or constraint violations. ```typescript import { InquireException } from '@stackpress/inquire'; try { await engine.insert('users') .values({ name: 'John', email: 'invalid-email' // Might violate constraints }); } catch (error) { if (error instanceof InquireException) { console.log('Insert error:', error.message); // Handle specific error types if (error.message.includes('duplicate')) { console.log('Duplicate entry detected'); } else if (error.message.includes('constraint')) { console.log('Constraint violation'); } } } ``` -------------------------------- ### PostgreSQL Schema Creation and Querying Source: https://github.com/stackpress/inquire/blob/main/docs/Examples.md Illustrates connecting to a PostgreSQL database using 'pg' and '@stackpress/inquire-pg'. It covers creating a 'users' table with SERIAL, JSONB types, and default timestamps, inserting data with a RETURNING clause, and executing SQL queries with JSON data extraction. ```typescript import { Pool } from 'pg'; import connect from '@stackpress/inquire-pg'; // Connection setup const pool = new Pool({ user: 'postgres', host: 'localhost', database: 'myapp', password: 'password', port: 5432, }); const connection = await pool.connect(); const engine = connect(connection); // PostgreSQL-specific features await engine.create('users') .addField('id', { type: 'SERIAL', primaryKey: true }) .addField('name', { type: 'VARCHAR', length: 255 }) .addField('data', { type: 'JSONB' }) .addField('created_at', { type: 'TIMESTAMP', default: 'NOW()' }); // Using RETURNING clause const newUsers = await engine.insert('users') .values({ name: 'Alice', data: { role: 'admin' } }) .returning('*'); // PostgreSQL arrays and JSON const usersWithJsonData = await engine.sql<{ id: number; name: string; roles: string[]; }>` SELECT id, name, data->>'roles' as roles FROM users WHERE data ? ${'role'} `; ``` -------------------------------- ### Comprehensive Table Alteration Example Source: https://github.com/stackpress/inquire/blob/main/docs/builders/Alter.md A detailed example of performing multiple schema modifications on a 'blog_posts' table, including adding various fields, modifying existing ones, adding indexes, unique constraints, and foreign keys. ```typescript await engine.alter('blog_posts') // Add new fields .addField('excerpt', { type: 'TEXT', nullable: true }) .addField('featured_image', { type: 'VARCHAR', length: 500, nullable: true }) .addField('meta_title', { type: 'VARCHAR', length: 60, nullable: true }) .addField('meta_description', { type: 'VARCHAR', length: 160, nullable: true }) .addField('reading_time', { type: 'INTEGER', unsigned: true, nullable: true }) .addField('featured', { type: 'BOOLEAN', default: false }) // Modify existing fields .changeField('title', { type: 'VARCHAR', length: 300, nullable: false }) .changeField('content', { type: 'LONGTEXT', nullable: false }) // Add indexes for performance .addIndex('idx_featured', ['featured']) .addIndex('idx_reading_time', ['reading_time']) .addIndex('idx_meta_title', ['meta_title']) // Add unique constraint .addUniqueKey('unique_meta_title', ['meta_title']) // Add foreign key for featured image .addField('featured_image_id', { type: 'INTEGER', unsigned: true, nullable: true }) .addForeignKey('fk_featured_image', { local: ['featured_image_id'], foreign: { table: 'media', columns: ['id'] }, onUpdate: 'CASCADE', onDelete: 'SET NULL' }) .addIndex('idx_featured_image', ['featured_image_id']); ``` -------------------------------- ### MySQL JSON Operations Source: https://github.com/stackpress/inquire/blob/main/docs/dialects/README.md Provides an example of performing JSON operations in MySQL using JSON_EXTRACT and JSON_CONTAINS. ```typescript // JSON operations await engine.sql` SELECT JSON_EXTRACT(data, '$.name') as name FROM users WHERE JSON_CONTAINS(data, ${'{"active": true}'}) `; ``` -------------------------------- ### MySQL Multi-Table Operations Source: https://github.com/stackpress/inquire/blob/main/docs/dialects/README.md Shows an example of deleting data from multiple tables in MySQL using a LEFT JOIN. ```typescript // Multi-table operations await engine.sql` DELETE u, p FROM users u LEFT JOIN posts p ON u.id = p.user_id WHERE u.active = ${[false]} `; ``` -------------------------------- ### Connect to PostgreSQL with Inquire Source: https://github.com/stackpress/inquire/blob/main/packages/inquire/README.md Shows how to connect to PostgreSQL using either a `pg` Pool or Client and then map the connection to the Inquire engine. ```typescript import { Client, Pool } from 'pg'; import connect from '@stackpress/inquire-pg'; // Using a Pool const pool = new Pool({ database: 'inquire', user: 'postgres' }); const connection = await pool.connect(); // Or using a Client const client = new Client({ database: 'inquire', user: 'postgres' }); await client.connect(); // Map the resource to the Inquire engine const engine = connect(connection); // or connect(client) ``` -------------------------------- ### Connect to MySQL using Mysql2Connection Source: https://github.com/stackpress/inquire/blob/main/docs/Connections.md Demonstrates how to establish a connection to a MySQL database using the `Mysql2Connection` class from the `@stackpress/inquire-mysql2` package. It shows the necessary imports and the process of creating a database resource and then an Inquire engine. ```typescript import mysql from 'mysql2/promise'; import connect from '@stackpress/inquire-mysql2'; const resource = await mysql.createConnection({ host: 'localhost', user: 'root', database: 'inquire', }); const engine = connect(resource); ``` -------------------------------- ### Connect to MySQL with Inquire Source: https://github.com/stackpress/inquire/blob/main/packages/inquire/README.md Demonstrates how to establish a MySQL connection using `mysql2/promise` and integrate it with the Inquire engine. ```typescript import mysql from 'mysql2/promise'; import connect from '@stackpress/inquire-mysql2'; // Create the raw database connection const resource = await mysql.createConnection({ host: 'localhost', user: 'root', database: 'inquire', }); // Map the resource to the Inquire engine const engine = connect(resource); ``` -------------------------------- ### Window Functions: Running Totals Source: https://github.com/stackpress/inquire/blob/main/docs/builders/Select.md Example of calculating running totals using the `SUM() OVER()` window function, ordered by a specific column. ```typescript const runningTotals = await engine.select([ 'id', 'amount', 'created_at', 'SUM(amount) OVER (ORDER BY created_at) as running_total' ]) .from('orders') .orderBy('created_at'); ``` -------------------------------- ### Connect to PostgreSQL with Inquire Source: https://github.com/stackpress/inquire/blob/main/README.md Shows how to connect to PostgreSQL using either a `pg` Pool or Client and then map the connection to the Inquire engine. ```typescript import { Client, Pool } from 'pg'; import connect from '@stackpress/inquire-pg'; // Using a Pool const pool = new Pool({ database: 'inquire', user: 'postgres' }); const connection = await pool.connect(); // Or using a Client const client = new Client({ database: 'inquire', user: 'postgres' }); await client.connect(); // Map the resource to the Inquire engine const engine = connect(connection); // or connect(client) ``` -------------------------------- ### Remove Indexes Source: https://github.com/stackpress/inquire/blob/main/docs/builders/Alter.md Provides an example of removing existing indexes from a database table. This is useful for optimizing schema by removing unused or redundant indexes. ```typescript await engine.alter('posts') .removeIndex('old_index') .removeIndex('unused_index') .removeIndex('deprecated_idx'); ``` -------------------------------- ### Conditional Updates Source: https://github.com/stackpress/inquire/blob/main/docs/builders/Update.md Provides examples of performing conditional updates based on current record values or using CASE statements for complex logic. ```typescript // Update based on current values await engine.update('users') .set({ status: 'inactive', deactivated_at: new Date() }) .where('last_login < ?', [new Date(Date.now() - 90 * 24 * 60 * 60 * 1000)]) .where('status = ?', ['active']); ``` ```typescript // Update with CASE statements await engine.update('products') .set({ status: `CASE WHEN stock_quantity = 0 THEN 'out_of_stock' WHEN stock_quantity < 10 THEN 'low_stock' ELSE 'in_stock' END`, updated_at: new Date() }) .where('category = ?', ['electronics']); ``` -------------------------------- ### Connect to MySQL with Inquire Source: https://github.com/stackpress/inquire/blob/main/README.md Demonstrates how to establish a MySQL connection using `mysql2/promise` and integrate it with the Inquire engine. ```typescript import mysql from 'mysql2/promise'; import connect from '@stackpress/inquire-mysql2'; // Create the raw database connection const resource = await mysql.createConnection({ host: 'localhost', user: 'root', database: 'inquire', }); // Map the resource to the Inquire engine const engine = connect(resource); ``` -------------------------------- ### SQLite Indexing Strategy Source: https://github.com/stackpress/inquire/blob/main/docs/dialects/SQLite.md Provides examples of creating various types of indexes in SQLite to optimize query performance, including single-column, composite, and partial indexes. ```typescript await engine.sql`CREATE INDEX idx_users_email ON users(email)`; ``` ```typescript await engine.sql`CREATE INDEX idx_posts_user_id ON posts(user_id)`; ``` ```typescript await engine.sql`CREATE INDEX idx_posts_created_at ON posts(created_at)`; ``` ```typescript await engine.sql`CREATE INDEX idx_posts_status_date ON posts(status, created_at)`; ``` ```typescript await engine.sql`CREATE INDEX idx_active_users ON users(email) WHERE active = 1`; ``` -------------------------------- ### SQLite Auto-Increment Support Source: https://github.com/stackpress/inquire/blob/main/docs/dialects/SQLite.md Demonstrates the support for AUTOINCREMENT in the SQLite dialect for primary key fields. Examples show how to define auto-incrementing integer primary keys. ```typescript engine.create('users') .field('id', { type: 'int', autoIncrement: true }) // INTEGER PRIMARY KEY AUTOINCREMENT .primary('id'); // Or inline primary key engine.create('posts') .field('id', { type: 'int', autoIncrement: true }) // Automatically becomes PRIMARY KEY .field('title', { type: 'varchar', length: 255 }); ``` -------------------------------- ### Connect to PostgreSQL using PGConnection Source: https://github.com/stackpress/inquire/blob/main/docs/Connections.md Demonstrates how to establish a connection to a PostgreSQL database using the `PGConnection` class from the `@stackpress/inquire-pg` package. It includes setting up the `pg` client and creating an Inquire engine. ```typescript import { Client } from 'pg'; import connect from '@stackpress/inquire-pg'; const client = new Client({ database: 'inquire', user: 'postgres' }); await client.connect(); const engine = connect(client); ``` -------------------------------- ### Getting Query Information Source: https://github.com/stackpress/inquire/blob/main/docs/builders/Select.md Shows how to inspect the generated SQL query string and parameter values before executing the query using the `.query()` method. ```typescript const selectBuilder = engine.select(['id', 'name']) .from('users') .where('active = ?', [true]) .orderBy('name', 'ASC') .limit(10); const { query, values } = selectBuilder.query(); console.log('SQL:', query); console.log('Values:', values); // Then execute const results = await selectBuilder; ```