Expand description
Bindings for emulating a MySQL/MariaDB server.
When developing new databases or caching layers, it can be immensely useful to test your system using existing applications. However, this often requires significant work modifying applications to use your database over the existing ones. This crate solves that problem by acting as a MySQL server, and delegating operations such as querying and query execution to user-defined logic.
To start, implement MysqlShim
for your backend, and create a MysqlIntermediary
over an
instance of your backend and a connection stream. The appropriate methods will be called on
your backend whenever a client issues a QUERY
, PREPARE
, or EXECUTE
command, and you will
have a chance to respond appropriately. For example, to write a shim that always responds to
all commands with a “no results” reply:
extern crate mysql;
use msql_srv::*;
use mysql::prelude::*;
use mysql::Opts;
struct Backend;
impl<W: io::Read + io::Write> MysqlShim<W> for Backend {
type Error = io::Error;
fn on_prepare(&mut self, _: &str, info: StatementMetaWriter<W>) -> io::Result<()> {
info.reply(42, &[], &[])
}
fn on_execute(
&mut self,
_: u32,
_: ParamParser,
results: QueryResultWriter<W>,
) -> io::Result<()> {
results.completed(0, 0)
}
fn on_close(&mut self, _: u32) {}
fn on_init(&mut self, _: &str, writer: InitWriter<W>) -> io::Result<()> { Ok(()) }
fn on_query(&mut self, _: &str, results: QueryResultWriter<W>) -> io::Result<()> {
let cols = [
Column {
table: "foo".to_string(),
column: "a".to_string(),
coltype: ColumnType::MYSQL_TYPE_LONGLONG,
colflags: ColumnFlags::empty(),
},
Column {
table: "foo".to_string(),
column: "b".to_string(),
coltype: ColumnType::MYSQL_TYPE_STRING,
colflags: ColumnFlags::empty(),
},
];
let mut rw = results.start(&cols)?;
rw.write_col(42)?;
rw.write_col("b's value")?;
rw.finish()
}
}
fn main() {
let listener = net::TcpListener::bind("127.0.0.1:0").unwrap();
let port = listener.local_addr().unwrap().port();
let jh = thread::spawn(move || {
if let Ok((s, _)) = listener.accept() {
MysqlIntermediary::run_on_tcp(Backend, s).unwrap();
}
});
let mut db = mysql::Conn::new(Opts::from_url(&format!("mysql://127.0.0.1:{}", port)).unwrap()).unwrap();
assert_eq!(db.ping(), true);
assert_eq!(db.query_iter("SELECT a, b FROM foo").unwrap().count(), 1);
drop(db);
jh.join().unwrap();
}
Structs§
- Authentication
Context - Information about an authenticated user
- Column
- Meta-information abot a single column, used either to describe a prepared statement parameter or an output column.
- Column
Flags - MySql column flags
- Init
Writer - Convenience type for responding to a client
USE <db>
command. - Mysql
Intermediary - A server that speaks the MySQL/MariaDB protocol, and can delegate client commands to a backend
that implements
MysqlShim
. - Param
Parser - A
ParamParser
decodes query parameters included in a client’sEXECUTE
command given type information for the expected parameters. - Param
Value - A single parameter value provided by a client when issuing an
EXECUTE
command. - Params
- An iterator over parameters provided by a client in an
EXECUTE
command. - Query
Result Writer - Convenience type for providing query results to clients.
- RowWriter
- Convenience type for sending rows of a resultset to a client.
- Statement
Meta Writer - Convenience type for responding to a client
PREPARE
command. - Status
Flags - MySql server status flags
- Value
- MySQL value as provided when executing prepared statements.
Enums§
- Column
Type - Type of MySql column field
- Error
Kind - MySQL error type
- Value
Inner - A representation of a concrete, typed MySQL value.
Traits§
- Mysql
Shim - Implementors of this trait can be used to drive a MySQL-compatible database backend.
- ToMysql
Value - Implementors of this trait can be sent as a single resultset value to a MySQL/MariaDB client.