Advanced Queries — ODAC.JS Docs
Docs / ODAC.JS / Backend / Database / Advanced Queries

Advanced Queries

For complex applications, ODAC provides advanced query capabilities like nested constraints, joins, transactions, and raw SQL execution.

Nested Where Clauses

To create complex AND / OR logic (like parenthesis in SQL), use a callback function with .where() or .andWhere().

Example:
SELECT * FROM users WHERE status = 'active' AND (role = 'admin' OR role = 'editor')

ODAC Code:

await Odac.DB.users
  .where('status', 'active')
  .andWhere(builder => {
    builder.where('role', 'admin').orWhere('role', 'editor');
  })
  .select();

Joins

You can join multiple tables using .join(), .leftJoin(), etc.

const posts = await Odac.DB.posts
  .join('users', 'posts.user_id', '=', 'users.id')
  .select('posts.title', 'users.name as author');

Transactions

Transactions allow you to ensure multiple database operations succeed or fail together.

await Odac.DB.transaction(async (trx) => {
  
  const [userId] = await trx('users').insert({ name: 'Alice' });
  
  await trx('accounts').insert({ user_id: userId, balance: 100 });

  // If anything throws an error here, both inserts are rolled back.
});

Note: Use Odac.DB.connectionName.transaction(...) for non-default connections.


Raw Queries & Values

Raw SQL Execution

If you need to execute a completely raw SQL query:

const result = await Odac.DB.run('SELECT email FROM users WHERE id = ?', [1]);

Raw Values in Updates

Sometimes you need to call SQL functions (like NOW() or COUNT()) inside an update or insert.

await Odac.DB.users.where('id', 1).update({
  updated_at: Odac.DB.raw('NOW()'),
  visits: Odac.DB.raw('visits + 1')
});

Safe Table Access

If your table name conflicts with a reserved ODAC method (e.g., transaction, schema, run), use the .table() method to access it safely.

// Access a table named 'transaction'
const logs = await Odac.DB.table('transaction').select();