Alias MySQLVal

MySQLVal is mysql-native's tagged algebraic type that supports only @safe usage (see TaggedAlgebraic for more information on the features of this type). Note that TaggedAlgebraic has UFCS methods that are not available without importing that module in your code.

alias MySQLVal = taggedalgebraic.taggedalgebraic.TaggedAlgebraic!(mysql.types._MYTYPE);

The type can hold any possible type that MySQL can use or return. The MYTYPE union, which is a private union for the project, defines the names of the types that can be stored. These names double as the names for the MySQLVal.Kind enumeration. To that end, this is the entire union definition:

private union _MYTYPE
{
	ubyte[] Blob;
	const(ubyte)[] CBlob;

	typeof(null) Null;
	bool Bit;
	ubyte UByte;
	byte Byte;
	ushort UShort;
	short Short;
	uint UInt;
	int Int;
	ulong ULong;
	long Long;
	float Float;
	double Double;
	std.datetime.DateTime DateTime;
	std.datetime.TimeOfDay Time;
	Timestamp Timestamp;
	std.datetime.Date Date;

	string Text;
	const(char)[] CText;

	// pointers
	const(bool)* BitRef;
	const(ubyte)* UByteRef;
	const(byte)* ByteRef;
	const(ushort)* UShortRef;
	const(short)* ShortRef;
	const(uint)* UIntRef;
	const(int)* IntRef;
	const(ulong)* ULongRef;
	const(long)* LongRef;
	const(float)* FloatRef;
	const(double)* DoubleRef;
	const(DateTime)* DateTimeRef;
	const(TimeOfDay)* TimeRef;
	const(Date)* DateRef;
	const(string)* TextRef;
	const(char[])* CTextRef;
	const(ubyte[])* BlobRef;
	const(Timestamp)* TimestampRef;
}

Note that the pointers are all const, as the only use case in mysql-native for them is as rebindable parameters to a Prepared struct.

MySQLVal allows operations, field, and member function access for each of the supported types without unwrapping the MySQLVal value. For example:

import mysql.safe;

// support for comparison is valid for any type that supports it
assert(conn.queryValue("SELECT COUNT(*) FROM sometable") > 20);

// access members of supporting types without unwrapping or verifying type first
assert(conn.queryValue("SELECT updated_date FROM someTable WHERE id=5").year == 2020);

// arithmetic is supported, return type may vary
auto val = conn.queryValue("SELECT some_integer FROM sometable WHERE id=5") + 100;
static assert(is(typeof(val) == MySQLVal));
assert(val.kind == MySQLVal.Kind.Int);

// this will be a double and not a MySQLVal, because all types that support
// addition with a double result in a double.
auto val2 = conn.queryValue("SELECT some_float FROM sometable WHERE id=5") + 100.0;
static assert(is(typeof(val2) == double));

Note that per [TaggedAlgebraic's API](https://vibed.org/api/taggedalgebraic.taggedalgebraic/TaggedAlgebraic), using operators or members of a MySQLVal that aren't valid for the currently held type will throw an assertion error. If you wish to avoid this, and are not sure of the actual type, first validate the type is as you expect using the kind member.

MySQLVal is used in all operations interally for mysql-native, and explicitly for all safe API calls. Version 3.0.x and earlier of the mysql-native library used Variant, so this module provides multiple shims to allow code to "just work", and also provides conversion back to Variant.

See the Safe Migration document for more details.