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