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 void argsVariadic(Targs ...)(Targs t_args) 43 { 44 _args.length = t_args.length; 45 46 static foreach(i, T; Targs) 47 { 48 _args[i] = toValue!T(t_args[i]); 49 } 50 } 51 52 @property string preparedStatementName() const { return sqlCommand; } 53 @property void preparedStatementName(string s){ sqlCommand = s; } 54 } 55 56 unittest 57 { 58 QueryParams qp; 59 qp.argsVariadic(123, "asd", true); 60 61 assert(qp.args[0] == 123.toValue); 62 assert(qp.args[1] == "asd".toValue); 63 assert(qp.args[2] == true.toValue); 64 } 65 66 /// Used as parameters by PQexecParams-like functions 67 package struct InternalQueryParams 68 { 69 private 70 { 71 const(string)* sqlCommand; 72 Oid[] oids; 73 int[] formats; 74 int[] lengths; 75 const(ubyte)*[] values; 76 } 77 78 ValueFormat resultFormat; 79 80 this(in QueryParams* qp) pure 81 { 82 sqlCommand = &qp.sqlCommand; 83 resultFormat = qp.resultFormat; 84 85 oids = new Oid[qp.args.length]; 86 formats = new int[qp.args.length]; 87 lengths = new int[qp.args.length]; 88 values = new const(ubyte)* [qp.args.length]; 89 90 for(int i = 0; i < qp.args.length; ++i) 91 { 92 oids[i] = qp.args[i].oidType; 93 formats[i] = qp.args[i].format; 94 95 if(!qp.args[i].isNull) 96 { 97 lengths[i] = qp.args[i].data.length.to!int; 98 99 immutable ubyte[] zeroLengthArg = [123]; // fake value, isn't used as argument 100 101 if(qp.args[i].data.length == 0) 102 values[i] = &zeroLengthArg[0]; 103 else 104 values[i] = &qp.args[i].data[0]; 105 } 106 } 107 } 108 109 /// Values used by PQexecParams-like functions 110 const(char)* command() pure const 111 { 112 return cast(const(char)*) (*sqlCommand).toStringz; 113 } 114 115 /// ditto 116 const(char)* stmtName() pure const 117 { 118 return command(); 119 } 120 121 /// ditto 122 int nParams() pure const 123 { 124 return values.length.to!int; 125 } 126 127 /// ditto 128 const(Oid)* paramTypes() pure 129 { 130 if(oids.length == 0) 131 return null; 132 else 133 return &oids[0]; 134 } 135 136 /// ditto 137 const(ubyte*)* paramValues() pure 138 { 139 if(values.length == 0) 140 return null; 141 else 142 return &values[0]; 143 } 144 145 /// ditto 146 const(int)* paramLengths() pure 147 { 148 if(lengths.length == 0) 149 return null; 150 else 151 return &lengths[0]; 152 } 153 154 /// ditto 155 const(int)* paramFormats() pure 156 { 157 if(formats.length == 0) 158 return null; 159 else 160 return &formats[0]; 161 } 162 }