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