1 // Written in D programming language 2 /** 3 * This module defines high-level wrapper around libpq bindings. 4 * 5 * The major goals: 6 * <ul> 7 * <li>Get more control over library errors (by converting to exceptions)</li> 8 * <li>Create layer that can be mocked in purpose of unittesting</li> 9 * </ul> 10 * 11 * Copyright: © 2014 DSoftOut 12 * License: Subject to the terms of the MIT license, as written in the included LICENSE file. 13 * Authors: NCrashed <ncrashed@gmail.com> 14 */ 15 module pgator.db.pq.api; 16 17 import dpq2.answer; 18 public import pgator.db.pq.types.oids; 19 import pgator.db.connection; 20 import pgator.db.pq.types.conv; 21 import vibe.data.bson; 22 import dlogg.log; 23 24 /** 25 * Prototype: PGResult 26 */ 27 interface IPGresult 28 { 29 synchronized: 30 31 /** 32 * Prototype: PQresultStatus 33 */ 34 ExecStatusType resultStatus() nothrow const; 35 36 /** 37 * Prototype: PQresStatus 38 * Note: same as resultStatus, but converts 39 * the enum to human-readable string. 40 */ 41 string resStatus() const; 42 43 /** 44 * Prototype: PQresultErrorMessage 45 */ 46 string resultErrorMessage() const; 47 48 /** 49 * Prototype: PQclear 50 */ 51 //void clear() nothrow; 52 53 /** 54 * Prototype: PQntuples 55 */ 56 size_t ntuples() const nothrow; 57 58 /** 59 * Prototype: PQnfields 60 */ 61 size_t nfields() const nothrow; 62 63 /** 64 * Prototype: PQfname 65 */ 66 string fname(size_t colNumber) const; 67 68 /** 69 * Prototype: PQfformat 70 */ 71 bool isBinary(size_t colNumber) const; 72 73 /** 74 * Prototype: PQgetvalue 75 */ 76 string asString(size_t rowNumber, size_t colNumber) const; 77 78 /** 79 * Prototype: PQgetvalue 80 */ 81 ubyte[] asBytes(size_t rowNumber, size_t colNumber) const; 82 83 /** 84 * Prototype: PQgetisnull 85 */ 86 bool getisnull(size_t rowNumber, size_t colNumber) const; 87 88 /** 89 * Prototype: PQftype 90 */ 91 OidType ftype(size_t colNumber) const; 92 93 /** 94 * Creates Bson from result in column echelon order. 95 * 96 * Bson consists of named arrays of column values. 97 */ 98 Bson asColumnBson(shared IConnection conn) const; 99 100 /// Getting local logger 101 protected shared(ILogger) logger() nothrow; 102 } 103 104 /** 105 * Prototype: PGconn 106 */ 107 interface IPGconn 108 { 109 synchronized: 110 111 /** 112 * Prototype: PQconnectPoll 113 */ 114 PostgresPollingStatusType poll() nothrow; 115 116 /** 117 * Prototype: PQstatus 118 */ 119 ConnStatusType status() nothrow; 120 121 /** 122 * Prototype: PQfinish 123 * Note: this function should be called even 124 * there was an error. 125 */ 126 void finish() nothrow; 127 128 /** 129 * Prototype: PQflush 130 */ 131 bool flush() nothrow const; 132 133 /** 134 * Prototype: PQresetStart 135 * Throws: PGReconnectException 136 */ 137 void resetStart(); 138 139 /** 140 * Prototype: PQresetPoll 141 */ 142 PostgresPollingStatusType resetPoll() nothrow; 143 144 /** 145 * Prototype: PQerrorMessage 146 */ 147 string errorMessage() const nothrow @property; 148 149 /** 150 * Prototype: PQsendQueryParams 151 * Note: This is simplified version of the command that 152 * handles only string params. 153 * Warning: libpq doesn't support multiple SQL commands in 154 * the function. See the sendQueryParamsExt as 155 * an extended version of the function. 156 * Throws: PGQueryException 157 */ 158 void sendQueryParams(string command, string[] paramValues); 159 160 /** 161 * Prototype: PQsendQuery 162 * Throws: PGQueryException 163 */ 164 void sendQuery(string command); 165 166 /** 167 * Like sendQueryParams but uses libpq escaping functions 168 * and sendQuery. 169 * 170 * The main advantage of the function is ability to handle 171 * multiple SQL commands in one query. 172 * Throws: PGQueryException 173 */ 174 void sendQueryParamsExt(string command, string[] paramValues); 175 176 /** 177 * Prototype: PQgetResult 178 * Note: Even when PQresultStatus indicates a fatal error, 179 * PQgetResult should be called until it returns a null pointer 180 * to allow libpq to process the error information completely. 181 * Note: A null pointer is returned when the command is complete and t 182 * here will be no more results. 183 */ 184 shared(IPGresult) getResult(); 185 186 /** 187 * Prototype: PQconsumeInput 188 * Throws: PGQueryException 189 */ 190 void consumeInput(); 191 192 /** 193 * Prototype: PQisBusy 194 */ 195 bool isBusy() nothrow; 196 197 /** 198 * Prototype: PQescapeLiteral 199 * Throws: PGEscapeException 200 */ 201 string escapeLiteral(string msg); 202 203 /** 204 * Prototype: PQparameterStatus 205 * Throws: PGParamNotExistException 206 */ 207 string parameterStatus(string param); 208 209 /** 210 * Prototype: PQsetNoticeProcessor 211 */ 212 PQnoticeProcessor setNoticeProcessor(PQnoticeProcessor proc, void* arg) nothrow; 213 214 /// Getting local logger 215 protected shared(ILogger) logger() nothrow; 216 217 string server() nothrow; 218 } 219 220 /** 221 * OOP styled libpq wrapper to automatically handle library loading/unloading and 222 * to provide mockable layer for unittests. 223 */ 224 shared interface IPostgreSQL 225 { 226 /** 227 * Prototype: PQconnectStart 228 * Throws: PGMemoryLackException 229 */ 230 shared(IPGconn) startConnect(string conninfo); 231 }