1 module dpq2.args;
2 
3 @safe:
4 
5 public import dpq2.conv.from_d_types;
6 public import dpq2.conv.from_bson;
7 
8 import dpq2;
9 import std.conv: to;
10 import std..string: toStringz;
11 
12 /// Query parameters
13 struct QueryParams
14 {
15     string sqlCommand; /// SQL command
16     ValueFormat resultFormat = ValueFormat.BINARY; /// Result value format
17     private Value[] _args; // SQL command arguments
18 
19     /// SQL command arguments
20     @property void args(Value[] vargs)
21     {
22         _args = vargs;
23     }
24 
25     /// ditto
26     @property ref inout (Value[]) args() inout pure
27     {
28         return _args;
29     }
30 
31     /// Useful for simple text-only query params
32     /// Postgres infers a data type for the parameter in the same way it would do for an untyped literal string.
33     @property void argsFromArray(in string[] arr)
34     {
35         _args.length = arr.length;
36 
37         foreach(i, ref a; _args)
38             a = toValue(arr[i], ValueFormat.TEXT);
39     }
40 
41     @property string preparedStatementName() const { return sqlCommand; }
42     @property void preparedStatementName(string s){ sqlCommand = s; }
43 }
44 
45 /// Used as parameters by PQexecParams-like functions
46 package struct InternalQueryParams
47 {
48     private
49     {
50         const(string)* sqlCommand;
51         Oid[] oids;
52         int[] formats;
53         int[] lengths;
54         const(ubyte)*[] values;
55     }
56 
57     ValueFormat resultFormat;
58 
59     this(in QueryParams* qp) pure
60     {
61         sqlCommand = &qp.sqlCommand;
62         resultFormat = qp.resultFormat;
63 
64         oids = new Oid[qp.args.length];
65         formats = new int[qp.args.length];
66         lengths = new int[qp.args.length];
67         values = new const(ubyte)* [qp.args.length];
68 
69         for(int i = 0; i < qp.args.length; ++i)
70         {
71             oids[i] = qp.args[i].oidType;
72             formats[i] = qp.args[i].format;
73 
74             if(!qp.args[i].isNull)
75             {
76                 lengths[i] = qp.args[i].data.length.to!int;
77 
78                 immutable ubyte[] zeroLengthArg = [123]; // fake value, isn't used as argument
79 
80                 if(qp.args[i].data.length == 0)
81                     values[i] = &zeroLengthArg[0];
82                 else
83                     values[i] = &qp.args[i].data[0];
84             }
85         }
86     }
87 
88     /// Values used by PQexecParams-like functions
89     const(char)* command() pure const
90     {
91         return cast(const(char)*) (*sqlCommand).toStringz;
92     }
93 
94     /// ditto
95     const(char)* stmtName() pure const
96     {
97         return command();
98     }
99 
100     /// ditto
101     int nParams() pure const
102     {
103         return values.length.to!int;
104     }
105 
106     /// ditto
107     const(Oid)* paramTypes() pure
108     {
109         if(oids.length == 0)
110             return null;
111         else
112             return &oids[0];
113     }
114 
115     /// ditto
116     const(ubyte*)* paramValues() pure
117     {
118         if(values.length == 0)
119             return null;
120         else
121             return &values[0];
122     }
123 
124     /// ditto
125     const(int)* paramLengths() pure
126     {
127         if(lengths.length == 0)
128             return null;
129         else
130             return &lengths[0];
131     }
132 
133     /// ditto
134     const(int)* paramFormats() pure
135     {
136         if(formats.length == 0)
137             return null;
138         else
139             return &formats[0];
140     }
141 }