AI Core

ai-mysql for developers

The oxmysql exports ai-mysql answers, what each one returns, the promise forms, the MySQL.lua wrapper and the error events.

Writing an ai-* style resource in TypeScript? Do not use ai-mysql. Use AI Core's database package @aicore-fivem/mysql in your own resource (no export hop per query, typed tables). See Database. ai-mysql is for Lua and JavaScript scripts written for oxmysql.

ai-mysql answers oxmysql's API exactly (signatures, callback rules, result shapes), so oxmysql's own documentation applies. This page lists what it answers and the details that matter.

Using it from Lua

Load oxmysql's wrapper; the path resolves to ai-mysql:

fxmanifest.lua
server_script '@oxmysql/lib/MySQL.lua'
server.lua
-- Waits for the result: call inside a thread or an event handler.
local row = MySQL.single.await('SELECT money FROM my_accounts WHERE owner = ?', { identifier })

-- Callback form: does not wait.
MySQL.update('UPDATE my_accounts SET money = money - ? WHERE owner = ? AND money >= ?', { 100, identifier, 100 }, function(affected)
    if affected == 1 then print('paid') end
end)

Exports

Every export is server side and answers under exports['ai-mysql'] and exports.oxmysql. Each one takes (query, params?, callback?):

  • query: the SQL text, with ? placeholders or named @name / :name placeholders.
  • params: an array for ?, an object for named placeholders. May be left out; the callback can then be the second argument.
  • callback: called with the result. Without it the call still runs.

Each export also has a promise form <name>_async and <name>Sync (query_async(query, params) returns a Promise that rejects on an error).

ExportAnswersUse it for
querythe rows (array of objects) for a SELECT, or the result header for other statementsanything; execute and fetch are old aliases
singlethe first row, or nullone row by key
scalarthe first column of the first row, or nulla count, one value
insertthe new row's id (insertId), or nullINSERT
updatethe number of affected rows, or nullUPDATE, DELETE
prepareprepared statement (binary protocol); INSERT answers the id, UPDATE / DELETE the affected rows, SELECT the first row (or its only value). Several value lists run it once each.the same query many times
rawExecuteprepared statement with the full, unshaped resultswhen you need the raw result
transactiontrue when committed, false after a rollback (always through the callback)several statements that must all succeed
startTransactiona Promise of true when committed, false after a rollbacka transaction with logic between queries
storehands the query text back to the callbackold code that stored queries
isReadyboolean: the pool is openchecks at start
awaitConnectiona Promise of true once connectedwaiting at start

transaction

Runs several statements on one connection; all of them succeed or none.

Side: Server · Waits: no (answers through the callback; transaction_async returns a Promise)

Signature
transaction(queries: Array<string | [string, unknown[] | object] | { query: string; values?: unknown[] | object; parameters?: unknown[] | object }>, params?: unknown[] | object, cb?: (committed: boolean) => void): void
Lua
local ok = MySQL.transaction.await({
    { query = 'UPDATE my_accounts SET money = money - ? WHERE owner = ?', values = { 100, from } },
    { query = 'UPDATE my_accounts SET money = money + ? WHERE owner = ?', values = { 100, to } },
})

Parameters

Prop

Type

Returns

Nothing directly; the callback gets true or false. A rollback prints the error in the console and fires oxmysql:transaction-error.

startTransaction

Opens a transaction and gives your function a query helper bound to it. Return false from your function to roll back. It times out after 30 seconds.

Side: Server · Waits: yes (Promise)

Signature
startTransaction(work: (query: (sql: string, params?: unknown[] | object) => Promise<unknown>) => Promise<boolean | void>): Promise<boolean>

Returns

Promise<boolean>: true when committed. false when your function returned false, threw, or the 30 seconds ran out.

Example

// A plain JavaScript or TypeScript resource without @aicore-fivem/mysql.
const db = exports.oxmysql;

async function pay(from: string, to: string, amount: number): Promise<boolean> {
  return db.startTransaction(async (query: (sql: string, params?: unknown[]) => Promise<any>) => {
    const res = await query("UPDATE my_accounts SET money = money - ? WHERE owner = ? AND money >= ?", [amount, from, amount]);
    if (res.affectedRows !== 1) return false; // not enough money: roll back
    await query("UPDATE my_accounts SET money = money + ? WHERE owner = ?", [amount, to]);
  });
}

Old export names

Old resourceNamesSame as
ghmattimysqlexecute, scalar, transaction, store (and executeSync, scalarSync, ...)query, scalar, transaction, store
mysql-asyncmysql_execute, mysql_insert, mysql_fetch_all, mysql_fetch_scalar, mysql_transaction, mysql_storeupdate, insert, query, scalar, transaction, store

Callback and error rules

These follow oxmysql:

  • Success: the callback gets the result.
  • Failure with a promise form (or .await in Lua): the promise rejects with the error text.
  • Failure with a plain callback: the error is printed in the console and the callback is not called.

Events

oxmysql:error

Side: Server (local) · fires when a query fails.

Prop

Type

oxmysql:transaction-error

Side: Server (local) · fires when a transaction rolls back. Payload { message: string, resource: string }.

on("oxmysql:error", (e: { query?: string; message: string; resource: string }) => {
  console.log(`[db] ${e.resource}: ${e.message} (${e.query ?? "?"})`);
});

Always pass values as parameters, never by joining them into the SQL text. A value from a player put straight into SQL lets them run their own queries.

On this page