Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions src/sql/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -183,8 +183,6 @@ pub mod postgres {
pub mod copy_out_response;
#[path = "DataRow.rs"]
pub mod data_row;
#[path = "DecoderWrap.rs"]
pub mod decoder_wrap;
#[path = "Describe.rs"]
pub mod describe;
#[path = "ErrorResponse.rs"]
Expand Down Expand Up @@ -225,14 +223,10 @@ pub mod postgres {
pub mod stack_reader;
#[path = "StartupMessage.rs"]
pub mod startup_message;
#[path = "WriteWrap.rs"]
pub mod write_wrap;

// ── flat re-exports for `bun_sql_jsc` (Decode/Write trait surface) ──
pub use decoder_wrap::DecoderWrap;
pub use new_reader::{NewReader, NewReaderWrap, ProtocolInt, ReaderContext};
pub use new_writer::{LengthWriter, NewWriter, WriterContext, new_writer};
pub use write_wrap::WriteWrap;
}

pub use any_postgres_error::{AnyPostgresError, PostgresErrorOptions};
Expand Down
346 changes: 74 additions & 272 deletions src/sql/mysql/Capabilities.rs
Original file line number Diff line number Diff line change
@@ -1,84 +1,86 @@
// MySQL capability flags
//
// Modeled as a plain struct of `bool` fields (NOT a `packed struct(u32)`-style
// bitfield), with explicit bit-value constants and
// hand-unrolled field loops for `to_int`/`from_int`/`Display`. Field names stay
// SCREAMING_SNAKE_CASE because `Display` emits them verbatim.
// (non_snake_case / non_upper_case_globals allowed at crate root.)
// bitfield). Field names stay SCREAMING_SNAKE_CASE because `Display` emits them
// verbatim. (non_snake_case / non_upper_case_globals allowed at crate root.)

use core::fmt;

#[derive(Default, Clone, Copy, PartialEq, Eq)]
pub struct Capabilities {
pub CLIENT_LONG_PASSWORD: bool,
pub CLIENT_FOUND_ROWS: bool,
pub CLIENT_LONG_FLAG: bool,
pub CLIENT_CONNECT_WITH_DB: bool,
pub CLIENT_NO_SCHEMA: bool,
pub CLIENT_COMPRESS: bool,
pub CLIENT_ODBC: bool,
pub CLIENT_LOCAL_FILES: bool,
pub CLIENT_IGNORE_SPACE: bool,
pub CLIENT_PROTOCOL_41: bool,
pub CLIENT_INTERACTIVE: bool,
pub CLIENT_SSL: bool,
pub CLIENT_IGNORE_SIGPIPE: bool,
pub CLIENT_TRANSACTIONS: bool,
pub CLIENT_RESERVED: bool,
pub CLIENT_SECURE_CONNECTION: bool,
pub CLIENT_MULTI_STATEMENTS: bool,
pub CLIENT_MULTI_RESULTS: bool,
pub CLIENT_PS_MULTI_RESULTS: bool,
pub CLIENT_PLUGIN_AUTH: bool,
pub CLIENT_CONNECT_ATTRS: bool,
pub CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA: bool,
pub CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS: bool,
pub CLIENT_SESSION_TRACK: bool,
pub CLIENT_DEPRECATE_EOF: bool,
pub CLIENT_OPTIONAL_RESULTSET_METADATA: bool,
pub CLIENT_ZSTD_COMPRESSION_ALGORITHM: bool,
pub CLIENT_QUERY_ATTRIBUTES: bool,
pub MULTI_FACTOR_AUTHENTICATION: bool,
pub CLIENT_CAPABILITY_EXTENSION: bool,
pub CLIENT_SSL_VERIFY_SERVER_CERT: bool,
pub CLIENT_REMEMBER_OPTIONS: bool,
macro_rules! capabilities {
($($name:ident = $bit:literal),* $(,)?) => {
#[derive(Default, Clone, Copy, PartialEq, Eq)]
pub struct Capabilities {
$(pub $name: bool,)*
}

impl Capabilities {
pub fn to_int(self) -> u32 {
0 $(| ((self.$name as u32) << $bit))*
}

pub fn from_int(flags: u32) -> Capabilities {
Capabilities {
$($name: (flags & (1u32 << $bit)) != 0,)*
}
}
}

impl fmt::Display for Capabilities {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut first = true;
$(
if self.$name {
if !first {
f.write_str(", ")?;
}
first = false;
f.write_str(stringify!($name))?;
}
)*
let _ = first;
Ok(())
}
}
};
}

impl Capabilities {
// Constants with correct shift values from MySQL protocol
const _CLIENT_LONG_PASSWORD: u32 = 1; // 1 << 0
const _CLIENT_FOUND_ROWS: u32 = 2; // 1 << 1
const _CLIENT_LONG_FLAG: u32 = 4; // 1 << 2
const _CLIENT_CONNECT_WITH_DB: u32 = 8; // 1 << 3
const _CLIENT_NO_SCHEMA: u32 = 16; // 1 << 4
const _CLIENT_COMPRESS: u32 = 32; // 1 << 5
const _CLIENT_ODBC: u32 = 64; // 1 << 6
const _CLIENT_LOCAL_FILES: u32 = 128; // 1 << 7
const _CLIENT_IGNORE_SPACE: u32 = 256; // 1 << 8
const _CLIENT_PROTOCOL_41: u32 = 512; // 1 << 9
const _CLIENT_INTERACTIVE: u32 = 1024; // 1 << 10
const _CLIENT_SSL: u32 = 2048; // 1 << 11
const _CLIENT_IGNORE_SIGPIPE: u32 = 4096; // 1 << 12
const _CLIENT_TRANSACTIONS: u32 = 8192; // 1 << 13
const _CLIENT_RESERVED: u32 = 16384; // 1 << 14
const _CLIENT_SECURE_CONNECTION: u32 = 32768; // 1 << 15
const _CLIENT_MULTI_STATEMENTS: u32 = 65536; // 1 << 16
const _CLIENT_MULTI_RESULTS: u32 = 131072; // 1 << 17
const _CLIENT_PS_MULTI_RESULTS: u32 = 262144; // 1 << 18
const _CLIENT_PLUGIN_AUTH: u32 = 524288; // 1 << 19
const _CLIENT_CONNECT_ATTRS: u32 = 1048576; // 1 << 20
const _CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA: u32 = 2097152; // 1 << 21
const _CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS: u32 = 4194304; // 1 << 22
const _CLIENT_SESSION_TRACK: u32 = 8388608; // 1 << 23
const _CLIENT_DEPRECATE_EOF: u32 = 16777216; // 1 << 24
const _CLIENT_OPTIONAL_RESULTSET_METADATA: u32 = 33554432; // 1 << 25
const _CLIENT_ZSTD_COMPRESSION_ALGORITHM: u32 = 67108864; // 1 << 26
const _CLIENT_QUERY_ATTRIBUTES: u32 = 134217728; // 1 << 27
const _MULTI_FACTOR_AUTHENTICATION: u32 = 268435456; // 1 << 28
const _CLIENT_CAPABILITY_EXTENSION: u32 = 536870912; // 1 << 29
const _CLIENT_SSL_VERIFY_SERVER_CERT: u32 = 1073741824; // 1 << 30
const _CLIENT_REMEMBER_OPTIONS: u32 = 2147483648; // 1 << 31
// Bit positions from the MySQL protocol.
capabilities! {
CLIENT_LONG_PASSWORD = 0,
CLIENT_FOUND_ROWS = 1,
CLIENT_LONG_FLAG = 2,
CLIENT_CONNECT_WITH_DB = 3,
CLIENT_NO_SCHEMA = 4,
CLIENT_COMPRESS = 5,
CLIENT_ODBC = 6,
CLIENT_LOCAL_FILES = 7,
CLIENT_IGNORE_SPACE = 8,
CLIENT_PROTOCOL_41 = 9,
CLIENT_INTERACTIVE = 10,
CLIENT_SSL = 11,
CLIENT_IGNORE_SIGPIPE = 12,
CLIENT_TRANSACTIONS = 13,
CLIENT_RESERVED = 14,
CLIENT_SECURE_CONNECTION = 15,
CLIENT_MULTI_STATEMENTS = 16,
CLIENT_MULTI_RESULTS = 17,
CLIENT_PS_MULTI_RESULTS = 18,
CLIENT_PLUGIN_AUTH = 19,
CLIENT_CONNECT_ATTRS = 20,
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA = 21,
CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS = 22,
CLIENT_SESSION_TRACK = 23,
CLIENT_DEPRECATE_EOF = 24,
CLIENT_OPTIONAL_RESULTSET_METADATA = 25,
CLIENT_ZSTD_COMPRESSION_ALGORITHM = 26,
CLIENT_QUERY_ATTRIBUTES = 27,
MULTI_FACTOR_AUTHENTICATION = 28,
CLIENT_CAPABILITY_EXTENSION = 29,
CLIENT_SSL_VERIFY_SERVER_CERT = 30,
CLIENT_REMEMBER_OPTIONS = 31,
}

impl Capabilities {
pub fn reject(&mut self) {
self.CLIENT_ZSTD_COMPRESSION_ALGORITHM = false;
self.MULTI_FACTOR_AUTHENTICATION = false;
Expand All @@ -95,154 +97,6 @@ impl Capabilities {
self.CLIENT_QUERY_ATTRIBUTES = false;
}

pub fn to_int(self) -> u32 {
let mut value: u32 = 0;

// Keep in sync with the Capabilities field list above.
if self.CLIENT_LONG_PASSWORD {
value |= Self::_CLIENT_LONG_PASSWORD;
}
if self.CLIENT_FOUND_ROWS {
value |= Self::_CLIENT_FOUND_ROWS;
}
if self.CLIENT_LONG_FLAG {
value |= Self::_CLIENT_LONG_FLAG;
}
if self.CLIENT_CONNECT_WITH_DB {
value |= Self::_CLIENT_CONNECT_WITH_DB;
}
if self.CLIENT_NO_SCHEMA {
value |= Self::_CLIENT_NO_SCHEMA;
}
if self.CLIENT_COMPRESS {
value |= Self::_CLIENT_COMPRESS;
}
if self.CLIENT_ODBC {
value |= Self::_CLIENT_ODBC;
}
if self.CLIENT_LOCAL_FILES {
value |= Self::_CLIENT_LOCAL_FILES;
}
if self.CLIENT_IGNORE_SPACE {
value |= Self::_CLIENT_IGNORE_SPACE;
}
if self.CLIENT_PROTOCOL_41 {
value |= Self::_CLIENT_PROTOCOL_41;
}
if self.CLIENT_INTERACTIVE {
value |= Self::_CLIENT_INTERACTIVE;
}
if self.CLIENT_SSL {
value |= Self::_CLIENT_SSL;
}
if self.CLIENT_IGNORE_SIGPIPE {
value |= Self::_CLIENT_IGNORE_SIGPIPE;
}
if self.CLIENT_TRANSACTIONS {
value |= Self::_CLIENT_TRANSACTIONS;
}
if self.CLIENT_RESERVED {
value |= Self::_CLIENT_RESERVED;
}
if self.CLIENT_SECURE_CONNECTION {
value |= Self::_CLIENT_SECURE_CONNECTION;
}
if self.CLIENT_MULTI_STATEMENTS {
value |= Self::_CLIENT_MULTI_STATEMENTS;
}
if self.CLIENT_MULTI_RESULTS {
value |= Self::_CLIENT_MULTI_RESULTS;
}
if self.CLIENT_PS_MULTI_RESULTS {
value |= Self::_CLIENT_PS_MULTI_RESULTS;
}
if self.CLIENT_PLUGIN_AUTH {
value |= Self::_CLIENT_PLUGIN_AUTH;
}
if self.CLIENT_CONNECT_ATTRS {
value |= Self::_CLIENT_CONNECT_ATTRS;
}
if self.CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA {
value |= Self::_CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA;
}
if self.CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS {
value |= Self::_CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS;
}
if self.CLIENT_SESSION_TRACK {
value |= Self::_CLIENT_SESSION_TRACK;
}
if self.CLIENT_DEPRECATE_EOF {
value |= Self::_CLIENT_DEPRECATE_EOF;
}
if self.CLIENT_OPTIONAL_RESULTSET_METADATA {
value |= Self::_CLIENT_OPTIONAL_RESULTSET_METADATA;
}
if self.CLIENT_ZSTD_COMPRESSION_ALGORITHM {
value |= Self::_CLIENT_ZSTD_COMPRESSION_ALGORITHM;
}
if self.CLIENT_QUERY_ATTRIBUTES {
value |= Self::_CLIENT_QUERY_ATTRIBUTES;
}
if self.MULTI_FACTOR_AUTHENTICATION {
value |= Self::_MULTI_FACTOR_AUTHENTICATION;
}
if self.CLIENT_CAPABILITY_EXTENSION {
value |= Self::_CLIENT_CAPABILITY_EXTENSION;
}
if self.CLIENT_SSL_VERIFY_SERVER_CERT {
value |= Self::_CLIENT_SSL_VERIFY_SERVER_CERT;
}
if self.CLIENT_REMEMBER_OPTIONS {
value |= Self::_CLIENT_REMEMBER_OPTIONS;
}

value
}

pub fn from_int(flags: u32) -> Capabilities {
// Keep in sync with the Capabilities field list above.
Capabilities {
CLIENT_LONG_PASSWORD: (Self::_CLIENT_LONG_PASSWORD & flags) != 0,
CLIENT_FOUND_ROWS: (Self::_CLIENT_FOUND_ROWS & flags) != 0,
CLIENT_LONG_FLAG: (Self::_CLIENT_LONG_FLAG & flags) != 0,
CLIENT_CONNECT_WITH_DB: (Self::_CLIENT_CONNECT_WITH_DB & flags) != 0,
CLIENT_NO_SCHEMA: (Self::_CLIENT_NO_SCHEMA & flags) != 0,
CLIENT_COMPRESS: (Self::_CLIENT_COMPRESS & flags) != 0,
CLIENT_ODBC: (Self::_CLIENT_ODBC & flags) != 0,
CLIENT_LOCAL_FILES: (Self::_CLIENT_LOCAL_FILES & flags) != 0,
CLIENT_IGNORE_SPACE: (Self::_CLIENT_IGNORE_SPACE & flags) != 0,
CLIENT_PROTOCOL_41: (Self::_CLIENT_PROTOCOL_41 & flags) != 0,
CLIENT_INTERACTIVE: (Self::_CLIENT_INTERACTIVE & flags) != 0,
CLIENT_SSL: (Self::_CLIENT_SSL & flags) != 0,
CLIENT_IGNORE_SIGPIPE: (Self::_CLIENT_IGNORE_SIGPIPE & flags) != 0,
CLIENT_TRANSACTIONS: (Self::_CLIENT_TRANSACTIONS & flags) != 0,
CLIENT_RESERVED: (Self::_CLIENT_RESERVED & flags) != 0,
CLIENT_SECURE_CONNECTION: (Self::_CLIENT_SECURE_CONNECTION & flags) != 0,
CLIENT_MULTI_STATEMENTS: (Self::_CLIENT_MULTI_STATEMENTS & flags) != 0,
CLIENT_MULTI_RESULTS: (Self::_CLIENT_MULTI_RESULTS & flags) != 0,
CLIENT_PS_MULTI_RESULTS: (Self::_CLIENT_PS_MULTI_RESULTS & flags) != 0,
CLIENT_PLUGIN_AUTH: (Self::_CLIENT_PLUGIN_AUTH & flags) != 0,
CLIENT_CONNECT_ATTRS: (Self::_CLIENT_CONNECT_ATTRS & flags) != 0,
CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA: (Self::_CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA
& flags)
!= 0,
CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS: (Self::_CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS
& flags)
!= 0,
CLIENT_SESSION_TRACK: (Self::_CLIENT_SESSION_TRACK & flags) != 0,
CLIENT_DEPRECATE_EOF: (Self::_CLIENT_DEPRECATE_EOF & flags) != 0,
CLIENT_OPTIONAL_RESULTSET_METADATA: (Self::_CLIENT_OPTIONAL_RESULTSET_METADATA & flags)
!= 0,
CLIENT_ZSTD_COMPRESSION_ALGORITHM: (Self::_CLIENT_ZSTD_COMPRESSION_ALGORITHM & flags)
!= 0,
CLIENT_QUERY_ATTRIBUTES: (Self::_CLIENT_QUERY_ATTRIBUTES & flags) != 0,
MULTI_FACTOR_AUTHENTICATION: (Self::_MULTI_FACTOR_AUTHENTICATION & flags) != 0,
CLIENT_CAPABILITY_EXTENSION: (Self::_CLIENT_CAPABILITY_EXTENSION & flags) != 0,
CLIENT_SSL_VERIFY_SERVER_CERT: (Self::_CLIENT_SSL_VERIFY_SERVER_CERT & flags) != 0,
CLIENT_REMEMBER_OPTIONS: (Self::_CLIENT_REMEMBER_OPTIONS & flags) != 0,
}
}

/// Returns the intersection of two capability sets (AND).
/// Per MySQL protocol, the client should only request capabilities
/// that the server also advertises.
Expand All @@ -264,55 +118,3 @@ impl Capabilities {
}
}
}

impl fmt::Display for Capabilities {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut first = true;
// Keep in sync with the Capabilities field list above.
macro_rules! emit {
($field:ident) => {
if self.$field {
if !first {
f.write_str(", ")?;
}
first = false;
f.write_str(stringify!($field))?;
}
};
}
emit!(CLIENT_LONG_PASSWORD);
emit!(CLIENT_FOUND_ROWS);
emit!(CLIENT_LONG_FLAG);
emit!(CLIENT_CONNECT_WITH_DB);
emit!(CLIENT_NO_SCHEMA);
emit!(CLIENT_COMPRESS);
emit!(CLIENT_ODBC);
emit!(CLIENT_LOCAL_FILES);
emit!(CLIENT_IGNORE_SPACE);
emit!(CLIENT_PROTOCOL_41);
emit!(CLIENT_INTERACTIVE);
emit!(CLIENT_SSL);
emit!(CLIENT_IGNORE_SIGPIPE);
emit!(CLIENT_TRANSACTIONS);
emit!(CLIENT_RESERVED);
emit!(CLIENT_SECURE_CONNECTION);
emit!(CLIENT_MULTI_STATEMENTS);
emit!(CLIENT_MULTI_RESULTS);
emit!(CLIENT_PS_MULTI_RESULTS);
emit!(CLIENT_PLUGIN_AUTH);
emit!(CLIENT_CONNECT_ATTRS);
emit!(CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA);
emit!(CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS);
emit!(CLIENT_SESSION_TRACK);
emit!(CLIENT_DEPRECATE_EOF);
emit!(CLIENT_OPTIONAL_RESULTSET_METADATA);
emit!(CLIENT_ZSTD_COMPRESSION_ALGORITHM);
emit!(CLIENT_QUERY_ATTRIBUTES);
emit!(MULTI_FACTOR_AUTHENTICATION);
emit!(CLIENT_CAPABILITY_EXTENSION);
emit!(CLIENT_SSL_VERIFY_SERVER_CERT);
emit!(CLIENT_REMEMBER_OPTIONS);
let _ = first;
Ok(())
}
}
Loading
Loading