mysql_samp¶
MySQL plugin for SA-MP and Open Multiplayer, written entirely in Rust. Non-blocking queries with FIFO ordering, a result cache, an ORM, zero external runtime dependencies.
Not affiliated
This is an independent, community-maintained project. It is not affiliated with, endorsed by, sponsored by, or otherwise connected to SA-MP, the open.mp (Open Multiplayer) project, or the MySQL plugin by BlueG / maddinat0r that this one is compared against. It has no relationship with any of them. "SA-MP", "open.mp" and "MySQL" belong to their respective owners and are referenced here solely to describe what this plugin is compatible with.
The same .so / .dll runs on SA-MP and on Open Multiplayer — natively as a component (recommended) or via legacy mode. See Installation for both registration paths.
Where to start¶
| Goal | Path |
|---|---|
| First time here | Installation → Connection → Queries |
| Coming from MySQL R41-4 | Migration guide → Migration changes → Migration examples |
| Quick lookup | API reference |
| Performance numbers | Benchmark |
Minimal example¶
Connect, fire a threaded query, read the result inside the callback:
#include <a_samp>
#include <mysql_samp>
new g_mysql;
public OnGameModeInit()
{
g_mysql = mysql_connect("127.0.0.1", "root", "password", "samp_db");
if (mysql_errno() != MYSQL_OK)
{
printf("[MySQL] connect failed: errno=%d", mysql_errno());
return 1;
}
// Non-blocking, FIFO-ordered query. Callback receives playerid via "d" format.
mysql_query(g_mysql, "SELECT id, name FROM players LIMIT 5", "OnPlayersLoaded", "d", 0);
return 1;
}
forward OnPlayersLoaded(playerid);
public OnPlayersLoaded(playerid)
{
new rows = cache_get_row_count();
for (new i = 0; i < rows; i++)
{
new id = cache_get_value_name_int(i, "id");
new name[MAX_PLAYER_NAME];
cache_get_value_name(i, "name", name);
printf("Player #%d: %s", id, name);
}
}
public OnGameModeExit()
{
mysql_close(g_mysql);
return 1;
}
Topics¶
| Topic | Contents |
|---|---|
| Installation | Download, register on SA-MP and Open Multiplayer, log files |
| Connection | mysql_connect, mysql_connect_file, mysql_close, mysql_status, charset, pool size |
| Options | All MYSQL_OPT_* values, defaults, TLS and mutual TLS |
| Queries | mysql_query, mysql_pquery, mysql_format, mysql_escape_string, mysql_stmt_*, mysql_transaction_* |
| Cache | cache_* natives, active stack, persistent caches, multiple result sets |
| ORM | Bind Pawn variables to columns, CRUD without writing SQL |
| Errors | mysql_errno, mysql_error, OnQueryError, MySQL error codes |
| Security | Prepared statements vs escaping, password storage, TLS, resource limits |
| API reference | One-line table of every native and forward (75 total) |
Plugin facts¶
- rust-samp: built on top of rust-samp v3.4.0.
- MySQL crate:
mysql28.0 withdefault-rust+rustls-tls-ring. The MySQL protocol itself is pure Rust; the TLS backend (ring) carries a C/assembly crypto core that is compiled into the binary, so the shipped artifact still needs nolibmysqlclientand no system OpenSSL. - TLS: rustls is compiled into the binary (
rustls-tls-ring);MYSQL_OPT_SSLenables TLS,MYSQL_OPT_SSL_CAsets the root certificate, andMYSQL_OPT_SSL_CERT/_KEYdo mutual TLS. WithoutMYSQL_OPT_SSL_CAonly the bundled webpki roots are trusted — not the OS trust store — so a self-signed or internal-CA server needs it. See Options. - Injection safety: prefer prepared statements (
mysql_stmt_*) overmysql_formatfor player input — values are bound server-side and never enter the SQL text. - Password hashing:
mysql_hash_password/mysql_verify_passwordrun Argon2id on a worker thread. - Tick dispatch: the unified
on_tickfrom rust-samp v3 fires on both SA-MP (viaProcessTick) and Open Multiplayer native mode (viaITimersComponent). No Pawn timer is required. - Server compatibility: MySQL 5.7, 8.x and 9.x, plus MariaDB. The driver implements
caching_sha2_password(the default since MySQL 8.0.4, and the only option since 9.0 removedmysql_native_password), including the RSA public-key exchange used for first authentication over a plaintext connection. - Threading: each
mysql_queryspawns a worker thread that pulls a connection from amysql::Pool; results travel back over anmpscchannel and are dispatched on the next tick.