1 module postgresql.core;
2 
3 public
4 {
5     import postgresql.value: Value;
6     import postgresql.protocol: PGType, Field;
7 }
8 
9 package
10 {
11     import std.regex;
12 
13     auto regexParam = ctRegex!(`\$\d+`, "g");
14 
15     void _debug(A...)(lazy A args)
16     {
17         debug version (POSTGRESQL_USE_DEBUG)
18         {
19             import std.stdio;
20             writefln(args);
21         }
22     }
23 }
24 
25 import std.traits;
26 
27 /**
28 * Error container
29 *
30 * API is stable
31 */
32 struct PgError
33 {
34     //@disable this();
35     private
36     {
37         string  _msg;
38         int     _code = -1;
39     }
40 
41     @property const nothrow @safe @nogc
42     {
43         ///// Returns true if no error, otherwise false
44         bool empty()
45         {
46             return _code <= 0 && !_msg;
47         }
48 
49         /// Error code
50         int code()
51         {
52             return _code;
53         }
54 
55         /// Error text
56         const(string) msg()
57         {
58             return _msg;
59         }
60 
61         T opCast(T)()
62         if ( is(T == bool) )
63         {
64             return !this.empty;
65         }
66     }
67 
68     this(in string m, int c = -1) nothrow @safe
69     {
70         _msg  = m.dup;
71         _code = c;
72     }
73 }
74 ///
75 unittest
76 {
77     PgError empty;
78 
79     assert(empty.empty);
80     assert(!empty);
81     assert(empty.code == -1);
82     assert(empty.msg  == "");
83 
84 
85     auto error = PgError("Some error", 100);
86 
87     assert(error);
88     assert(!error.empty);
89     assert(error.code == 100);
90     assert(error.msg  == "Some error");
91 }
92 
93 interface ILink
94 {
95     @property bool   isAttached();
96     @property string error();
97 
98     bool attach(bool wait = true);
99     void detach();
100 
101     final bool begin()
102     {
103         return exec("BEGIN");
104     }
105 
106     final bool commit()
107     {
108         return exec("COMMIT");
109     }
110 
111     final void rollback()
112     {
113         exec("ROLLBACK");
114     }
115 
116     final bool exec(A ...)(in string query, A args)
117     {
118         return exec(query, valueArray(args));
119     }
120 
121     bool exec(in string query, Value[] args = null);
122 
123     bool query(T, A ...)(ref T result, in string query, A args)
124     {
125         return query(result, query, valueArray(args));
126     }
127 
128     bool query(T)(ref T result, in string query, Value[] args = null);
129 }
130 
131 
132 enum bool isResult(T) = isCallable!(T.reset)     && arity!(T.reset) == 0
133                      // setCols(size_t)
134                      //&& isCallable!(T.setCols)
135                      //&& arity!(T.setCols) == 1
136                      //&& is(Parameters!(T.setCols)[0] == size_t)
137                      // setRows(size_t)
138                      //&& isCallable!(T.setRows)
139                      //&& arity!(T.setRows) == 1
140                      //&& is(Parameters!(T.setRows)[0] == size_t)
141                      // rowBegin(size_t)
142                      && isCallable!(T.rowBegin)
143                      && arity!(T.rowBegin) == 1
144                      && is(Parameters!(T.rowBegin)[0] == size_t)
145                      // rowEnd(size_t)
146                      && isCallable!(T.rowEnd)
147                      && arity!(T.rowEnd) == 1
148                      && is(Parameters!(T.rowEnd)[0] == size_t)
149                      // dataAdd(size_t row, size_t col, Value val)
150                      && isCallable!(T.dataAdd)
151                      && arity!(T.dataAdd) == 3
152                      && is(Parameters!(T.dataAdd)[0] == size_t)
153                      && is(Parameters!(T.dataAdd)[1] == size_t)
154                      && is(Parameters!(T.dataAdd)[2] == Value)
155                       ;
156