denizzzka / dpq2
1
///
2
module dpq2.value;
3

4
import dpq2.oids;
5

6
@safe:
7

8
/**
9
Represents table cell or argument value
10

11
Internally it is a ubyte[].
12
If it returned by Answer methods it contains a reference to the data of
13
the server answer and it can not be accessed after Answer is destroyed.
14
*/
15
struct Value
16
{
17
    private
18
    {
19
        bool _isNull = true;
20
        OidType _oidType = OidType.Undefined;
21

22
        ValueFormat _format;
23
    }
24

25
    package immutable(ubyte)[] _data;
26

27
    // FIXME:
28
    // The pointer returned by PQgetvalue points to storage that is part of the PGresult structure.
29
    // One should not modify the data it points to, and one must explicitly copy the data into other
30
    // storage if it is to be used past the lifetime of the PGresult structure itself.
31
    // Thus, it is need to store reference to Answer here to ensure that result is still available.
32
    // (Also see DIP1000)
33
    /// ctor
34 1
    this(immutable(ubyte)[] data, in OidType oidType, bool isNull = false, in ValueFormat format = ValueFormat.BINARY) inout pure
35
    {
36
        import std.exception: enforce;
37

38
        //TODO: it is possible to skip this check for fixed-size values?
39 1
        enforce(data.length <= int.max, `data.length is too big for use as Postgres value`);
40

41 1
        this._data = data;
42 1
        this._format = format;
43 1
        this._oidType = oidType;
44 1
        this._isNull = isNull;
45
    }
46

47
    /// Null Value constructor
48 1
    this(in ValueFormat format, in OidType oidType) pure
49
    {
50 1
        this._format = format;
51 1
        this._oidType = oidType;
52
    }
53

54
    @safe const pure nothrow @nogc
55
    {
56
        /// Indicates if the value is NULL
57
        bool isNull()
58
        {
59 1
            return _isNull;
60
        }
61

62
        /// Indicates if the value is array type
63
        bool isArray()
64
        {
65 1
            return dpq2.oids.isSupportedArray(oidType);
66
        }
67
        alias isSupportedArray = isArray; //TODO: deprecate
68

69
        /// Returns Oid of the value
70
        OidType oidType()
71
        {
72 1
            return _oidType;
73
        }
74

75
        /// Returns ValueFormat representation (text or binary)
76
        ValueFormat format()
77
        {
78 1
            return _format;
79
        }
80
    }
81

82
    package void oidType(OidType type) @safe pure nothrow @nogc
83
    {
84 1
        _oidType = type;
85
    }
86

87
    immutable(ubyte)[] data() pure const
88
    {
89
        import std.exception;
90
        import core.exception;
91

92 1
        enforce!AssertError(!isNull, "Attempt to read NULL value", __FILE__, __LINE__);
93

94 1
        return _data;
95
    }
96

97
    ///
98
    string toString() const @trusted
99
    {
100
        import vibe.data.bson: Bson;
101
        import dpq2.conv.to_bson;
102
        import std.conv: to;
103

104 0
        return this.as!Bson.toString~"::"~oidType.to!string~"("~(format == ValueFormat.TEXT? "t" : "b")~")";
105
    }
106
}
107

108
@system unittest
109
{
110
    import dpq2.conv.to_d_types;
111
    import core.exception: AssertError;
112

113 1
    Value v = Value(ValueFormat.BINARY, OidType.Int4);
114

115 1
    bool exceptionFlag = false;
116

117
    try
118 1
        cast(void) v.as!int;
119
    catch(AssertError e)
120 1
        exceptionFlag = true;
121

122 1
    assert(exceptionFlag);
123
}
124

125
///
126
enum ValueFormat : int {
127
    TEXT, ///
128
    BINARY ///
129
}
130

131
import std.conv: to, ConvException;
132

133
/// Conversion exception types
134
enum ConvExceptionType
135
{
136
    NOT_ARRAY, /// Format of the value isn't array
137
    NOT_BINARY, /// Format of the column isn't binary
138
    NOT_TEXT, /// Format of the column isn't text string
139
    NOT_IMPLEMENTED, /// Support of this type isn't implemented (or format isn't matches to specified D type)
140
    SIZE_MISMATCH, /// Value size is not matched to the Postgres value or vice versa
141
    CORRUPTED_JSONB, /// Corrupted JSONB value
142
    DATE_VALUE_OVERFLOW, /// Date value isn't fits to Postgres binary Date value
143
    DIMENSION_MISMATCH, /// Array dimension size is not matched to the Postgres array
144
    CORRUPTED_ARRAY, /// Corrupted array value
145
    OUT_OF_RANGE, /// Index is out of range
146
}
147

148
/// Value conversion exception
149
class ValueConvException : ConvException
150
{
151
    const ConvExceptionType type; /// Exception type
152

153 1
    this(ConvExceptionType t, string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) pure @safe
154
    {
155 1
        type = t;
156 1
        super(msg, file, line, next);
157
    }
158
}
159

160
package void throwTypeComplaint(OidType receivedType, string expectedType, string file = __FILE__, size_t line = __LINE__) pure
161
{
162 1
    throw new ValueConvException(
163
            ConvExceptionType.NOT_IMPLEMENTED,
164
            "Format of the column ("~to!string(receivedType)~") doesn't match to D native "~expectedType,
165
            file, line
166
        );
167
}

Read our documentation on viewing source code .

Loading