PostgreSQLInterface.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #include "PostgreSQLInterface.h"
  11. #include "VariadicSQLParser.h"
  12. // libpq-fe.h is part of PostgreSQL which must be installed on this computer to use the PostgreRepository
  13. #include "libpq-fe.h"
  14. #ifdef _CONSOLE_1
  15. #include "Console1Includes.h"
  16. #elif defined(_WIN32)
  17. #include <winsock2.h> // htonl
  18. #elif defined(_CONSOLE_2)
  19. #include "Console2Includes.h"
  20. #else
  21. #include <arpa/inet.h>
  22. #endif
  23. // alloca
  24. #ifdef _COMPATIBILITY_1
  25. #elif defined(_WIN32)
  26. #include <malloc.h>
  27. #else
  28. //#include <stdlib.h>
  29. #endif
  30. #include "RakString.h"
  31. #include "RakAssert.h"
  32. #include "BitStream.h"
  33. #include "FormatString.h"
  34. #include "LinuxStrings.h"
  35. #define PQEXECPARAM_FORMAT_TEXT 0
  36. #define PQEXECPARAM_FORMAT_BINARY 1
  37. PostgreSQLInterface::PostgreSQLInterface()
  38. {
  39. pgConn=0;
  40. isConnected=false;
  41. lastError[0]=0;
  42. pgConnAllocatedHere=false;
  43. }
  44. PostgreSQLInterface::~PostgreSQLInterface()
  45. {
  46. if (isConnected && pgConnAllocatedHere)
  47. PQfinish(pgConn);
  48. }
  49. bool PostgreSQLInterface::Connect(const char *conninfo)
  50. {
  51. if (isConnected==false)
  52. {
  53. _conninfo=conninfo;
  54. pgConn=PQconnectdb(conninfo);
  55. ConnStatusType status = PQstatus(pgConn);
  56. isConnected=status==CONNECTION_OK;
  57. if (isConnected==false)
  58. {
  59. PQfinish(pgConn);
  60. return false;
  61. }
  62. pgConnAllocatedHere=true;
  63. }
  64. return isConnected;
  65. }
  66. void PostgreSQLInterface::AssignConnection(PGconn *_pgConn)
  67. {
  68. pgConnAllocatedHere=false;
  69. pgConn=_pgConn;
  70. ConnStatusType status = PQstatus(pgConn);
  71. isConnected=status==CONNECTION_OK;
  72. }
  73. PGconn *PostgreSQLInterface::GetPGConn(void) const
  74. {
  75. return pgConn;
  76. }
  77. void PostgreSQLInterface::Disconnect(void)
  78. {
  79. if (isConnected)
  80. {
  81. PQfinish(pgConn);
  82. isConnected=false;
  83. }
  84. }
  85. void PostgreSQLInterface::Rollback(void)
  86. {
  87. PGresult *result = PQexec(pgConn, "ROLLBACK;");
  88. PQclear(result);
  89. }
  90. bool PostgreSQLInterface::IsResultSuccessful(PGresult *result, bool rollbackOnFailure)
  91. {
  92. if (result==0)
  93. return false;
  94. bool success=false;
  95. ExecStatusType execStatus = PQresultStatus(result);
  96. strcpy(lastError,PQresultErrorMessage(result));
  97. switch (execStatus)
  98. {
  99. case PGRES_COMMAND_OK:
  100. success=true;
  101. break;
  102. case PGRES_EMPTY_QUERY:
  103. break;
  104. case PGRES_TUPLES_OK:
  105. success=true;
  106. break;
  107. case PGRES_COPY_OUT:
  108. break;
  109. case PGRES_COPY_IN:
  110. break;
  111. case PGRES_BAD_RESPONSE:
  112. break;
  113. case PGRES_NONFATAL_ERROR:
  114. break;
  115. case PGRES_FATAL_ERROR:
  116. if (rollbackOnFailure)
  117. Rollback();
  118. break;
  119. }
  120. return success;
  121. }
  122. bool PostgreSQLInterface::ExecuteBlockingCommand(const char *command, PGresult **result, bool rollbackOnFailure)
  123. {
  124. *result = PQexec(pgConn, command);
  125. return IsResultSuccessful(*result, rollbackOnFailure);
  126. }
  127. bool PostgreSQLInterface::PQGetValueFromBinary(int *output, PGresult *result, unsigned int rowIndex, const char *columnName)
  128. {
  129. return PQGetValueFromBinary(output,result,(int) rowIndex,columnName);
  130. }
  131. bool PostgreSQLInterface::PQGetValueFromBinary(int *output, PGresult *result, int rowIndex, const char *columnName)
  132. {
  133. int columnIndex = PQfnumber(result, columnName); if (columnIndex==-1) return false;
  134. char *binaryData = PQgetvalue(result, rowIndex, columnIndex);
  135. if (binaryData==0)
  136. return false;
  137. if (binaryData)
  138. {
  139. RakAssert(PQgetlength(result, rowIndex, columnIndex)==sizeof(int));
  140. memcpy(output, binaryData, sizeof(int));
  141. EndianSwapInPlace((char*)output, sizeof(int));
  142. return true;
  143. }
  144. return false;
  145. }
  146. bool PostgreSQLInterface::PQGetValueFromBinary(unsigned int *output, PGresult *result, int rowIndex, const char *columnName)
  147. {
  148. int columnIndex = PQfnumber(result, columnName); if (columnIndex==-1) return false;
  149. char *binaryData = PQgetvalue(result, rowIndex, columnIndex);
  150. if (binaryData==0 || PQgetlength(result, rowIndex, columnIndex)==0)
  151. return false;
  152. if (binaryData)
  153. {
  154. RakAssert(PQgetlength(result, rowIndex, columnIndex)==sizeof(unsigned int));
  155. memcpy(output, binaryData, sizeof(unsigned int));
  156. EndianSwapInPlace((char*)output, sizeof(unsigned int));
  157. return true;
  158. }
  159. return false;
  160. }
  161. bool PostgreSQLInterface::PQGetValueFromBinary(long long *output, PGresult *result, int rowIndex, const char *columnName)
  162. {
  163. int columnIndex = PQfnumber(result, columnName); if (columnIndex==-1) return false;
  164. char *binaryData = PQgetvalue(result, rowIndex, columnIndex);
  165. if (binaryData==0)
  166. return false;
  167. if (binaryData)
  168. {
  169. RakAssert(PQgetlength(result, rowIndex, columnIndex)==sizeof(long long));
  170. memcpy(output, binaryData, sizeof(long long));
  171. EndianSwapInPlace((char*)output, sizeof(long long));
  172. return true;
  173. }
  174. return false;
  175. }
  176. bool PostgreSQLInterface::PQGetValueFromBinary(float *output, PGresult *result, int rowIndex, const char *columnName)
  177. {
  178. int columnIndex = PQfnumber(result, columnName); if (columnIndex==-1) return false;
  179. char *binaryData = PQgetvalue(result, rowIndex, columnIndex);
  180. if (binaryData==0)
  181. return false;
  182. int len = PQgetlength(result, rowIndex, columnIndex);
  183. RakAssert(len==sizeof(float));
  184. RakAssert(binaryData);
  185. if (binaryData)
  186. {
  187. memcpy(output, binaryData, sizeof(float));
  188. EndianSwapInPlace((char*)output, sizeof(float));
  189. return true;
  190. }
  191. return false;
  192. }
  193. bool PostgreSQLInterface::PQGetValueFromBinary(double *output, PGresult *result, int rowIndex, const char *columnName)
  194. {
  195. int columnIndex = PQfnumber(result, columnName); if (columnIndex==-1) return false;
  196. char *binaryData = PQgetvalue(result, rowIndex, columnIndex);
  197. if (binaryData==0)
  198. return false;
  199. int len = PQgetlength(result, rowIndex, columnIndex);
  200. RakAssert(len==sizeof(double));
  201. RakAssert(binaryData);
  202. if (binaryData)
  203. {
  204. memcpy(output, binaryData, sizeof(double));
  205. EndianSwapInPlace((char*)output, sizeof(double));
  206. return true;
  207. }
  208. return false;
  209. }
  210. bool PostgreSQLInterface::PQGetValueFromBinary(bool *output, PGresult *result, int rowIndex, const char *columnName)
  211. {
  212. int columnIndex = PQfnumber(result, columnName); if (columnIndex==-1) return false;
  213. char *binaryData = PQgetvalue(result, rowIndex, columnIndex);
  214. if (binaryData==0)
  215. return false;
  216. *output = binaryData[0]!=0;
  217. // Seems to return 1 byte only
  218. /*
  219. int tempResult=0;
  220. // int len = PQgetlength(result, rowIndex, columnIndex);
  221. // RakAssert(len==sizeof(int)); // bug here, returns 0, but is an int
  222. RakAssert(binaryData);
  223. if (binaryData)
  224. {
  225. memcpy(&tempResult, binaryData, sizeof(int));
  226. EndianSwapInPlace((char*)&tempResult, sizeof(int));
  227. *output = tempResult!=0;
  228. return true;
  229. }
  230. */
  231. return true;
  232. }
  233. bool PostgreSQLInterface::PQGetValueFromBinary(RakNet::RakString *output, PGresult *result, int rowIndex, const char *columnName)
  234. {
  235. int columnIndex = PQfnumber(result, columnName); if (columnIndex==-1) return false;
  236. char *gv;
  237. gv = PQgetvalue(result, rowIndex, columnIndex);
  238. if (gv && gv[0])
  239. *output=gv;
  240. else
  241. output->Clear();
  242. return output->IsEmpty()==false;
  243. }
  244. bool PostgreSQLInterface::PQGetValueFromBinary(char **output, unsigned int *outputLength, PGresult *result, int rowIndex, const char *columnName)
  245. {
  246. return PQGetValueFromBinary(output, (int*) outputLength,result, rowIndex,columnName);
  247. }
  248. bool PostgreSQLInterface::PQGetValueFromBinary(char **output, int *outputLength, PGresult *result, int rowIndex, const char *columnName)
  249. {
  250. int columnIndex = PQfnumber(result, columnName);
  251. if (columnIndex!=-1)
  252. {
  253. *outputLength=PQgetlength(result, rowIndex, columnIndex);
  254. if (*outputLength==0)
  255. {
  256. *output=0;
  257. return false;
  258. }
  259. else
  260. {
  261. *output = (char*) rakMalloc_Ex(*outputLength,_FILE_AND_LINE_);
  262. memcpy(*output, PQgetvalue(result, rowIndex, columnIndex), *outputLength);
  263. return true;
  264. }
  265. }
  266. else
  267. return false;
  268. }
  269. void PostgreSQLInterface::EndianSwapInPlace(char* data, int dataLength)
  270. {
  271. static bool alreadyNetworkOrder=(htonl(12345) == 12345);
  272. if (alreadyNetworkOrder)
  273. return;
  274. int i;
  275. char tmp;
  276. for (i=0; i < dataLength/2; i++)
  277. {
  278. tmp=data[i];
  279. data[i]=data[dataLength-1-i];
  280. data[dataLength-1-i]=tmp;
  281. }
  282. }
  283. char *PostgreSQLInterface::GetLocalTimestamp(void)
  284. {
  285. static char strRes[512];
  286. PGresult *result;
  287. if (ExecuteBlockingCommand("SELECT LOCALTIMESTAMP", &result, false))
  288. {
  289. char *ts=PQgetvalue(result, 0, 0);
  290. if (ts)
  291. {
  292. sprintf(strRes,"Local timestamp is: %s\n", ts);
  293. }
  294. else
  295. {
  296. sprintf(strRes,"Can't read current time\n");
  297. }
  298. PQclear(result);
  299. }
  300. else
  301. sprintf(strRes,"Failed to read LOCALTIMESTAMP\n");
  302. return (char*)strRes;
  303. }
  304. long long PostgreSQLInterface::GetEpoch(void)
  305. {
  306. PGresult *result;
  307. long long out;
  308. result = QueryVariadic("EXTRACT(EPOCH FROM current_timestamp) as out);");
  309. PostgreSQLInterface::PQGetValueFromBinary(&out, result, 0, "out");
  310. PQclear(result);
  311. return out;
  312. }
  313. const char* PostgreSQLInterface::GetLastError(void) const
  314. {
  315. return (char*)lastError;
  316. }
  317. void PostgreSQLInterface::EncodeQueryInput(const char *colName, unsigned int value, RakNet::RakString &paramTypeStr, RakNet::RakString &valueStr, int &numParams, char **paramData, int *paramLength, int *paramFormat)
  318. {
  319. (void)numParams;
  320. (void)paramData;
  321. (void)paramLength;
  322. (void)paramFormat;
  323. if (paramTypeStr.IsEmpty()==false)
  324. {
  325. paramTypeStr += ", ";
  326. valueStr += ", ";
  327. }
  328. paramTypeStr += colName;
  329. valueStr += FormatString("%i", value);
  330. }
  331. void PostgreSQLInterface::EncodeQueryUpdate(const char *colName, unsigned int value, RakNet::RakString &valueStr, int &numParams, char **paramData, int *paramLength, int *paramFormat)
  332. {
  333. (void)numParams;
  334. (void)paramData;
  335. (void)paramLength;
  336. (void)paramFormat;
  337. if (valueStr.IsEmpty()==false)
  338. {
  339. valueStr += ", ";
  340. }
  341. valueStr += colName;
  342. valueStr += " = ";
  343. valueStr += FormatString("%i", value);
  344. }
  345. void PostgreSQLInterface::EncodeQueryInput(const char *colName, int value, RakNet::RakString &paramTypeStr, RakNet::RakString &valueStr, int &numParams, char **paramData, int *paramLength, int *paramFormat)
  346. {
  347. (void)numParams;
  348. (void)paramData;
  349. (void)paramLength;
  350. (void)paramFormat;
  351. if (paramTypeStr.IsEmpty()==false)
  352. {
  353. paramTypeStr += ", ";
  354. valueStr += ", ";
  355. }
  356. paramTypeStr += colName;
  357. valueStr += FormatString("%i", value);
  358. }
  359. void PostgreSQLInterface::EncodeQueryInput(const char *colName, bool value, RakNet::RakString &paramTypeStr, RakNet::RakString &valueStr, int &numParams, char **paramData, int *paramLength, int *paramFormat)
  360. {
  361. (void)numParams;
  362. (void)paramData;
  363. (void)paramLength;
  364. (void)paramFormat;
  365. if (paramTypeStr.IsEmpty()==false)
  366. {
  367. paramTypeStr += ", ";
  368. valueStr += ", ";
  369. }
  370. paramTypeStr += colName;
  371. if (value)
  372. valueStr += "true";
  373. else
  374. valueStr += "false";
  375. }
  376. void PostgreSQLInterface::EncodeQueryUpdate(const char *colName, int value, RakNet::RakString &valueStr, int &numParams, char **paramData, int *paramLength, int *paramFormat)
  377. {
  378. (void)numParams;
  379. (void)paramData;
  380. (void)paramLength;
  381. (void)paramFormat;
  382. if (valueStr.IsEmpty()==false)
  383. {
  384. valueStr += ", ";
  385. }
  386. valueStr += colName;
  387. valueStr += " = ";
  388. valueStr += FormatString("%i", value);
  389. }
  390. void PostgreSQLInterface::EncodeQueryInput(const char *colName, float value, RakNet::RakString &paramTypeStr, RakNet::RakString &valueStr, int &numParams, char **paramData, int *paramLength, int *paramFormat)
  391. {
  392. (void)numParams;
  393. (void)paramData;
  394. (void)paramLength;
  395. (void)paramFormat;
  396. if (paramTypeStr.IsEmpty()==false)
  397. {
  398. paramTypeStr += ", ";
  399. valueStr += ", ";
  400. }
  401. paramTypeStr += colName;
  402. valueStr += FormatString("%f", value);
  403. }
  404. void PostgreSQLInterface::EncodeQueryUpdate(const char *colName, float value, RakNet::RakString &valueStr, int &numParams, char **paramData, int *paramLength, int *paramFormat)
  405. {
  406. (void)numParams;
  407. (void)paramData;
  408. (void)paramLength;
  409. (void)paramFormat;
  410. if (valueStr.IsEmpty()==false)
  411. {
  412. valueStr += ", ";
  413. }
  414. valueStr += colName;
  415. valueStr += " = ";
  416. valueStr += FormatString("%f", value);
  417. }
  418. void PostgreSQLInterface::EncodeQueryInput(const char *colName, char *binaryData, int binaryDataLength, RakNet::RakString &paramTypeStr, RakNet::RakString &valueStr, int &numParams, char **paramData, int *paramLength, int *paramFormat, bool writeEmpty)
  419. {
  420. if (writeEmpty==false && (binaryData==0 || binaryDataLength==0))
  421. return;
  422. if (binaryData==0)
  423. binaryDataLength=0;
  424. if (paramTypeStr.IsEmpty()==false)
  425. {
  426. paramTypeStr += ", ";
  427. valueStr += ", ";
  428. }
  429. paramTypeStr += colName;
  430. valueStr+=FormatString("$%i::bytea", numParams+1);
  431. paramData[numParams]=binaryData;
  432. paramLength[numParams]=binaryDataLength;
  433. paramFormat[numParams]=PQEXECPARAM_FORMAT_BINARY;
  434. numParams++;
  435. }
  436. void PostgreSQLInterface::EncodeQueryUpdate(const char *colName, char *binaryData, int binaryDataLength, RakNet::RakString &valueStr, int &numParams, char **paramData, int *paramLength, int *paramFormat)
  437. {
  438. if (binaryData==0 || binaryDataLength==0)
  439. return;
  440. if (binaryData==0)
  441. binaryDataLength=0;
  442. if (valueStr.IsEmpty()==false)
  443. {
  444. valueStr += ", ";
  445. }
  446. valueStr += colName;
  447. valueStr += " = ";
  448. valueStr+=FormatString("$%i::bytea", numParams+1);
  449. paramData[numParams]=binaryData;
  450. paramLength[numParams]=binaryDataLength;
  451. paramFormat[numParams]=PQEXECPARAM_FORMAT_BINARY;
  452. numParams++;
  453. }
  454. void PostgreSQLInterface::EncodeQueryInput(const char *colName, const char *str, RakNet::RakString &paramTypeStr, RakNet::RakString &valueStr, int &numParams, char **paramData, int *paramLength, int *paramFormat, bool writeEmpty, const char *type)
  455. {
  456. if (writeEmpty==false && (str==0 || str[0]==0))
  457. return;
  458. static char *emptyStr=(char*)"";
  459. static char *emptyDate=(char*)"01/01/01";
  460. if (paramTypeStr.IsEmpty()==false)
  461. {
  462. paramTypeStr += ", ";
  463. valueStr += ", ";
  464. }
  465. paramTypeStr += colName;
  466. valueStr+=FormatString("$%i::%s", numParams+1, type);
  467. if (writeEmpty && (str==0 || str[0]==0))
  468. {
  469. if (strcmp(type,"date")==0)
  470. {
  471. paramData[numParams]=emptyDate;
  472. paramLength[numParams]=(int)strlen(emptyDate);
  473. }
  474. else
  475. {
  476. paramData[numParams]=emptyStr;
  477. paramLength[numParams]=0;
  478. }
  479. }
  480. else
  481. {
  482. paramData[numParams]=(char*) str;
  483. paramLength[numParams]=(int) strlen(str);
  484. }
  485. paramFormat[numParams]=PQEXECPARAM_FORMAT_TEXT;
  486. numParams++;
  487. }
  488. void PostgreSQLInterface::EncodeQueryUpdate(const char *colName, const char *str, RakNet::RakString &valueStr, int &numParams, char **paramData, int *paramLength, int *paramFormat, const char *type)
  489. {
  490. if (str==0 || str[0]==0)
  491. return;
  492. if (valueStr.IsEmpty()==false)
  493. {
  494. valueStr += ", ";
  495. }
  496. valueStr += colName;
  497. valueStr+=" = ";
  498. valueStr+=FormatString("$%i::%s", numParams+1, type);
  499. paramData[numParams]=(char*) str;
  500. paramLength[numParams]=(int) strlen(str);
  501. paramFormat[numParams]=PQEXECPARAM_FORMAT_TEXT;
  502. numParams++;
  503. }
  504. void PostgreSQLInterface::EncodeQueryInput(const char *colName, const RakNet::RakString &str, RakNet::RakString &paramTypeStr, RakNet::RakString &valueStr, int &numParams, char **paramData, int *paramLength, int *paramFormat, bool writeEmpty, const char *type)
  505. {
  506. EncodeQueryInput(colName, str.C_String(), paramTypeStr, valueStr, numParams, paramData, paramLength, paramFormat, writeEmpty, type);
  507. }
  508. void PostgreSQLInterface::EncodeQueryUpdate(const char *colName, const RakNet::RakString &str, RakNet::RakString &valueStr, int &numParams, char **paramData, int *paramLength, int *paramFormat, const char *type)
  509. {
  510. EncodeQueryUpdate(colName, str.C_String(), valueStr, numParams, paramData, paramLength, paramFormat, type);
  511. }
  512. RakNet::RakString PostgreSQLInterface::GetEscapedString(const char *input) const
  513. {
  514. unsigned long len = (unsigned long) strlen(input);
  515. char *fn = (char*) rakMalloc_Ex(len*2+1,_FILE_AND_LINE_);
  516. int error;
  517. PQescapeStringConn(pgConn, fn, input, len, &error);
  518. RakNet::RakString output;
  519. // Use assignment so it doesn't parse printf escape strings
  520. output = fn;
  521. rakFree_Ex(fn,_FILE_AND_LINE_);
  522. return output;
  523. }
  524. PGresult * PostgreSQLInterface::QueryVariadic( const char * input, ... )
  525. {
  526. RakNet::RakString query;
  527. PGresult *result;
  528. DataStructures::List<VariadicSQLParser::IndexAndType> indices;
  529. if ( input==0 || input[0]==0 )
  530. return 0;
  531. // Lookup this query in the stored query table. If it doesn't exist, prepare it.
  532. RakNet::RakString inputStr;
  533. inputStr=input;
  534. unsigned int preparedQueryIndex;
  535. for (preparedQueryIndex=0; preparedQueryIndex < preparedQueries.Size(); preparedQueryIndex++)
  536. {
  537. if (preparedQueries[preparedQueryIndex].StrICmp(inputStr)==0)
  538. break;
  539. }
  540. // Find out how many params there are
  541. // Find out the type of each param (%f, %s)
  542. indices.Clear(false, _FILE_AND_LINE_);
  543. GetTypeMappingIndices( input, indices );
  544. if (preparedQueryIndex==preparedQueries.Size())
  545. {
  546. // if (indices.Size()>0)
  547. // query += " (";
  548. RakNet::RakString formatCopy;
  549. RakNet::RakString insertion;
  550. formatCopy=input;
  551. unsigned int i;
  552. unsigned int indexOffset=0;
  553. for (i=0; i < indices.Size(); i++)
  554. {
  555. // if (i!=0)
  556. // query += ",";
  557. // query+=typeMappings[indices[i].typeMappingIndex].type;
  558. formatCopy.SetChar(indices[i].strIndex+indexOffset, '$');
  559. // if (i < 9)
  560. // formatCopy.SetChar(indices[i].strIndex+1, i+1+'0');
  561. // else
  562. insertion=RakNet::RakString("%i::%s", i+1, VariadicSQLParser::GetTypeMappingAtIndex(indices[i].typeMappingIndex));
  563. formatCopy.SetChar(indices[i].strIndex+1+indexOffset, insertion);
  564. indexOffset+=(unsigned int) insertion.GetLength()-1;
  565. }
  566. // if (indices.Size()>0)
  567. // query += ")";
  568. // query += " AS ";
  569. query += formatCopy;
  570. // query += ";\n";
  571. formatCopy+= ";\n";
  572. result = PQprepare(pgConn, RakNet::RakString("PGSQL_ExecuteVariadic_%i", preparedQueries.Size()), formatCopy.C_String(), indices.Size(), NULL);
  573. if (IsResultSuccessful(result, false))
  574. {
  575. PQclear(result);
  576. preparedQueries.Insert(inputStr, _FILE_AND_LINE_);
  577. }
  578. else
  579. {
  580. printf(formatCopy.C_String());
  581. printf("\n");
  582. printf(lastError);
  583. RakAssert(0);
  584. PQclear(result);
  585. return 0;
  586. }
  587. }
  588. // char *paramData[512];
  589. // int paramLength[512];
  590. // int paramFormat[512];
  591. va_list argptr;
  592. va_start(argptr, input);
  593. char **paramData;
  594. int *paramLength;
  595. int *paramFormat;
  596. ExtractArguments(argptr, indices, &paramData, &paramLength);
  597. paramFormat=RakNet::OP_NEW_ARRAY<int>(indices.Size(),_FILE_AND_LINE_);
  598. for (unsigned int i=0; i < indices.Size(); i++)
  599. paramFormat[i]=PQEXECPARAM_FORMAT_BINARY;
  600. result = PQexecPrepared(pgConn, RakNet::RakString("PGSQL_ExecuteVariadic_%i", preparedQueryIndex), indices.Size(), paramData, paramLength, paramFormat, PQEXECPARAM_FORMAT_BINARY );
  601. VariadicSQLParser::FreeArguments(indices, paramData, paramLength);
  602. RakNet::OP_DELETE_ARRAY(paramFormat,_FILE_AND_LINE_);
  603. va_end(argptr);
  604. if (IsResultSuccessful(result, false)==false)
  605. {
  606. printf(lastError);
  607. PQclear(result);
  608. return 0;
  609. }
  610. return result;
  611. }
  612. /*
  613. PGresult * PostgreSQLInterface::QueryVariadic( const char * input, ... )
  614. {
  615. RakNet::RakString query;
  616. PGresult *result;
  617. unsigned int i;
  618. DataStructures::List<IndexAndType> indices;
  619. if ( input==0 || input[0]==0 )
  620. return 0;
  621. // Find out how many params there are
  622. // Find out the type of each param (%f, %s)
  623. GetTypeMappingIndices( input, indices );
  624. char *paramData[512];
  625. int paramLength[512];
  626. int paramFormat[512];
  627. va_list argptr;
  628. int variadicArgIndex;
  629. va_start(argptr, input);
  630. for (variadicArgIndex=0, i=0; i < indices.Size(); i++, variadicArgIndex++)
  631. {
  632. if (typeMappings[indices[i].typeMappingIndex].inputType=='i' ||
  633. typeMappings[indices[i].typeMappingIndex].inputType=='d')
  634. {
  635. int val = va_arg( argptr, int );
  636. paramData[i]=(char*) &val;
  637. paramLength[i]=sizeof(val);
  638. if (RakNet::BitStream::IsNetworkOrder()==false) RakNet::BitStream::ReverseBytesInPlace((unsigned char*) paramData[i], paramLength[i]);
  639. }
  640. else if (typeMappings[indices[i].typeMappingIndex].inputType=='s')
  641. {
  642. char* val = va_arg( argptr, char* );
  643. paramData[i]=val;
  644. paramLength[i]=(int) strlen(val);
  645. }
  646. else if (typeMappings[indices[i].typeMappingIndex].inputType=='b')
  647. {
  648. bool val = va_arg( argptr, bool );
  649. paramData[i]=(char*) &val;
  650. paramLength[i]=sizeof(bool);
  651. if (RakNet::BitStream::IsNetworkOrder()==false) RakNet::BitStream::ReverseBytesInPlace((unsigned char*) paramData[i], paramLength[i]);
  652. }
  653. else if (typeMappings[indices[i].typeMappingIndex].inputType=='f')
  654. {
  655. float val = va_arg( argptr, float );
  656. paramData[i]=(char*) &val;
  657. paramLength[i]=sizeof(float);
  658. if (RakNet::BitStream::IsNetworkOrder()==false) RakNet::BitStream::ReverseBytesInPlace((unsigned char*) paramData[i], paramLength[i]);
  659. }
  660. else if (typeMappings[indices[i].typeMappingIndex].inputType=='g')
  661. {
  662. double val = va_arg( argptr, double );
  663. paramData[i]=(char*) &val;
  664. paramLength[i]=sizeof(double);
  665. if (RakNet::BitStream::IsNetworkOrder()==false) RakNet::BitStream::ReverseBytesInPlace((unsigned char*) paramData[i], paramLength[i]);
  666. }
  667. else if (typeMappings[indices[i].typeMappingIndex].inputType=='a')
  668. {
  669. char* val = va_arg( argptr, char* );
  670. paramData[i]=val;
  671. variadicArgIndex++;
  672. paramLength[i]=va_arg( argptr, unsigned int );
  673. }
  674. paramFormat[i]=PQEXECPARAM_FORMAT_BINARY;
  675. }
  676. // Replace each %whatever with $index::type
  677. RakNet::RakString inputCopy;
  678. inputCopy=input;
  679. unsigned int lastIndex=0;
  680. for (i=0; i < indices.Size(); i++)
  681. {
  682. query+=inputCopy.SubStr(lastIndex, indices[i].strIndex-lastIndex);
  683. query+=RakNet::RakString("$%i::", i+1);
  684. query+=typeMappings[indices[i].typeMappingIndex].type;
  685. lastIndex=indices[i].strIndex+2; // +2 is to skip the %whateverCharacter
  686. }
  687. query+=inputCopy.SubStr(lastIndex, (unsigned int)-1);
  688. result = PQexecParams(pgConn, query.C_String(),indices.Size(),0,paramData,paramLength,paramFormat,PQEXECPARAM_FORMAT_BINARY);
  689. if (IsResultSuccessful(result, false)==false)
  690. {
  691. PQclear(result);
  692. return 0;
  693. }
  694. return result;
  695. }
  696. */
  697. void PostgreSQLInterface::ClearResult(PGresult *result)
  698. {
  699. PQclear(result);
  700. }
粤ICP备19079148号