1 module dpq2.value; 2 3 @safe: 4 5 import dpq2.oids; 6 7 /// Minimal Postgres value 8 struct Value 9 { 10 private 11 { 12 bool _isNull = true; 13 OidType _oidType = OidType.Undefined; 14 15 ValueFormat _format; 16 } 17 18 package ubyte[] _data; 19 20 // FIXME: 21 // The pointer returned by PQgetvalue points to storage that is part of the PGresult structure. 22 // One should not modify the data it points to, and one must explicitly copy the data into other 23 // storage if it is to be used past the lifetime of the PGresult structure itself. 24 // Thus, it is need to store reference to Answer here to ensure that result is still available. 25 26 this(ubyte[] data, in OidType oidType, bool isNull, in ValueFormat format = ValueFormat.BINARY) pure 27 { 28 this._data = data; 29 this._format = format; 30 this._oidType = oidType; 31 this._isNull = isNull; 32 } 33 34 /// Null Value constructor 35 this(in ValueFormat format, in OidType oidType) pure 36 { 37 this._format = format; 38 this._oidType = oidType; 39 } 40 41 @safe const pure nothrow @nogc 42 { 43 /// Indicates if the value is NULL 44 bool isNull() 45 { 46 return _isNull; 47 } 48 49 /// Indicates if the value is supported array type 50 bool isSupportedArray() 51 { 52 return dpq2.oids.isSupportedArray(oidType); 53 } 54 55 /// Returns OidType of the value 56 OidType oidType() 57 { 58 return _oidType; 59 } 60 61 /// Returns ValueFormat representation (text or binary) 62 ValueFormat format() 63 { 64 return _format; 65 } 66 } 67 68 package void oidType(OidType type) @safe pure nothrow @nogc 69 { 70 _oidType = type; 71 } 72 73 inout (ubyte[]) data() pure inout 74 { 75 import std.exception; 76 import core.exception; 77 78 enforceEx!AssertError(!isNull, "Attempt to read NULL value", __FILE__, __LINE__); 79 80 return _data; 81 } 82 83 debug string toString() const @trusted 84 { 85 import vibe.data.bson: Bson; 86 import dpq2.conv.to_bson; 87 import std.conv: to; 88 89 return this.as!Bson.toString~"::"~oidType.to!string~"("~(format == ValueFormat.TEXT? "t" : "b")~")"; 90 } 91 } 92 93 @trusted unittest 94 { 95 import dpq2.conv.to_d_types; 96 import core.exception: AssertError; 97 98 Value v = Value(ValueFormat.BINARY, OidType.Int4); 99 100 bool exceptionFlag = false; 101 102 try 103 cast(void) v.as!int; 104 catch(AssertError e) 105 exceptionFlag = true; 106 107 assert(exceptionFlag); 108 } 109 110 enum ValueFormat : int { 111 TEXT, 112 BINARY 113 } 114 115 import std.conv: to, ConvException; 116 117 /// Conversion exception types 118 enum ConvExceptionType 119 { 120 NOT_ARRAY, /// Format of the value isn't array 121 NOT_BINARY, /// Format of the column isn't binary 122 NOT_TEXT, /// Format of the column isn't text string 123 NOT_IMPLEMENTED, /// Support of this type isn't implemented (or format isn't matches to specified D type) 124 SIZE_MISMATCH, /// Result value size is not matched to the received Postgres value 125 CORRUPTED_JSONB, /// Corrupted JSONB value 126 DATE_VALUE_OVERFLOW, /// Date value isn't fits to Postgres binary Date value 127 } 128 129 class ValueConvException : ConvException 130 { 131 const ConvExceptionType type; /// Exception type 132 133 this(ConvExceptionType t, string msg, string file, size_t line) pure @safe 134 { 135 type = t; 136 super(msg, file, line); 137 } 138 }