1 /* @source ajsql **************************************************************
2 **
3 ** AJAX SQL functions
4 **
5 ** @author Copyright (C) 2006 Michael K. Schuster
6 ** @version $Revision: 1.36 $
7 ** @modified $Date: 2013/06/29 22:25:51 $ by $Author: rice $
8 ** @@
9 **
10 ** This library is free software; you can redistribute it and/or
11 ** modify it under the terms of the GNU Lesser General Public
12 ** License as published by the Free Software Foundation; either
13 ** version 2.1 of the License, or (at your option) any later version.
14 **
15 ** This library is distributed in the hope that it will be useful,
16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 ** Lesser General Public License for more details.
19 **
20 ** You should have received a copy of the GNU Lesser General Public
21 ** License along with this library; if not, write to the Free Software
22 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
23 ** MA 02110-1301, USA.
24 **
25 ******************************************************************************/
26
27 /* ========================================================================= */
28 /* ============================= include files ============================= */
29 /* ========================================================================= */
30
31 #include "ajlib.h"
32
33 #include "ajsql.h"
34 #include "ajmath.h"
35 #include "ajtime.h"
36
37 #include <string.h>
38 #include <limits.h>
39
40 #ifdef HAVE_MYSQL
41 #ifdef WIN32
42 #include <windows.h>
43 #include <winsock2.h>
44 #endif /* WIN32 */
45 #include "mysql.h"
46 #endif /* HAVE_MYSQL */
47
48 #ifdef HAVE_POSTGRESQL
49 #include "libpq-fe.h"
50 #endif /* HAVE_POSTGRESQL */
51
52
53
54
55 /* ========================================================================= */
56 /* =============================== constants =============================== */
57 /* ========================================================================= */
58
59
60
61
62 /* ========================================================================= */
63 /* =========================== global variables ============================ */
64 /* ========================================================================= */
65
66
67
68
69 /* ========================================================================= */
70 /* ============================= private data ============================== */
71 /* ========================================================================= */
72
73
74
75
76 /* ========================================================================= */
77 /* =========================== private constants =========================== */
78 /* ========================================================================= */
79
80
81
82
83 /* #conststatic sqlconnectionKClient ******************************************
84 **
85 ** #value [const char**] sqlconnectionKClient AJAX SQL Connection client
86 ** library enumeration. The following strings are used for conversion in
87 ** database operations and correspond to AjESqlconnectionClient.
88 ** #see AjESqlconnectionClient
89 **
90 ******************************************************************************/
91
92 static const char *sqlconnectionKClient[] =
93 {
94 NULL,
95 "mysql",
96 "postgresql",
97 NULL
98 };
99
100
101
102
103 /* ========================================================================= */
104 /* =========================== private variables =========================== */
105 /* ========================================================================= */
106
107
108
109
110 /* #varstatic initialisation **************************************************
111 **
112 ** #value [AjBool] sqlGInit Private boolean variable to ascertain that
113 ** ajSqlInit has been called once and only once.
114 **
115 ******************************************************************************/
116
117 static AjBool sqlGInit = AJFALSE;
118
119
120
121
122 /* #varstatic statistics ******************************************************
123 **
124 ** #value [ajuint] sqlconnectionGCountTotal
125 ** Count of all AJAX SQL Connection objects
126 ** #value [ajuint] sqlconnectionGCountFree
127 ** Count of freed AJAX SQL Connection objects
128 ** #value [ajuint] sqlconnectionGCountError
129 ** Count of error
130 ** #value [ajuint] sqlstatementGCountTotal
131 ** Count of all AJAX SQL Statement objects
132 ** #value [ajuint] sqlstatementGCountFree
133 ** Count of freed AJAX SQL Statement objects
134 ** #value [ajuint] sqlstatementGCountError
135 ** Count of errors
136 **
137 ******************************************************************************/
138
139 #ifdef AJ_SAVESTATS
140
141 static ajuint sqlconnectionGCountTotal = 0U;
142 static ajuint sqlconnectionGCountFree = 0U;
143 static ajuint sqlconnectionGCountError = 0U;
144 static ajuint sqlstatementGCountTotal = 0U;
145 static ajuint sqlstatementGCountFree = 0U;
146 static ajuint sqlstatementGCountError = 0U;
147
148 #endif /* AJ_SAVESTATS */
149
150
151
152
153 /* ==================================================================== */
154 /* ======================== private functions ========================= */
155 /* ==================================================================== */
156
157
158
159
160 #ifdef HAVE_MYSQL
161
162 static AjPSqlconnection sqlconnectionMysqlNewData(
163 const AjPStr user,
164 const AjPStr password,
165 const AjPStr host,
166 const AjPStr port,
167 const AjPStr socketfile,
168 const AjPStr database,
169 AjBool debug);
170
171 static AjPSqlstatement sqlstatementMysqlNewRun(AjPSqlconnection sqlc,
172 const AjPStr statement,
173 AjBool debug);
174
175 #endif /* HAVE_MYSQL */
176
177 #ifdef HAVE_POSTGRESQL
178
179 static AjPSqlconnection sqlconnectionPostgresqlNewData(
180 const AjPStr user,
181 const AjPStr password,
182 const AjPStr host,
183 const AjPStr port,
184 const AjPStr socketfile,
185 const AjPStr database,
186 AjBool debug);
187
188 static AjPSqlstatement sqlstatementPostgresqlNewRun(AjPSqlconnection sqlc,
189 const AjPStr statement,
190 AjBool debug);
191
192 #endif /* HAVE_POSTGRESQL */
193
194 static AjBool arrVoidResize(AjPVoid *thys, ajuint size);
195
196
197
198
199 /* @filesection ajsql *********************************************************
200 **
201 ** @nam1rule aj Function belongs to the AJAX library
202 ** @nam2rule Sql AJAX SQL interface to MySQL or Postgres
203 **
204 ******************************************************************************/
205
206
207
208
209 /* @datasection [none] Internals **********************************************
210 **
211 ** Function is for setup or control of internals
212 **
213 ******************************************************************************/
214
215
216
217
218 /* @section initialization ****************************************************
219 **
220 ** @fdata [none]
221 ** @fcategory internals
222 **
223 ** @nam3rule Init Initialize SQL internals
224 **
225 ** @valrule * [AjBool] True on success
226 **
227 ******************************************************************************/
228
229
230
231
232 /* @func ajSqlInit ************************************************************
233 **
234 ** Initialises implementation-specific SQL client libraries.
235 **
236 ** @return [AjBool] ajTrue if the initialisation was successful.
237 **
238 ** @release 6.2.0
239 ** @@
240 ******************************************************************************/
241
ajSqlInit(void)242 AjBool ajSqlInit(void)
243 {
244 if(sqlGInit)
245 return ajTrue;
246
247 #ifdef HAVE_MYSQL
248
249 if(mysql_library_init(0, (char **) NULL, (char **) NULL))
250 {
251 ajDebug("ajSqlInit MySQL initialisation failed.\n");
252
253 return ajFalse;
254 }
255 else
256 ajDebug("ajSqlInit MySQL client library %s\n",
257 mysql_get_client_info());
258
259 #endif /* HAVE_MYSQL */
260
261 sqlGInit = ajTrue;
262
263 return ajTrue;
264 }
265
266
267
268
269 /* @section exiting ***********************************************************
270 **
271 ** @fdata [none]
272 ** @fcategory internals
273 **
274 ** @nam3rule Exit Initialize SQL internals
275 **
276 ** @valrule * [void]
277 **
278 ******************************************************************************/
279
280
281
282
283 /* @func ajSqlExit ************************************************************
284 **
285 ** Finalises implementation-specific SQL client libraries.
286 **
287 ** @return [void]
288 **
289 ** @release 6.2.0
290 ** @@
291 ******************************************************************************/
292
ajSqlExit(void)293 void ajSqlExit(void)
294 {
295 if(!sqlGInit)
296 return;
297
298 #ifdef HAVE_MYSQL
299
300 mysql_library_end();
301
302 #endif /* HAVE_MYSQL */
303
304 #ifdef AJ_SAVESTATS
305
306 ajDebug("SQL Connection usage: "
307 "%u opened, %u closed, %u in use, %u failed\n",
308 sqlconnectionGCountTotal, sqlconnectionGCountFree,
309 sqlconnectionGCountTotal - sqlconnectionGCountFree,
310 sqlconnectionGCountError);
311
312 ajDebug("SQL Statement usage: "
313 "%u opened, %u closed, %u in use, %u failed\n",
314 sqlstatementGCountTotal, sqlstatementGCountFree,
315 sqlstatementGCountTotal - sqlstatementGCountFree,
316 sqlstatementGCountError);
317
318 #endif /* AJ_SAVESTATS */
319
320 sqlGInit = ajFalse;
321
322 return;
323 }
324
325
326
327
328 /* @datasection [AjPSqlconnection] SQL Connection *****************************
329 **
330 ** Functions for manipulating AJAX SQL Connections.
331 **
332 ** @nam2rule Sqlconnection Functions for manipulating AJAX SQL Connections.
333 **
334 ******************************************************************************/
335
336
337
338
339 #ifdef HAVE_MYSQL
340 /* @funcstatic sqlconnectionMysqlNewData **************************************
341 **
342 ** MySQL client library-specific AJAX SQL Connection constructor, which also
343 ** constructs a client library-specific (MYSQL *) connection object.
344 **
345 ** Configuration options will be read from the [client] and [EMBOSS] groups
346 ** of the default my.cnf options file.
347 **
348 ** A connection to a MySQL server is established.
349 **
350 ** @param [r] user [const AjPStr] SQL account user name
351 ** @param [r] password [const AjPStr] SQL account password
352 ** @param [r] host [const AjPStr] SQL server hostname or IP address
353 ** @param [r] port [const AjPStr] SQL server port number
354 ** @param [r] socketfile [const AjPStr] SQL server UNIX socket file name
355 ** MySQL: Absolute path to the socket file.
356 ** @param [r] database [const AjPStr] SQL database name
357 ** @param [r] debug [AjBool] Debug mode
358 **
359 ** @return [AjPSqlconnection] AJAX SQL Connection or NULL
360 **
361 ** @release 6.3.0
362 ** @@
363 ******************************************************************************/
364
sqlconnectionMysqlNewData(const AjPStr user,const AjPStr password,const AjPStr host,const AjPStr port,const AjPStr socketfile,const AjPStr database,AjBool debug)365 static AjPSqlconnection sqlconnectionMysqlNewData(
366 const AjPStr user,
367 const AjPStr password,
368 const AjPStr host,
369 const AjPStr port,
370 const AjPStr socketfile,
371 const AjPStr database,
372 AjBool debug)
373 {
374 unsigned long clientflag = 0;
375
376 ajuint portnumber = 0;
377
378 AjPSqlconnection sqlc = NULL;
379
380 MYSQL *Pmysql = NULL;
381
382 debug |= ajDebugTest("sqlconnectionMysqlNewData");
383
384 if(!ajStrToUint(port, &portnumber))
385 {
386 ajWarn("sqlconnectionMysqlNewData could not parse port '%S' into an "
387 "AJAX unsigned integer value.", port);
388
389 return NULL;
390 }
391
392 Pmysql = mysql_init(Pmysql);
393
394 if(Pmysql == NULL)
395 {
396 ajWarn("sqlconnectionMysqlNewData MySQL connection object "
397 "initialisation via mysql_init failed.\n");
398
399 return NULL;
400 }
401
402 /*
403 ** Read options from the [client] and [EMBOSS] groups of the
404 ** default my.cnf options file.
405 */
406
407 mysql_options(Pmysql, MYSQL_READ_DEFAULT_GROUP, "EMBOSS");
408
409 if(mysql_real_connect(Pmysql,
410 ajStrGetPtr(host),
411 ajStrGetPtr(user),
412 ajStrGetPtr(password),
413 ajStrGetPtr(database),
414 (unsigned int) portnumber,
415 ajStrGetPtr(socketfile),
416 clientflag))
417 {
418 /* The connection was successful. */
419
420 AJNEW0(sqlc);
421
422 sqlc->Pconnection = (void *) Pmysql;
423
424 sqlc->Client = ajESqlconnectionClientMySQL;
425
426 sqlc->Use = 1;
427
428 if(debug)
429 ajDebug("sqlconnectionMysqlNewData established a "
430 "MySQL connection to server '%S' on port '%S' (%d) "
431 "as user '%S' for database '%S'.\n",
432 host, port, portnumber, user, database);
433 }
434 else
435 {
436 /* The connection was not successful. */
437
438 ajDebug("sqlconnectionMysqlNewData could not establish a "
439 "MySQL connection to server '%S' on port '%S' (%d) "
440 "as user '%S' for database '%S'.\n"
441 " MySQL error: %s\n",
442 host, port, portnumber, user, database,
443 mysql_error(Pmysql));
444
445 mysql_close(Pmysql);
446
447 #ifdef AJ_SAVESTATS
448
449 sqlconnectionGCountError++;
450
451 #endif /* AJ_SAVESTATS */
452 }
453
454 return sqlc;
455 }
456
457 #endif /* HAVE_MYSQL */
458
459
460
461
462 #ifdef HAVE_POSTGRESQL
463 /* @funcstatic sqlconnectionPostgresqlNewData *********************************
464 **
465 ** PostgreSQL client library-specific AJAX SQL Connection constructor, which
466 ** also constructs a client library-specific (PGconn *) connection object.
467 **
468 ** A connection to a PostgreSQL server is established.
469 **
470 ** @param [r] user [const AjPStr] SQL account user name
471 ** @param [r] password [const AjPStr] SQL account password
472 ** @param [r] host [const AjPStr] SQL server hostname or IP address
473 ** @param [r] port [const AjPStr] SQL server port number
474 ** @param [r] socketfile [const AjPStr] SQL server UNIX socket file
475 ** PostgreSQL: Absolute path to the socket directory only.
476 ** Socket file names are then generated from this directory
477 ** information and the port number above.
478 ** See "%s/.s.PGSQL.%d" in macro UNIXSOCK_PATH in source
479 ** file pgsql/src/include/libpq/pqcomm.h
480 ** @param [r] database [const AjPStr] SQL database name
481 ** @param [r] debug [AjBool] Debug mode
482 **
483 ** @return [AjPSqlconnection] AJAX SQL Connection or NULL
484 **
485 ** @release 6.3.0
486 ** @@
487 ******************************************************************************/
488
sqlconnectionPostgresqlNewData(const AjPStr user,const AjPStr password,const AjPStr host,const AjPStr port,const AjPStr socketfile,const AjPStr database,AjBool debug)489 static AjPSqlconnection sqlconnectionPostgresqlNewData(
490 const AjPStr user,
491 const AjPStr password,
492 const AjPStr host,
493 const AjPStr port,
494 const AjPStr socketfile,
495 const AjPStr database,
496 AjBool debug)
497 {
498 AjPSqlconnection sqlc = NULL;
499
500 AjPStr conninfo = NULL;
501 AjPStr safeinfo = NULL;
502
503 PGconn *Ppgconn = NULL;
504
505 debug |= ajDebugTest("sqlconnectionPostgresqlNewData");
506
507 conninfo = ajStrNew();
508 safeinfo = ajStrNew();
509
510 /* PostgreSQL needs escaping of ' and \ to \' and \\. */
511
512 if(ajStrGetLen(user))
513 {
514 ajStrAssignS(&safeinfo, user);
515 ajStrExchangeCC(&safeinfo, "'", "\'");
516 ajStrExchangeCC(&safeinfo, "\\", "\\\\");
517
518 ajFmtPrintAppS(&conninfo, "user = '%S' ", safeinfo);
519 }
520
521 if(ajStrGetLen(password))
522 {
523 ajStrAssignS(&safeinfo, password);
524 ajStrExchangeCC(&safeinfo, "'", "\'");
525 ajStrExchangeCC(&safeinfo, "\\", "\\\\");
526
527 ajFmtPrintAppS(&conninfo, "password = '%S' ", safeinfo);
528 }
529
530 if(ajStrGetLen(host))
531 {
532 ajStrAssignS(&safeinfo, host);
533 ajStrExchangeCC(&safeinfo, "'", "\'");
534 ajStrExchangeCC(&safeinfo, "\\", "\\\\");
535
536 ajFmtPrintAppS(&conninfo, "host = '%S' ", safeinfo);
537 }
538
539 if(ajStrGetLen(socketfile))
540 {
541 ajStrAssignS(&safeinfo, socketfile);
542 ajStrExchangeCC(&safeinfo, "'", "\'");
543 ajStrExchangeCC(&safeinfo, "\\", "\\\\");
544
545 ajFmtPrintAppS(&conninfo, "host = '%S' ", safeinfo);
546 }
547
548 if(ajStrGetLen(port))
549 {
550 ajStrAssignS(&safeinfo, port);
551 ajStrExchangeCC(&safeinfo, "'", "\'");
552 ajStrExchangeCC(&safeinfo, "\\", "\\\\");
553
554 ajFmtPrintAppS(&conninfo, "port = '%S' ", safeinfo);
555 }
556
557 if(ajStrGetLen(database))
558 {
559 ajStrAssignS(&safeinfo, database);
560 ajStrExchangeCC(&safeinfo, "'", "\'");
561 ajStrExchangeCC(&safeinfo, "\\", "\\\\");
562
563 ajFmtPrintAppS(&conninfo, "dbname = '%S' ", safeinfo);
564 }
565
566 /*
567 ** Other PQconnectdb conninfo parameters:
568 **
569 ** hostaddr: Numeric IPv4 or IPv6 address of host to connect to.
570 ** connect_timeout: Maximum wait for connection, in seconds.
571 ** options: Command line options to be sent to the server.
572 ** sslmode: disable, allow, prefer, require
573 ** requiressl: Deprecated use sslmode option instead.
574 ** krbsrvname: Kerberos5 service name.
575 ** service: Service name to use for additional parameters.
576 */
577
578 /*
579 ** FIXME: sslmode should probably be configurable
580 */
581 ajFmtPrintAppS(&conninfo, "sslmode = 'disable'");
582
583 ajStrDel(&safeinfo);
584
585 Ppgconn = PQconnectdb(ajStrGetPtr(conninfo));
586
587 ajStrDel(&conninfo);
588
589 if(Ppgconn == NULL)
590 {
591 ajWarn("sqlconnectionPostgresqlNewData PostgreSQL connection object "
592 "initialisation via PQconnectdb failed.\n");
593
594 return NULL;
595 }
596
597 switch(PQstatus(Ppgconn))
598 {
599 case CONNECTION_OK:
600
601 AJNEW0(sqlc);
602
603 sqlc->Pconnection = (void *) Ppgconn;
604
605 sqlc->Client = ajESqlconnectionClientPostgreSQL;
606
607 sqlc->Use = 1;
608
609 if(debug)
610 ajDebug("sqlconnectionPostgresqlNewData established a "
611 "PostgreSQL connection to server '%S' on port '%S' "
612 "as user '%S' for database '%S'\n",
613 host, port, user, database);
614
615 break;
616
617 case CONNECTION_BAD:
618
619 ajDebug("sqlconnectionPostgresqlNewData could not establish a "
620 "PostgreSQL connection to server '%S' on port '%S' "
621 "as user '%S' for database '%S'.\n"
622 " PostgreSQL error: %s\n",
623 host, port, user, database,
624 PQerrorMessage(Ppgconn));
625
626 PQfinish(Ppgconn);
627
628 #ifdef AJ_SAVESTATS
629
630 sqlconnectionGCountError++;
631
632 #endif /* AJ_SAVESTATS */
633
634 break;
635
636 default:
637
638 ajDebug("sqlconnectionPostgresqlNewData got unexpected "
639 "PQstatus return value %d.\n", PQstatus(Ppgconn));
640 }
641
642 return sqlc;
643 }
644
645 #endif /* HAVE_POSTGRESQL */
646
647
648
649
650 /* @section constructors ******************************************************
651 **
652 ** Functions for constructing AJAX SQL Connection objects.
653 **
654 ** @fdata [AjPSqlconnection]
655 **
656 ** @nam3rule New Construct a new AJAX SQL Connection
657 ** @nam4rule NewData Constructor with set of initial values
658 ** @nam4rule NewRef Constructor by incrementing the reference counter
659 **
660 ** @argrule NewData client [AjESqlconnectionClient] SQL client
661 ** @argrule NewData user [const AjPStr] SQL account user name
662 ** @argrule NewData password [const AjPStr] SQL account password
663 ** @argrule NewData host [const AjPStr] SQL server hostname or IP address
664 ** @argrule NewData port [const AjPStr] SQL server port number
665 ** @argrule NewData socketfile [const AjPStr] SQL server UNIX socket file
666 ** MySQL: Absolute path to the socket file.
667 ** PostgreSQL: Absolute path to the socket directory only.
668 ** Socket file names are then generated from this directory
669 ** information and the port number above.
670 ** See "%s/.s.PGSQL.%d" in macro UNIXSOCK_PATH in source
671 ** file pgsql/src/include/libpq/pqcomm.h
672 ** @argrule NewData database [const AjPStr] SQL database name
673 ** @argrule NewRef sqlc [AjPSqlconnection] AJAX SQL Connection
674 **
675 ** @valrule * [AjPSqlconnection] AJAX SQL Connection
676 **
677 ** @fcategory new
678 ******************************************************************************/
679
680
681
682
683 /* @func ajSqlconnectionNewData ***********************************************
684 **
685 ** Default AJAX SQL Connection constructor, which also allocates a client
686 ** library-specific connection object.
687 **
688 ** A connection to an SQL server is established.
689 **
690 ** For MySQL clients options will be read from the [client] and [EMBOSS] groups
691 ** of the default my.cnf options file.
692 **
693 ** @param [u] client [AjESqlconnectionClient] SQL client
694 ** @param [r] user [const AjPStr] SQL account user name
695 ** @param [r] password [const AjPStr] SQL account password
696 ** @param [r] host [const AjPStr] SQL server hostname or IP address
697 ** @param [r] port [const AjPStr] SQL server port number
698 ** @param [r] socketfile [const AjPStr] SQL server UNIX socket file
699 ** MySQL: Absolute path to the socket file.
700 ** PostgreSQL: Absolute path to the socket directory only.
701 ** Socket file names are then generated from this directory
702 ** information and the port number above.
703 ** See "%s/.s.PGSQL.%d" in macro UNIXSOCK_PATH in source
704 ** file pgsql/src/include/libpq/pqcomm.h
705 ** @param [r] database [const AjPStr] SQL database name
706 **
707 ** @return [AjPSqlconnection] AJAX SQL Connection or NULL
708 **
709 ** @release 6.2.0
710 ** @@
711 ******************************************************************************/
712
ajSqlconnectionNewData(AjESqlconnectionClient client,const AjPStr user,const AjPStr password,const AjPStr host,const AjPStr port,const AjPStr socketfile,const AjPStr database)713 AjPSqlconnection ajSqlconnectionNewData(AjESqlconnectionClient client,
714 const AjPStr user,
715 const AjPStr password,
716 const AjPStr host,
717 const AjPStr port,
718 const AjPStr socketfile,
719 const AjPStr database)
720 {
721 AjBool debug = AJFALSE;
722
723 AjPSqlconnection sqlc = NULL;
724
725 debug = ajDebugTest("ajSqlconnectionNewData");
726
727 if(debug)
728 ajDebug("ajSqlconnectionNewData\n"
729 " client %d\n"
730 " user '%S'\n"
731 " password '***'\n"
732 " host '%S'\n"
733 " port '%S'\n"
734 " socketfile '%S'\n"
735 " database '%S'\n",
736 client,
737 user,
738 host,
739 port,
740 socketfile,
741 database);
742
743 (void) password;
744
745 ajSqlInit();
746
747 switch(client)
748 {
749 case ajESqlconnectionClientMySQL:
750
751 #ifdef HAVE_MYSQL
752
753 sqlc = sqlconnectionMysqlNewData(user,
754 password,
755 host,
756 port,
757 socketfile,
758 database,
759 debug);
760
761 #else
762
763 ajDebug("ajSqlconnectionNewData EMBOSS AJAX library built without "
764 "MySQL client support.\n");
765
766 #endif /* HAVE_MYSQL */
767
768 break;
769
770 case ajESqlconnectionClientPostgreSQL:
771
772 #ifdef HAVE_POSTGRESQL
773
774 sqlc = sqlconnectionPostgresqlNewData(user,
775 password,
776 host,
777 port,
778 socketfile,
779 database,
780 debug);
781
782 #else
783
784 ajDebug("ajSqlconnectionNewData EMBOSS AJAX library built without "
785 "PostgreSQL client support.\n");
786
787 #endif /* HAVE_POSTGRESQL */
788
789 break;
790
791 default:
792
793 ajDebug("ajSqlconnectionNewData SQL Connection client %d "
794 "not supported.\n",
795 client);
796 }
797
798 #ifdef AJ_SAVESTATS
799
800 if(sqlc)
801 sqlconnectionGCountTotal++;
802
803 #endif /* AJ_SAVESTATS */
804
805 if(debug)
806 {
807 if(sqlc)
808 ajDebug("ajSqlconnectionNewData connected.\n");
809 else
810 ajDebug("ajSqlconnectionNewData not connected.\n");
811 }
812
813 return sqlc;
814 }
815
816
817
818
819 /* @func ajSqlconnectionNewRef ************************************************
820 **
821 ** Ensembl Object referencing function, which returns a pointer to the
822 ** Ensembl Object passed in and increases its reference count.
823 **
824 ** @param [u] sqlc [AjPSqlconnection] AJAX SQL Connection
825 **
826 ** @return [AjPSqlconnection] AJAX SQL Connection or NULL
827 **
828 ** @release 6.2.0
829 ** @@
830 ******************************************************************************/
831
ajSqlconnectionNewRef(AjPSqlconnection sqlc)832 AjPSqlconnection ajSqlconnectionNewRef(AjPSqlconnection sqlc)
833 {
834 if(!sqlc)
835 return NULL;
836
837 sqlc->Use++;
838
839 return sqlc;
840 }
841
842
843
844
845 /* @section destructors *******************************************************
846 **
847 ** Functions for destruction of AJAX SQL Connection objects.
848 **
849 ** @fdata [AjPSqlconnection]
850 **
851 ** @nam3rule Del Destroy (free) an existing AJAX SQL Connection
852 **
853 ** @argrule Del Psqlc [AjPSqlconnection*] AJAX SQL Connection address
854 **
855 ** @valrule * [void]
856 **
857 ** @fcategory delete
858 ******************************************************************************/
859
860
861
862
863 /* @func ajSqlconnectionDel ***************************************************
864 **
865 ** Default AJAX SQL Connection destructor, which disconnects from the
866 ** SQL server first, frees the client library-specific connection object and
867 ** finally the AJAX SQL Connection object.
868 **
869 ** @param [d] Psqlc [AjPSqlconnection*] AJAX SQL Connection address
870 **
871 ** @return [void]
872 **
873 ** @release 6.2.0
874 ** @@
875 ******************************************************************************/
876
ajSqlconnectionDel(AjPSqlconnection * Psqlc)877 void ajSqlconnectionDel(AjPSqlconnection *Psqlc)
878 {
879 AjBool debug = AJFALSE;
880
881 AjPSqlconnection pthis = NULL;
882
883 if(!Psqlc)
884 return;
885
886 if(!*Psqlc)
887 return;
888
889 debug = ajDebugTest("ajSqlconnectionDel");
890
891 if(debug)
892 ajDebug("ajSqlconnectionDel"
893 " *Psqlc %p\n",
894 *Psqlc);
895
896 pthis = *Psqlc;
897
898 pthis->Use--;
899
900 if(pthis->Use)
901 {
902 *Psqlc = NULL;
903
904 return;
905 }
906
907 switch(pthis->Client)
908 {
909 case ajESqlconnectionClientMySQL:
910
911 #ifdef HAVE_MYSQL
912
913 mysql_close((MYSQL *) pthis->Pconnection);
914
915 if(debug)
916 ajDebug("ajSqlconnectionDel deleted MySQL connection.\n");
917
918 #else
919
920 ajDebug("ajSqlconnectionDel got an AJAX SQL Connection, "
921 "which claims a MySQL connection, but support "
922 "for this client has not been built into the "
923 "EMBOSS AJAX library.\n");
924
925 #endif /* HAVE_MYSQL */
926
927 break;
928
929 case ajESqlconnectionClientPostgreSQL:
930
931 #ifdef HAVE_POSTGRESQL
932
933 PQfinish((PGconn *) pthis->Pconnection);
934
935 if(debug)
936 ajDebug("ajSqlconnectionDel deleted PostgreSQL connection.\n");
937
938 #else
939
940 ajDebug("ajSqlconnectionDel got an AJAX SQL Connection, "
941 "which claims a PostgreSQL connection, but support "
942 "for this client has not been built into the "
943 "EMBOSS AJAX library.\n");
944
945 #endif /* HAVE_POSTGRESQL */
946
947 break;
948
949 default:
950
951 ajDebug("ajSqlconnectionDel SQL Connection client %d "
952 "not supported.\n",
953 pthis->Client);
954 }
955
956 AJFREE(pthis);
957
958 *Psqlc = NULL;
959
960 #ifdef AJ_SAVESTATS
961
962 sqlconnectionGCountFree++;
963
964 #endif /* AJ_SAVESTATS */
965
966 return;
967 }
968
969
970
971
972 /* @section Cast **************************************************************
973 **
974 ** Functions for returning elements of an AJAX SQL Connection object.
975 **
976 ** @fdata [AjPSqlconnection]
977 **
978 ** @nam3rule Get Return AJAX SQL Connection elements
979 ** @nam4rule Client Return client element
980 ** @nam4rule Use Return the use counter element
981 ** @nam3rule Escape Escape an AJAX String based on an AJAX SQL Connection
982 ** @suffix C Return a char* escaped string
983 ** @suffix S Return an AjPStr escaped string
984 **
985 ** @argrule * sqlc [const AjPSqlconnection] AJAX SQL Connection
986 ** @argrule C Ptxt [char**] Address of the (new) SQL-escaped C-type string
987 ** @argrule S Pstr [AjPStr*] Address of the (new) SQL-escaped AJAX String
988 ** @argrule Escape str [const AjPStr] AJAX String to be escaped
989 **
990 ** @valrule Client [AjESqlconnectionClient] Client library enumeration
991 ** @valrule Use [ajuint] Use counter
992 ** @valrule Escape [AjBool] True on success
993 **
994 ** @fcategory cast
995 ******************************************************************************/
996
997
998
999
1000 /* @func ajSqlconnectionEscapeC ***********************************************
1001 **
1002 ** Escape special characters in an AJAX String for use in an SQL statement,
1003 ** taking into account the current character set of the AJAX SQL Connection
1004 ** and return a C-type character string.
1005 **
1006 ** The caller is responsible for deleting the escaped C-type character string.
1007 **
1008 ** @param [r] sqlc [const AjPSqlconnection] AJAX SQL Connection
1009 ** @param [w] Ptxt [char**] Address of the (new) SQL-escaped C-type string
1010 ** @param [r] str [const AjPStr] AJAX String to be escaped
1011 **
1012 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
1013 **
1014 ** @release 6.2.0
1015 ** @@
1016 ******************************************************************************/
1017
ajSqlconnectionEscapeC(const AjPSqlconnection sqlc,char ** Ptxt,const AjPStr str)1018 AjBool ajSqlconnectionEscapeC(const AjPSqlconnection sqlc,
1019 char **Ptxt,
1020 const AjPStr str)
1021 {
1022
1023 #ifdef HAVE_POSTGRESQL
1024
1025 int error = 0;
1026
1027 #endif /* HAVE_POSTGRESQL */
1028
1029 #if defined(HAVE_MYSQL) || defined(HAVE_POSTGRESQL)
1030
1031 size_t length = 0;
1032
1033 #endif /* defined(HAVE_MYSQL) || defined(HAVE_POSTGRESQL) */
1034
1035 if(!sqlc)
1036 return ajFalse;
1037
1038 if(!Ptxt)
1039 return ajFalse;
1040
1041 if(!str)
1042 return ajFalse;
1043
1044 switch(sqlc->Client)
1045 {
1046 case ajESqlconnectionClientMySQL:
1047
1048 #ifdef HAVE_MYSQL
1049
1050 /*
1051 ** At maximum the escaped string could be 2 * n + 1
1052 ** characters long.
1053 */
1054
1055 length = ajStrGetLen(str);
1056
1057 if(length >= LONG_MAX)
1058 ajFatal("ajSqlconnectionEscapeC exceeded the maximum length.");
1059
1060 *Ptxt = ajCharNewRes(2 * length + 1);
1061
1062 length = mysql_real_escape_string((MYSQL *) sqlc->Pconnection,
1063 *Ptxt,
1064 ajStrGetPtr(str),
1065 length);
1066
1067 #else
1068
1069 ajDebug("ajSqlconnectionEscapeC got an AJAX SQL Connection, "
1070 "which claims a MySQL connection, but support "
1071 "for this client has not been built into the "
1072 "EMBOSS AJAX library.\n");
1073
1074 #endif /* HAVE_MYSQL */
1075
1076 break;
1077
1078 case ajESqlconnectionClientPostgreSQL:
1079
1080 #ifdef HAVE_POSTGRESQL
1081
1082 /*
1083 ** At maximum the escaped string could be 2 * n + 1
1084 ** characters long.
1085 */
1086
1087 length = ajStrGetLen(str);
1088
1089 if(length >= LONG_MAX)
1090 ajFatal("ajSqlconnectionEscapeC exceeded the maximum length.");
1091
1092 *Ptxt = ajCharNewRes(2 * length + 1);
1093
1094 length = PQescapeStringConn((PGconn *) sqlc->Pconnection,
1095 *Ptxt,
1096 ajStrGetPtr(str),
1097 length,
1098 &error);
1099
1100 if(error)
1101 ajDebug("ajSqlconnectionEscapeC PostgreSQL client encountered "
1102 "an error calling PQescapeStringConn.\n"
1103 " PostgreSQL error: %s",
1104 PQerrorMessage((PGconn *) sqlc->Pconnection));
1105
1106 #else
1107
1108 ajDebug("ajSqlconnectionEscapeC got an AJAX SQL Connection, "
1109 "which claims a PostgreSQL connection, but support "
1110 "for this client has not been built into the "
1111 "EMBOSS AJAX library.\n");
1112
1113 #endif /* HAVE_POSTGRESQL */
1114
1115 break;
1116
1117 default:
1118
1119 ajDebug("ajSqlconnectionEscapeC SQL Connection client %d "
1120 "not supported.\n",
1121 sqlc->Client);
1122 }
1123
1124 return ajTrue;
1125 }
1126
1127
1128
1129
1130 /* @func ajSqlconnectionEscapeS ***********************************************
1131 **
1132 ** Escape special characters in an AJAX String for use in an SQL statement,
1133 ** taking into account the current character set of the AJAX SQL Connection
1134 ** and return an AJAX String.
1135 **
1136 ** The caller is responsible for deleting the escaped AJAX String.
1137 **
1138 ** @param [r] sqlc [const AjPSqlconnection] AJAX SQL Connection
1139 ** @param [w] Pstr [AjPStr*] Address of the (new) SQL-escaped AJAX String
1140 ** @param [r] str [const AjPStr] AJAX String to be escaped
1141 **
1142 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
1143 **
1144 ** @release 6.2.0
1145 ** @@
1146 ******************************************************************************/
1147
ajSqlconnectionEscapeS(const AjPSqlconnection sqlc,AjPStr * Pstr,const AjPStr str)1148 AjBool ajSqlconnectionEscapeS(const AjPSqlconnection sqlc,
1149 AjPStr *Pstr,
1150 const AjPStr str)
1151 {
1152 char *Ptxt = NULL;
1153
1154 if(!sqlc)
1155 return ajFalse;
1156
1157 if(!Pstr)
1158 return ajFalse;
1159
1160 if(!str)
1161 return ajFalse;
1162
1163 if(*Pstr)
1164 ajStrAssignClear(Pstr);
1165 else
1166 *Pstr = ajStrNew();
1167
1168 ajSqlconnectionEscapeC(sqlc, &Ptxt, str);
1169
1170 ajStrAssignC(Pstr, Ptxt);
1171
1172 ajCharDel(&Ptxt);
1173
1174 return ajTrue;
1175 }
1176
1177
1178
1179
1180 /* @func ajSqlconnectionGetClient *********************************************
1181 **
1182 ** Get the client element of an AJAX SQL Connection.
1183 **
1184 ** @param [r] sqlc [const AjPSqlconnection] AJAX SQL Connection
1185 **
1186 ** @return [AjESqlconnectionClient] AJAX SQL Connection client or
1187 ** ajESqlconnectionClientNULL
1188 **
1189 ** @release 6.2.0
1190 ** @@
1191 ******************************************************************************/
1192
ajSqlconnectionGetClient(const AjPSqlconnection sqlc)1193 AjESqlconnectionClient ajSqlconnectionGetClient(const AjPSqlconnection sqlc)
1194 {
1195 if(!sqlc)
1196 return ajESqlconnectionClientNULL;
1197
1198 return sqlc->Client;
1199 }
1200
1201
1202
1203
1204 /* @func ajSqlconnectionGetUse ************************************************
1205 **
1206 ** Get the use counter element of an AJAX SQL Connection.
1207 **
1208 ** @param [r] sqlc [const AjPSqlconnection] AJAX SQL Connection
1209 **
1210 ** @return [ajuint] Use counter
1211 **
1212 ** @release 6.3.0
1213 ** @@
1214 ******************************************************************************/
1215
ajSqlconnectionGetUse(const AjPSqlconnection sqlc)1216 ajuint ajSqlconnectionGetUse(const AjPSqlconnection sqlc)
1217 {
1218 if(!sqlc)
1219 return 0;
1220
1221 return sqlc->Use;
1222 }
1223
1224
1225
1226
1227 /* @section debugging *********************************************************
1228 **
1229 ** Functions for reporting of an AJAX SQL Connection object.
1230 **
1231 ** @fdata [AjPSqlconnection]
1232 ** @nam3rule Trace Report AJAX SQL Connection elements to debug file
1233 **
1234 ** @argrule Trace sqlc [const AjPSqlconnection] AJAX SQL Connection
1235 ** @argrule Trace level [ajuint] Indentation level
1236 **
1237 ** @valrule * [AjBool] ajTrue upon success, ajFalse otherwise
1238 **
1239 ** @fcategory misc
1240 ******************************************************************************/
1241
1242
1243
1244
1245 /* @func ajSqlconnectionTrace *************************************************
1246 **
1247 ** Trace an AJAX SQL Connection.
1248 **
1249 ** @param [r] sqlc [const AjPSqlconnection] AJAX SQL Connection
1250 ** @param [r] level [ajuint] Indentation level
1251 **
1252 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
1253 **
1254 ** @release 6.2.0
1255 ** @@
1256 ******************************************************************************/
1257
ajSqlconnectionTrace(const AjPSqlconnection sqlc,ajuint level)1258 AjBool ajSqlconnectionTrace(const AjPSqlconnection sqlc, ajuint level)
1259 {
1260 AjPStr indent = NULL;
1261
1262 if(!sqlc)
1263 return ajFalse;
1264
1265 indent = ajStrNew();
1266
1267 ajStrAppendCountK(&indent, ' ', level * 2);
1268
1269 ajDebug("%SajSqlconnectionTrace %p\n"
1270 "%S Pconnection %p\n"
1271 "%S Client %d\n"
1272 "%S Use %u\n",
1273 indent, sqlc,
1274 indent, sqlc->Pconnection,
1275 indent, sqlc->Client,
1276 indent, sqlc->Use);
1277
1278 ajStrDel(&indent);
1279
1280 return ajTrue;
1281 }
1282
1283
1284
1285
1286 /* @datasection [AjESqlconnectionClient] SQL Connection Client ****************
1287 **
1288 ** Functions for manipulating AJAX SQL Connection clients.
1289 **
1290 ** @nam3rule SqlconnectionClient Functions for manipulating AJAX SQL Connection
1291 ** clients.
1292 **
1293 ******************************************************************************/
1294
1295
1296
1297
1298 /* @section Misc **************************************************************
1299 **
1300 ** Functions for returning a AJAX SQL Connection Client enumeration
1301 **
1302 ** @fdata [AjESqlconnectionClient]
1303 **
1304 ** @nam4rule From AJAX SQL Connection Client query
1305 ** @nam5rule Str String object query
1306 **
1307 ** @argrule Str client [const AjPStr] Client name
1308 **
1309 ** @valrule * [AjESqlconnectionClient] AJAX SQL Connection Client enumeration
1310 **
1311 ** @fcategory misc
1312 ******************************************************************************/
1313
1314
1315
1316
1317 /* @func ajSqlconnectionClientFromStr *****************************************
1318 **
1319 ** Convert an AJAX String into an AJAX SQL Connection client element.
1320 **
1321 ** @param [r] client [const AjPStr] Client string
1322 **
1323 ** @return [AjESqlconnectionClient] AJAX SQL Connection client or
1324 ** ajESqlconnectionClientNULL
1325 **
1326 ** @release 6.3.0
1327 ** @@
1328 ******************************************************************************/
1329
ajSqlconnectionClientFromStr(const AjPStr client)1330 AjESqlconnectionClient ajSqlconnectionClientFromStr(const AjPStr client)
1331 {
1332 register AjESqlconnectionClient i = ajESqlconnectionClientNULL;
1333
1334 AjESqlconnectionClient eclient = ajESqlconnectionClientNULL;
1335
1336 for(i = ajESqlconnectionClientMySQL; sqlconnectionKClient[i]; i++)
1337 if(ajStrMatchC(client, sqlconnectionKClient[i]))
1338 eclient = i;
1339
1340 if(!eclient)
1341 ajDebug("ajSqlconnectionClientFromStr encountered "
1342 "unexpected string '%S'.\n", client);
1343
1344 return eclient;
1345 }
1346
1347
1348
1349
1350 /* @section Cast **************************************************************
1351 **
1352 ** Functions for returning attributes of an AJAX SQL Connection client
1353 ** enumeration
1354 **
1355 ** @fdata [AjESqlconnectionClient]
1356 **
1357 ** @nam4rule To Return AJAX SQL Connection Client enumeration
1358 ** @nam5rule Char Return C character string value
1359 **
1360 ** @argrule To client [AjESqlconnectionClient] AJAX SQL Connection
1361 **
1362 ** @valrule * [const char*] Client name
1363 ** @valrule *Char [const char*] Client name
1364 **
1365 ** @fcategory cast
1366 ******************************************************************************/
1367
1368
1369
1370
1371 /* @func ajSqlconnectionClientToChar ******************************************
1372 **
1373 ** Convert an AJAX SQL Connection client element into a C-type (char*) string.
1374 **
1375 ** @param [u] client [AjESqlconnectionClient] SQL Connection client
1376 **
1377 ** @return [const char*] SQL Connection client C-type (char*) string
1378 **
1379 ** @release 6.3.0
1380 ** @@
1381 ******************************************************************************/
1382
ajSqlconnectionClientToChar(AjESqlconnectionClient client)1383 const char* ajSqlconnectionClientToChar(AjESqlconnectionClient client)
1384 {
1385 register AjESqlconnectionClient i = ajESqlconnectionClientNULL;
1386
1387 if(!client)
1388 return NULL;
1389
1390 for(i = ajESqlconnectionClientMySQL;
1391 sqlconnectionKClient[i] && (i < client);
1392 i++);
1393
1394 if(!sqlconnectionKClient[i])
1395 ajDebug("ajSqlconnectionClientToChar encountered an "
1396 "out of boundary error on client %d.\n", client);
1397
1398 return sqlconnectionKClient[i];
1399 }
1400
1401
1402
1403
1404 /* @datasection [AjPSqlstatement] AJAX SQL Statement **************************
1405 **
1406 ** Functions for manipulating AJAX SQL Statements.
1407 **
1408 ** @nam2rule Sqlstatement Functions for manipulating AJAX SQL Statements.
1409 **
1410 ******************************************************************************/
1411
1412
1413
1414
1415 #ifdef HAVE_MYSQL
1416 /* @funcstatic sqlstatementMysqlNewRun ****************************************
1417 **
1418 ** MySQL client library-specific AJAX SQL Statement constructor.
1419 ** Upon construction the SQL Statement is run against the MySQL server
1420 ** specified in the AJAX SQL Connection.
1421 ** Eventual results of the SQL Statement are then stored inside this object.
1422 **
1423 ** @param [u] sqlc [AjPSqlconnection] AJAX SQL Connection
1424 ** @param [r] statement [const AjPStr] SQL statement
1425 ** @param [r] debug [AjBool] Debug mode
1426 **
1427 ** @return [AjPSqlstatement] AJAX SQL Statement or NULL
1428 **
1429 ** @release 6.3.0
1430 ** @@
1431 ******************************************************************************/
1432
sqlstatementMysqlNewRun(AjPSqlconnection sqlc,const AjPStr statement,AjBool debug)1433 static AjPSqlstatement sqlstatementMysqlNewRun(AjPSqlconnection sqlc,
1434 const AjPStr statement,
1435 AjBool debug)
1436 {
1437 AjPSqlstatement sqls = NULL;
1438
1439 MYSQL *Pmysql = NULL;
1440 MYSQL_RES *Pmysqlres = NULL;
1441
1442 debug |= ajDebugTest("sqlstatementMysqlNewRun");
1443
1444 if(!sqlc)
1445 return NULL;
1446
1447 if(!statement)
1448 return NULL;
1449
1450 Pmysql = (MYSQL *) sqlc->Pconnection;
1451
1452 if(!Pmysql)
1453 ajFatal("sqlstatementMysqlNewRun got an AJAX SQL Connection without "
1454 "a MYSQL client library-specific (MYSQL *) connection "
1455 "object.");
1456
1457 if(mysql_real_query(Pmysql,
1458 ajStrGetPtr(statement),
1459 (unsigned long) ajStrGetLen(statement)))
1460 {
1461 ajWarn("sqlstatementMysqlNewRun encountered an "
1462 "error upon calling mysql_real_query.\n"
1463 " statement: %S\n"
1464 " MySQL error: %s\n",
1465 statement,
1466 mysql_error(Pmysql));
1467
1468 #ifdef AJ_SAVESTATS
1469
1470 sqlstatementGCountError++;
1471
1472 #endif /* AJ_SAVESTATS */
1473
1474 return NULL;
1475 }
1476
1477 /*
1478 ** The SQL statement was successful, now process any data returned.
1479 ** The mysql_store_result function retrieves all rows from the
1480 ** server and stores them in the client immediately. This is can be
1481 ** memory intensive, but reduces the server load.
1482 **/
1483
1484 Pmysqlres = mysql_store_result(Pmysql);
1485
1486 if(Pmysqlres)
1487 {
1488 /*
1489 ** The SQL statement has returned a (MYSQL_RES*) result, hence
1490 ** create an AJAX SQL Statement object and set the number of rows
1491 ** selected by the SQL statement.
1492 */
1493
1494 AJNEW0(sqls);
1495
1496 sqls->Sqlconnection = ajSqlconnectionNewRef(sqlc);
1497
1498 sqls->Presult = (void *) Pmysqlres;
1499
1500 sqls->AffectedRows = 0;
1501
1502 sqls->SelectedRows = (ajulong) mysql_num_rows(Pmysqlres);
1503
1504 sqls->Columns = (ajuint) mysql_num_fields(Pmysqlres);
1505
1506 sqls->Use = 1;
1507
1508 if(debug)
1509 ajDebug("ajSqlstatementNewRun MySQL selected "
1510 "%Lu rows and %u columns.\n",
1511 sqls->SelectedRows,
1512 sqls->Columns);
1513 }
1514 else
1515 {
1516 /*
1517 ** Since the SQL statement has not returnd a (MYSQL_RES*) result,
1518 ** check whether it should have returned one.
1519 */
1520
1521 if(mysql_field_count(Pmysql))
1522 {
1523 /*
1524 ** The SQL statement was expected to return a (MYSQL_RES*)
1525 ** result.
1526 */
1527
1528 ajWarn("sqlstatementMysqlNewRun encountered an "
1529 "error upon calling mysql_store_result.\n"
1530 " statement: %S\n"
1531 " MySQL error: %s\n",
1532 statement,
1533 mysql_error(Pmysql));
1534
1535 #ifdef AJ_SAVESTATS
1536
1537 sqlstatementGCountError++;
1538
1539 #endif /* AJ_SAVESTATS */
1540 }
1541 else
1542 {
1543 /*
1544 ** The SQL statement was not expected to return a (MYSQL_RES*)
1545 ** result, hence create an AJAX SQL Statement object and set the
1546 ** number rows affected by the SQL statement.
1547 */
1548
1549 AJNEW0(sqls);
1550
1551 sqls->Sqlconnection = ajSqlconnectionNewRef(sqlc);
1552
1553 sqls->Presult = NULL;
1554
1555 sqls->AffectedRows = (ajulong) mysql_affected_rows(Pmysql);
1556
1557 sqls->SelectedRows = 0;
1558
1559 sqls->Columns = 0;
1560
1561 sqls->Use = 1;
1562
1563 if(debug)
1564 ajDebug("ajSqlstatementNewRun MySQL affected "
1565 "%Lu rows.\n",
1566 sqls->AffectedRows);
1567 }
1568 }
1569
1570 return sqls;
1571 }
1572
1573 #endif /* HAVE_MYSQL */
1574
1575
1576
1577
1578 #ifdef HAVE_POSTGRESQL
1579 /* @funcstatic sqlstatementPostgresqlNewRun ***********************************
1580 **
1581 ** PostgreSQL client library-specific AJAX SQL Statement constructor.
1582 ** Upon construction, the SQL Statement is run against the PostgreSQL server
1583 ** specified in the AJAX SQL Connection.
1584 ** Eventual results of the SQL Statement are then stored inside this object.
1585 **
1586 ** @param [u] sqlc [AjPSqlconnection] AJAX SQL Connection
1587 ** @param [r] statement [const AjPStr] SQL statement
1588 ** @param [r] debug [AjBool] Debug mode
1589 **
1590 ** @return [AjPSqlstatement] AJAX SQL Statement or NULL
1591 **
1592 ** @release 6.3.0
1593 ** @@
1594 ******************************************************************************/
1595
sqlstatementPostgresqlNewRun(AjPSqlconnection sqlc,const AjPStr statement,AjBool debug)1596 static AjPSqlstatement sqlstatementPostgresqlNewRun(AjPSqlconnection sqlc,
1597 const AjPStr statement,
1598 AjBool debug)
1599 {
1600 AjPSqlstatement sqls = NULL;
1601
1602 AjPStr affected = NULL;
1603
1604 PGconn *Ppgconn = NULL;
1605 PGresult *Ppgresult = NULL;
1606
1607 debug |= ajDebugTest("sqlstatementPostgresqlNewRun");
1608
1609 if(!sqlc)
1610 return NULL;
1611
1612 if(!statement)
1613 return NULL;
1614
1615 Ppgconn = (PGconn *) sqlc->Pconnection;
1616
1617 if(!Ppgconn)
1618 ajFatal("sqlstatementPostgresqlNewRun got AJAX SQL Connection without "
1619 "PostgreSQL client library-specific (PGconn *) connection "
1620 "object.");
1621
1622 Ppgresult = PQexec(Ppgconn, ajStrGetPtr(statement));
1623
1624 if(Ppgresult)
1625 {
1626 switch (PQresultStatus(Ppgresult))
1627 {
1628 case PGRES_EMPTY_QUERY:
1629
1630 ajDebug("sqlstatementPostgresqlNewRun PostgreSQL reported an "
1631 "empty statement string.\n"
1632 " statement: %S\n",
1633 statement);
1634
1635 PQclear(Ppgresult);
1636
1637 #ifdef AJ_SAVESTATS
1638
1639 sqlstatementGCountError++;
1640
1641 #endif /* AJ_SAVESTATS */
1642
1643 break;
1644
1645 case PGRES_COMMAND_OK:
1646
1647 /*
1648 ** PGRES_COMMAND_OK for statements that return no result
1649 ** rows but do affect rows.
1650 */
1651
1652 affected = ajStrNewC(PQcmdTuples(Ppgresult));
1653
1654 AJNEW0(sqls);
1655
1656 sqls->Sqlconnection = ajSqlconnectionNewRef(sqlc);
1657
1658 sqls->Presult = (void *) Ppgresult;
1659
1660 if(!ajStrToUlong(affected, &sqls->AffectedRows))
1661 ajWarn("sqlstatementPostgresqlNewRun could not parse "
1662 "'%S' into an AJAX unsigned long integer.",
1663 affected);
1664
1665 sqls->SelectedRows = 0;
1666
1667 sqls->Columns = 0;
1668
1669 sqls->Use = 1;
1670
1671 ajStrDel(&affected);
1672
1673 if(debug)
1674 ajDebug("ajSqlstatementNewRun PostgreSQL affected "
1675 "%Lu rows.\n",
1676 sqls->AffectedRows);
1677
1678 break;
1679
1680 case PGRES_TUPLES_OK:
1681
1682 /* PGRES_TUPLES_OK for commands that return result rows. */
1683
1684 AJNEW0(sqls);
1685
1686 sqls->Sqlconnection = ajSqlconnectionNewRef(sqlc);
1687
1688 sqls->Presult = (void *) Ppgresult;
1689
1690 sqls->AffectedRows = 0;
1691
1692 sqls->SelectedRows = (ajulong) PQntuples(Ppgresult);
1693
1694 sqls->Columns = (ajuint) PQnfields(Ppgresult);
1695
1696 sqls->Use = 1;
1697
1698 if(debug)
1699 ajDebug("ajSqlstatementNewRun PostgreSQL selected "
1700 "%Lu rows and %u columns.\n",
1701 sqls->SelectedRows,
1702 sqls->Columns);
1703
1704 break;
1705
1706 case PGRES_FATAL_ERROR:
1707
1708 ajWarn("sqlstatementPostgresqlNewRun encountered an "
1709 "error upon calling PQexec.\n"
1710 " statement: %S\n"
1711 " PostgreSQL error: %s\n",
1712 statement,
1713 PQresultErrorMessage(Ppgresult));
1714
1715 PQclear(Ppgresult);
1716
1717 #ifdef AJ_SAVESTATS
1718
1719 sqlstatementGCountError++;
1720
1721 #endif /* AJ_SAVESTATS */
1722
1723 break;
1724
1725 default:
1726
1727 ajDebug("sqlstatementPostgresqlNewRun encountered an "
1728 "unexpected status upon calling PQexec.\n"
1729 " PostgreSQL status: %s\n",
1730 PQresStatus(PQresultStatus(Ppgresult)));
1731
1732 PQclear(Ppgresult);
1733
1734 #ifdef AJ_SAVESTATS
1735
1736 sqlstatementGCountError++;
1737
1738 #endif /* AJ_SAVESTATS */
1739 }
1740 }
1741 else
1742 {
1743 ajWarn("sqlstatementPostgresqlNewRun encountered an "
1744 "error upon calling PQexec.\n"
1745 " statement: %S"
1746 " PostgreSQL error: %s\n",
1747 statement,
1748 PQerrorMessage(Ppgconn));
1749
1750 #ifdef AJ_SAVESTATS
1751
1752 sqlstatementGCountError++;
1753
1754 #endif /* AJ_SAVESTATS */
1755 }
1756
1757 return sqls;
1758 }
1759
1760 #endif /* HAVE_POSTGRESQL */
1761
1762
1763
1764
1765 /* @section constructors ******************************************************
1766 **
1767 ** Functions for constructing AJAX SQL Statement objects.
1768 **
1769 ** @fdata [AjPSqlstatement]
1770 **
1771 ** @nam3rule New Construct a new AJAX SQL Statement
1772 ** @nam4rule Ref Constructor by incrementing the reference counter
1773 ** @nam4rule Run Constructor by running a SQL statement
1774 **
1775 ** @argrule Ref sqls [AjPSqlstatement] Undocumented
1776 ** @argrule Run sqlc [AjPSqlconnection] Undocumented
1777 ** @argrule Run statement [const AjPStr] Undocumented
1778 **
1779 ** @valrule * [AjPSqlstatement] AJAX SQL Statement
1780 **
1781 ** @fcategory new
1782 ******************************************************************************/
1783
1784
1785
1786
1787 /* @func ajSqlstatementNewRef *************************************************
1788 **
1789 ** Ensembl Object referencing function, which returns a pointer to the
1790 ** Ensembl Object passed in and increases its reference count.
1791 **
1792 ** @param [u] sqls [AjPSqlstatement] AJAX SQL Statement
1793 **
1794 ** @return [AjPSqlstatement] AJAX SQL Statement or NULL
1795 **
1796 ** @release 6.2.0
1797 ** @@
1798 ******************************************************************************/
1799
ajSqlstatementNewRef(AjPSqlstatement sqls)1800 AjPSqlstatement ajSqlstatementNewRef(AjPSqlstatement sqls)
1801 {
1802 if(!sqls)
1803 return NULL;
1804
1805 sqls->Use++;
1806
1807 return sqls;
1808 }
1809
1810
1811
1812
1813 /* @func ajSqlstatementNewRun *************************************************
1814 **
1815 ** Default AJAX SQL Statement constructor. Upon construction the SQL Statement
1816 ** is run against the SQL server specified in the AJAX SQL Connection.
1817 ** Eventual results of the SQL Statement are then stored inside this object.
1818 **
1819 ** @param [u] sqlc [AjPSqlconnection] AJAX SQL Connection
1820 ** @param [r] statement [const AjPStr] SQL statement
1821 **
1822 ** @return [AjPSqlstatement] AJAX SQL Statement or NULL
1823 **
1824 ** @release 6.2.0
1825 ** @@
1826 ******************************************************************************/
1827
ajSqlstatementNewRun(AjPSqlconnection sqlc,const AjPStr statement)1828 AjPSqlstatement ajSqlstatementNewRun(AjPSqlconnection sqlc,
1829 const AjPStr statement)
1830 {
1831 AjBool debug = AJFALSE;
1832
1833 AjPSqlstatement sqls = NULL;
1834
1835 debug = ajDebugTest("ajSqlstatementNewRun");
1836
1837 if(!sqlc)
1838 return NULL;
1839
1840 if(!statement)
1841 return NULL;
1842
1843 if(debug)
1844 ajDebug("ajSqlstatementNewRun %S\n", statement);
1845
1846 switch(sqlc->Client)
1847 {
1848 case ajESqlconnectionClientMySQL:
1849
1850 #ifdef HAVE_MYSQL
1851
1852 sqls = sqlstatementMysqlNewRun(sqlc, statement, debug);
1853
1854 #else
1855
1856 ajDebug("ajSqlstatementNewRun got an AJAX SQL Connection, "
1857 "which claims a MySQL connection, but support "
1858 "for this client has not been built into the "
1859 "EMBOSS AJAX library.\n");
1860
1861 #endif /* HAVE_MYSQL */
1862
1863 break;
1864
1865 case ajESqlconnectionClientPostgreSQL:
1866
1867 #ifdef HAVE_POSTGRESQL
1868
1869 sqls = sqlstatementPostgresqlNewRun(sqlc, statement, debug);
1870
1871 #else
1872
1873 ajDebug("ajSqlstatementNewRun got an AJAX SQL Connection, "
1874 "which claims a PostgreSQL connection, but support "
1875 "for this client has not been built into the "
1876 "EMBOSS AJAX library.\n");
1877
1878 #endif /* HAVE_POSTGRESQL */
1879
1880 break;
1881
1882 default:
1883
1884 ajDebug("ajSqlstatementNewRun AJAX SQL Connection client %d "
1885 "not supported.\n",
1886 sqlc->Client);
1887 }
1888
1889 #ifdef AJ_SAVESTATS
1890
1891 if(sqls)
1892 sqlstatementGCountTotal++;
1893
1894 #endif /* AJ_SAVESTATS */
1895
1896 return sqls;
1897 }
1898
1899
1900
1901
1902 /* @section destructors *******************************************************
1903 **
1904 ** Functions for destruction of AJAX SQL Statement objects.
1905 **
1906 ** @fdata [AjPSqlstatement]
1907 **
1908 ** @nam3rule Del Destroy (free) an existing AJAX SQL Statement
1909 **
1910 ** @argrule Del Psqls [AjPSqlstatement*] AJAX SQL Statement address
1911 **
1912 ** @valrule * [void]
1913 **
1914 ** @fcategory delete
1915 ******************************************************************************/
1916
1917
1918
1919
1920 /* @func ajSqlstatementDel ****************************************************
1921 **
1922 ** Default AJAX SQL Statement destructor, which also destroys the SQL client
1923 ** library-specific result object.
1924 **
1925 ** @param [d] Psqls [AjPSqlstatement*] AJAX SQL Statement address
1926 **
1927 ** @return [void]
1928 **
1929 ** @release 6.2.0
1930 ** @@
1931 ******************************************************************************/
1932
ajSqlstatementDel(AjPSqlstatement * Psqls)1933 void ajSqlstatementDel(AjPSqlstatement *Psqls)
1934 {
1935 AjPSqlstatement pthis = NULL;
1936
1937 if(!Psqls)
1938 return;
1939
1940 if(!*Psqls)
1941 return;
1942
1943 pthis = *Psqls;
1944
1945 pthis->Use--;
1946
1947 if(pthis->Use)
1948 {
1949 *Psqls = NULL;
1950
1951 return;
1952 }
1953
1954 switch(pthis->Sqlconnection->Client)
1955 {
1956 case ajESqlconnectionClientMySQL:
1957
1958 #ifdef HAVE_MYSQL
1959
1960 mysql_free_result((MYSQL_RES *) pthis->Presult);
1961
1962 #else
1963
1964 ajDebug("ajSqlstatementDel got an AJAX SQL Connection, "
1965 "which claims a MySQL connection, but support "
1966 "for this client has not been built into the "
1967 "EMBOSS AJAX library.\n");
1968
1969 #endif /* HAVE_MYSQL */
1970
1971 break;
1972
1973 case ajESqlconnectionClientPostgreSQL:
1974
1975 #ifdef HAVE_POSTGRESQL
1976
1977 PQclear((PGresult *) pthis->Presult);
1978
1979 #else
1980
1981 ajDebug("ajSqlstatementDel got an AJAX SQL Connection, "
1982 "which claims a PostgreSQL connection, but support "
1983 "for this client has not been built into the "
1984 "EMBOSS AJAX library.\n");
1985
1986 #endif /* HAVE_POSTGRESQL */
1987
1988 break;
1989
1990 default:
1991
1992 ajDebug("ajSqlstatementDel AJAX SQL Connection client %d "
1993 "not supported.\n",
1994 pthis->Sqlconnection->Client);
1995
1996 }
1997
1998 ajSqlconnectionDel(&pthis->Sqlconnection);
1999
2000 AJFREE(pthis);
2001
2002 *Psqls = NULL;
2003
2004 #ifdef AJ_SAVESTATS
2005
2006 sqlstatementGCountFree++;
2007
2008 #endif /* AJ_SAVESTATS */
2009
2010 return;
2011 }
2012
2013
2014
2015
2016
2017 /* @section cast **************************************************************
2018 **
2019 ** @fdata [AjPSqlstatement]
2020 **
2021 ** @nam3rule Get return elements of a SQL statement
2022 ** @nam4rule Affectedrows return number of rows affected
2023 ** @nam4rule Columns return number of columns returned
2024 ** @nam4rule Identifier return identifier of a row inserted
2025 ** @nam4rule Selectedrows return number of rows selected
2026 **
2027 ** @argrule Get sqls [const AjPSqlstatement] Undocumented
2028 **
2029 ** @valrule Affectedrows [ajulong] Number of affected rows
2030 ** @valrule Columns [ajuint] Number of columns returned
2031 ** @valrule Identifier [ajuint] Identifier of a row inserted
2032 ** @valrule Selectedrows [ajulong] Number of selected rows
2033 **
2034 ** @fcategory cast
2035 **
2036 ******************************************************************************/
2037
2038
2039
2040
2041 /* @func ajSqlstatementGetAffectedrows ****************************************
2042 **
2043 ** Get the number of rows affected by a non-SELECT SQL statement.
2044 **
2045 ** @param [r] sqls [const AjPSqlstatement] AJAX SQL Statement
2046 **
2047 ** @return [ajulong] Number of affected rows
2048 **
2049 ** @release 6.2.0
2050 ** @@
2051 ******************************************************************************/
2052
ajSqlstatementGetAffectedrows(const AjPSqlstatement sqls)2053 ajulong ajSqlstatementGetAffectedrows(const AjPSqlstatement sqls)
2054 {
2055 if(!sqls)
2056 return 0;
2057
2058 return sqls->AffectedRows;
2059 }
2060
2061
2062
2063
2064 /* @func ajSqlstatementGetColumns *********************************************
2065 **
2066 ** Get the number of columns returned by a SELECT-like SQL statement.
2067 **
2068 ** @param [r] sqls [const AjPSqlstatement] AJAX SQL Statement
2069 **
2070 ** @return [ajuint] Number of selected columns
2071 **
2072 ** @release 6.2.0
2073 ** @@
2074 ******************************************************************************/
2075
ajSqlstatementGetColumns(const AjPSqlstatement sqls)2076 ajuint ajSqlstatementGetColumns(const AjPSqlstatement sqls)
2077 {
2078 if(!sqls)
2079 return 0;
2080
2081 return sqls->Columns;
2082 }
2083
2084
2085
2086
2087 /* @func ajSqlstatementGetIdentifier ******************************************
2088 **
2089 ** Get the identifier of a row inserted by the last INSERT-like SQL statement.
2090 **
2091 ** @param [r] sqls [const AjPSqlstatement] AJAX SQL Statement
2092 **
2093 ** @return [ajuint] Identifier of last inserted row
2094 **
2095 ** @release 6.2.0
2096 ** @@
2097 ******************************************************************************/
2098
ajSqlstatementGetIdentifier(const AjPSqlstatement sqls)2099 ajuint ajSqlstatementGetIdentifier(const AjPSqlstatement sqls)
2100 {
2101 ajuint identifier = 0;
2102
2103 #ifdef HAVE_MYSQL
2104
2105 MYSQL *Pmysql = NULL;
2106
2107 #endif /* HAVE_MYSQL */
2108
2109 #ifdef HAVE_POSTGRESQL
2110
2111 PGresult *Ppgresult = NULL;
2112
2113 #endif /* HAVE_POSTGRESQL */
2114
2115 if(!sqls)
2116 return 0;
2117
2118 switch(sqls->Sqlconnection->Client)
2119 {
2120 case ajESqlconnectionClientMySQL:
2121
2122 #ifdef HAVE_MYSQL
2123
2124 Pmysql = (MYSQL *) sqls->Sqlconnection->Pconnection;
2125
2126 identifier = (ajuint) mysql_insert_id(Pmysql);
2127
2128 #else
2129
2130 ajDebug("ajSqlstatementGetIdentifier got an AJAX SQL Connection, "
2131 "which claims a MySQL connection, but support "
2132 "for this client has not been built into the "
2133 "EMBOSS AJAX library.\n");
2134
2135 #endif
2136
2137 break;
2138
2139 case ajESqlconnectionClientPostgreSQL:
2140
2141 #ifdef HAVE_POSTGRESQL
2142
2143 Ppgresult = (PGresult *) sqls->Presult;
2144
2145 identifier = (ajuint) PQoidValue(Ppgresult);
2146
2147 #else
2148
2149 ajDebug("ajSqlstatementGetIdentifier got an AJAX SQL Connection, "
2150 "which claims a PostgreSQL connection, but support "
2151 "for this client has not been built into the "
2152 "EMBOSS AJAX library.\n");
2153
2154 #endif
2155 break;
2156
2157 default:
2158
2159 ajDebug("ajSqlstatementNewRun AJAX SQL Connection client %d "
2160 "not supported.\n",
2161 sqls->Sqlconnection->Client);
2162 }
2163
2164 return identifier;
2165 }
2166
2167
2168
2169
2170 /* @func ajSqlstatementGetSelectedrows ****************************************
2171 **
2172 ** Get the number of rows selected by a SELECT-like SQL statement.
2173 **
2174 ** @param [r] sqls [const AjPSqlstatement] AJAX SQL Statement
2175 **
2176 ** @return [ajulong] Number of selected rows
2177 **
2178 ** @release 6.2.0
2179 ** @@
2180 ******************************************************************************/
2181
ajSqlstatementGetSelectedrows(const AjPSqlstatement sqls)2182 ajulong ajSqlstatementGetSelectedrows(const AjPSqlstatement sqls)
2183 {
2184 if(!sqls)
2185 return 0;
2186
2187 return sqls->SelectedRows;
2188 }
2189
2190
2191
2192
2193 /* @datasection [AjISqlrow] AJAX SQL Row Iterator *****************************
2194 **
2195 ** Functions for manipulating AJAX SQL Row Iterators.
2196 **
2197 ** @nam2rule Sqlrowiter Functions for manipulating AJAX SQL Row Iterators.
2198 **
2199 ******************************************************************************/
2200
2201
2202
2203
2204 /* @section constructors ******************************************************
2205 **
2206 ** Functions for constructing AJAX SQL Row Iterator objects.
2207 **
2208 ** @fdata [AjISqlrow]
2209 **
2210 ** @nam3rule New Construct a new AJAX SQL Row Iterator
2211 **
2212 ** @argrule New sqls [AjPSqlstatement] Undocumented
2213 **
2214 ** @valrule * [AjISqlrow] AJAX SQL Row Iterator
2215 **
2216 ** @fcategory new
2217 ******************************************************************************/
2218
2219
2220
2221
2222 /* @func ajSqlrowiterNew ******************************************************
2223 **
2224 ** Default AJAX SQL Row Iterator constructor.
2225 **
2226 ** @param [u] sqls [AjPSqlstatement] AJAX SQL Statement
2227 **
2228 ** @return [AjISqlrow] AJAX SQL Row Iterator or NULL if the
2229 ** AJAX SQL Statement did not return rows and columns
2230 **
2231 ** @release 6.2.0
2232 ** @@
2233 ******************************************************************************/
2234
ajSqlrowiterNew(AjPSqlstatement sqls)2235 AjISqlrow ajSqlrowiterNew(AjPSqlstatement sqls)
2236 {
2237 AjISqlrow sqli = NULL;
2238
2239 if(!sqls)
2240 return NULL;
2241
2242 if(!sqls->SelectedRows)
2243 return NULL;
2244
2245 if(!sqls->Columns)
2246 return NULL;
2247
2248 AJNEW0(sqli);
2249
2250 sqli->Sqlstatement = ajSqlstatementNewRef(sqls);
2251
2252 sqli->Sqlrow = ajSqlrowNew(sqls->Columns);
2253
2254 sqli->Current = 0;
2255
2256 return sqli;
2257 }
2258
2259
2260
2261
2262 /* @section destructors *******************************************************
2263 **
2264 ** Functions for destruction of AJAX SQL Row Iterator objects.
2265 **
2266 ** @fdata [AjISqlrow]
2267 **
2268 ** @nam3rule Del Destroy (free) an existing AJAX SQL Row Iterator
2269 **
2270 ** @argrule Del Psqli [AjISqlrow*] AJAX SQL Row Iterator address
2271 **
2272 ** @valrule * [void]
2273 **
2274 ** @fcategory delete
2275 ******************************************************************************/
2276
2277
2278
2279
2280 /* @func ajSqlrowiterDel ******************************************************
2281 **
2282 ** Default AJAX SQL Row Iterator destructor.
2283 **
2284 ** @param [d] Psqli [AjISqlrow*] AJAX SQL Row Iterator address
2285 **
2286 ** @return [void]
2287 **
2288 ** @release 6.2.0
2289 ** @@
2290 ******************************************************************************/
2291
ajSqlrowiterDel(AjISqlrow * Psqli)2292 void ajSqlrowiterDel(AjISqlrow *Psqli)
2293 {
2294 AjISqlrow pthis = NULL;
2295
2296 if(!Psqli)
2297 return;
2298
2299 if(!*Psqli)
2300 return;
2301
2302 pthis = *Psqli;
2303
2304 ajSqlstatementDel(&pthis->Sqlstatement);
2305
2306 ajSqlrowDel(&pthis->Sqlrow);
2307
2308 AJFREE(pthis);
2309
2310 *Psqli = NULL;
2311
2312 return;
2313 }
2314
2315
2316
2317
2318 /* @section tests *************************************************************
2319 **
2320 ** @fdata [AjISqlrow]
2321 **
2322 ** @nam3rule Done Check whether iteration has ended (no more AJAX SQL Rows).
2323 **
2324 ** @argrule Done sqli [const AjISqlrow] AJAX SQL Row Iterator
2325 **
2326 ** @valrule * [AjBool] Result of test
2327 **
2328 ** @fcategory use
2329 ******************************************************************************/
2330
2331
2332
2333
2334 /* @func ajSqlrowiterDone *****************************************************
2335 **
2336 ** Tests whether an AJAX SQL Row Iterator has completed yet.
2337 **
2338 ** @param [r] sqli [const AjISqlrow] AJAX SQL Row Iterator
2339 **
2340 ** @return [AjBool] ajTrue if the iterator is exhausted
2341 **
2342 ** @release 6.2.0
2343 ** @@
2344 ******************************************************************************/
2345
ajSqlrowiterDone(const AjISqlrow sqli)2346 AjBool ajSqlrowiterDone(const AjISqlrow sqli)
2347 {
2348 if(!sqli)
2349 return ajTrue;
2350
2351 if(sqli->Current < sqli->Sqlstatement->SelectedRows)
2352 return ajFalse;
2353
2354 return ajTrue;
2355 }
2356
2357
2358
2359
2360 /* @section stepping **********************************************************
2361 **
2362 ** @fdata [AjISqlrow]
2363 **
2364 ** @nam3rule Get Next AJAX SQL Row.
2365 **
2366 ** @argrule * sqli [AjISqlrow] AJAX SQL Row Iterator
2367 **
2368 ** @valrule * [AjPSqlrow] AJAX SQL Row
2369 **
2370 ** @fcategory modify
2371 ******************************************************************************/
2372
2373
2374
2375
2376 /* @func ajSqlrowiterGet ******************************************************
2377 **
2378 ** Returns the next AJAX SQL Row using the iterator, or steps off the end.
2379 **
2380 ** @param [u] sqli [AjISqlrow] AJAX SQL Row Iterator
2381 **
2382 ** @return [AjPSqlrow] AJAX SQL Row or NULL
2383 **
2384 ** @release 6.2.0
2385 ** @@
2386 ******************************************************************************/
2387
ajSqlrowiterGet(AjISqlrow sqli)2388 AjPSqlrow ajSqlrowiterGet(AjISqlrow sqli)
2389 {
2390 register ajuint i = 0;
2391
2392 AjBool debug = AJFALSE;
2393
2394 AjPSqlrow sqlr = NULL;
2395
2396 #ifdef HAVE_MYSQL
2397
2398 unsigned long *lengths;
2399
2400 MYSQL *Pmysql = NULL;
2401 MYSQL_ROW mysqlrow;
2402
2403 #endif
2404
2405 debug = ajDebugTest("ajSqlrowiterGet");
2406
2407 if(!sqli)
2408 return NULL;
2409
2410 (void) i;
2411
2412 /* Check that the Iterator is within a valid range. */
2413
2414 if(sqli->Current >= sqli->Sqlstatement->SelectedRows)
2415 {
2416 if(debug)
2417 ajDebug("ajSqlrowiterGet got no more AJAX SQL Rows to fetch.\n");
2418
2419 return NULL;
2420 }
2421
2422 /*
2423 ** If an AJAX SQL Row already exits, reset the current column value,
2424 ** which can be used for iterating over columns of a row, otherwise
2425 ** construct a new AJAX SQL Row with the correct number of columns.
2426 */
2427
2428 if(sqli->Sqlrow)
2429 sqli->Sqlrow->Current = 0;
2430 else
2431 sqli->Sqlrow = ajSqlrowNew(sqli->Sqlstatement->Columns);
2432
2433 switch(sqli->Sqlstatement->Sqlconnection->Client)
2434 {
2435 case ajESqlconnectionClientMySQL:
2436
2437 #ifdef HAVE_MYSQL
2438
2439 mysqlrow = mysql_fetch_row(
2440 (MYSQL_RES *) sqli->Sqlstatement->Presult);
2441
2442 if(mysqlrow)
2443 {
2444 lengths = mysql_fetch_lengths(
2445 (MYSQL_RES *) sqli->Sqlstatement->Presult);
2446
2447 for(i = 0; i < sqli->Sqlstatement->Columns; i++)
2448 {
2449 ajVoidPut(&sqli->Sqlrow->Values, i, (void *) mysqlrow[i]);
2450
2451 ajLongPut(&sqli->Sqlrow->Lengths, i, (ajlong) lengths[i]);
2452 }
2453
2454 sqli->Current++;
2455
2456 sqlr = sqli->Sqlrow;
2457 }
2458 else
2459 {
2460 Pmysql =
2461 (MYSQL *) sqli->Sqlstatement->Sqlconnection->Pconnection;
2462
2463 if(mysql_errno(Pmysql))
2464 ajDebug("ajSqlrowiterGet encountered an error.\n"
2465 " MySQL error: %s", mysql_error(Pmysql));
2466 else
2467 ajDebug("ajSqlrowiterGet got no more MySQL rows "
2468 "to fetch?\n");
2469 }
2470
2471 #else
2472
2473 ajDebug("ajSqlrowiterGet got an AJAX SQL Connection, "
2474 "which claims a MySQL connection, but support "
2475 "for this client has not been built into the "
2476 "EMBOSS AJAX library.\n");
2477
2478 #endif
2479
2480 break;
2481
2482 case ajESqlconnectionClientPostgreSQL:
2483
2484 #ifdef HAVE_POSTGRESQL
2485
2486 for(i = 0; i < sqli->Sqlstatement->Columns; i++)
2487 {
2488 ajVoidPut(&sqli->Sqlrow->Values, i,
2489 (void *) PQgetvalue(
2490 (PGresult *) sqli->Sqlstatement->Presult,
2491 (int) sqli->Current,
2492 (int) i));
2493
2494 ajLongPut(&sqli->Sqlrow->Lengths, i,
2495 (ajlong) PQgetlength(
2496 (PGresult *) sqli->Sqlstatement->Presult,
2497 (int) sqli->Current,
2498 (int) i));
2499 }
2500
2501 sqli->Current++;
2502
2503 sqlr = sqli->Sqlrow;
2504
2505 #else
2506
2507 ajDebug("ajSqlrowiterGet got an AJAX SQL Connection, "
2508 "which claims a PostgreSQL connection, but support "
2509 "for this client has not been built into the "
2510 "EMBOSS AJAX library.\n");
2511
2512 #endif
2513
2514 break;
2515
2516 default:
2517
2518 ajDebug("ajSqlrowiterGet AJAX SQL Connection client %d "
2519 "not supported.\n",
2520 sqli->Sqlstatement->Sqlconnection->Client);
2521 }
2522
2523 return sqlr;
2524 }
2525
2526
2527
2528
2529 /* @section modifiers *********************************************************
2530 **
2531 ** @fdata [AjISqlrow]
2532 **
2533 ** @nam3rule Rewind Rewind to start
2534 **
2535 ** @argrule * sqli [AjISqlrow] SQL Row Iterator
2536 **
2537 ** @valrule * [AjBool] True on success
2538 **
2539 ** @fcategory modify
2540 ******************************************************************************/
2541
2542
2543
2544
2545 /* @func ajSqlrowiterRewind ***************************************************
2546 **
2547 ** Rewind an AJAX SQL Row Iterator to the start position.
2548 **
2549 ** @param [u] sqli [AjISqlrow] AJAX SQL Row Iterator
2550 **
2551 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
2552 **
2553 ** @release 6.2.0
2554 ** @@
2555 ******************************************************************************/
2556
ajSqlrowiterRewind(AjISqlrow sqli)2557 AjBool ajSqlrowiterRewind(AjISqlrow sqli)
2558 {
2559 AjBool value = AJFALSE;
2560
2561 if(!sqli)
2562 return ajFalse;
2563
2564
2565 switch(sqli->Sqlstatement->Sqlconnection->Client)
2566 {
2567 case ajESqlconnectionClientMySQL:
2568
2569 #ifdef HAVE_MYSQL
2570
2571 /* For MySQL, the cursor and the current row need resetting. */
2572
2573 sqli->Current = 0;
2574
2575 mysql_data_seek((MYSQL_RES *) sqli->Sqlstatement->Presult, 0);
2576
2577 value = ajTrue;
2578
2579 #else
2580
2581 ajDebug("ajSqlrowiterRewind got an AJAX SQL Connection, "
2582 "which claims a MySQL connection, but support "
2583 "for this client has not been built into the "
2584 "EMBOSS AJAX library.\n");
2585
2586 #endif
2587
2588 break;
2589
2590 case ajESqlconnectionClientPostgreSQL:
2591
2592 #ifdef HAVE_POSTGRESQL
2593
2594 /* For PostgreSQL, just the current row needs resetting. */
2595
2596 sqli->Current = 0;
2597
2598 value = ajTrue;
2599
2600 #else
2601
2602 ajDebug("ajSqlrowiterRewind got an AJAX SQL Connection, "
2603 "which claims a PostgreSQL connection, but support "
2604 "for this client has not been built into the "
2605 "EMBOSS AJAX library.\n");
2606
2607 #endif
2608
2609 break;
2610
2611 default:
2612
2613 ajDebug("ajSqlrowiterRewind AJAX SQL Connection client %d "
2614 "not supported.\n",
2615 sqli->Sqlstatement->Sqlconnection->Client);
2616 }
2617
2618 return value;
2619 }
2620
2621
2622
2623
2624 /* @datasection [AjPSqlrow] AJAX SQL Row **************************************
2625 **
2626 ** Functions for manipulating AJAX SQL Rows.
2627 **
2628 ** @nam2rule Sqlrow Functions for manipulating AJAX SQL Rows.
2629 **
2630 ******************************************************************************/
2631
2632
2633
2634
2635 /* @section constructors ******************************************************
2636 **
2637 ** Functions for constructing AJAX SQL Row objects.
2638 **
2639 ** @fdata [AjPSqlrow]
2640 **
2641 ** @nam3rule New Construct a new AJAX SQL Row
2642 ** @nam3rule NewRef Constructor by incrementing the reference counter
2643 **
2644 ** @argrule New columns [ajuint] Number of columns per AJAX SQL Row
2645 **
2646 ** @valrule * [AjPSqlrow] AJAX SQL Row
2647 **
2648 ** @fcategory new
2649 ******************************************************************************/
2650
2651
2652
2653
2654 /* @func ajSqlrowNew **********************************************************
2655 **
2656 ** Default AJAX SQL Row constructor.
2657 **
2658 ** @param [r] columns [ajuint] Number of columns per AJAX SQL Row
2659 **
2660 ** @return [AjPSqlrow] AJAX SQL Row
2661 **
2662 ** @release 6.2.0
2663 ** @@
2664 ******************************************************************************/
2665
ajSqlrowNew(ajuint columns)2666 AjPSqlrow ajSqlrowNew(ajuint columns)
2667 {
2668 AjPSqlrow sqlr = NULL;
2669
2670 AJNEW0(sqlr);
2671
2672 sqlr->Values = ajVoidNewRes(columns);
2673
2674 sqlr->Lengths = ajLongNewRes(columns);
2675
2676 sqlr->Columns = columns;
2677
2678 sqlr->Current = 0;
2679
2680 return sqlr;
2681 }
2682
2683
2684
2685
2686 /* @section destructors *******************************************************
2687 **
2688 ** Functions for destruction of AJAX SQL Row objects.
2689 **
2690 ** @fdata [AjPSqlrow]
2691 **
2692 ** @nam3rule Del Destroy (free) an existing AJAX SQL Row
2693 **
2694 ** @argrule Del Psqlr [AjPSqlrow*] AJAX SQL Row address
2695 **
2696 ** @valrule * [void]
2697 **
2698 ** @fcategory delete
2699 ******************************************************************************/
2700
2701
2702
2703
2704 /* @func ajSqlrowDel **********************************************************
2705 **
2706 ** Default AJAX SQL Row destructor.
2707 **
2708 ** @param [d] Psqlr [AjPSqlrow*] AJAX SQL Row address
2709 **
2710 ** @return [void]
2711 **
2712 ** @release 6.2.0
2713 ** @@
2714 ******************************************************************************/
2715
ajSqlrowDel(AjPSqlrow * Psqlr)2716 void ajSqlrowDel(AjPSqlrow *Psqlr)
2717 {
2718 AjPSqlrow pthis = NULL;
2719
2720 if(!Psqlr)
2721 return;
2722
2723 if(!*Psqlr)
2724 return;
2725
2726 pthis = *Psqlr;
2727
2728 ajVoidDel(&pthis->Values);
2729
2730 ajLongDel(&pthis->Lengths);
2731
2732 AJFREE(pthis);
2733
2734 *Psqlr = NULL;
2735
2736 return;
2737 }
2738
2739
2740
2741
2742 /* @section element retrieval *************************************************
2743 **
2744 ** Functions for returning elements of an AJAX SQL Row object.
2745 **
2746 ** @fdata [AjPSqlrow]
2747 ** @fnote None
2748 **
2749 ** @nam3rule Get Return SQL Row attribute(s)
2750 ** @nam4rule Lengths Return the AJAX Long Array of column value lengths
2751 ** @nam4rule Columns Return the number of columns
2752 ** @nam4rule Current Return the number of the current column in iteration
2753 ** @nam4rule Values Return the AJAX Void Pointer Array of column values
2754 **
2755 ** @argrule * sqlr [const AjPSqlrow] SQL Row
2756 **
2757 ** @valrule Columns [ajuint] Number of columns
2758 ** @valrule Current [ajuint] Current column
2759 ** @valrule Lengths [AjPLong] Column value lengths
2760 ** @valrule Values [AjPVoid] Column values
2761 **
2762 ** @fcategory use
2763 ******************************************************************************/
2764
2765
2766
2767
2768 /* @func ajSqlrowGetColumns ***************************************************
2769 **
2770 ** Get the number of columns in an AJAX SQL Row.
2771 **
2772 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
2773 **
2774 ** @return [ajuint] Number of columns in an AJAX SQL Row
2775 **
2776 ** @release 6.2.0
2777 ** @@
2778 ******************************************************************************/
2779
ajSqlrowGetColumns(const AjPSqlrow sqlr)2780 ajuint ajSqlrowGetColumns(const AjPSqlrow sqlr)
2781 {
2782 if(!sqlr)
2783 return 0;
2784
2785 return sqlr->Columns;
2786 }
2787
2788
2789
2790
2791 /* @func ajSqlrowGetCurrent ***************************************************
2792 **
2793 ** Get the number of the current column in column iterations of an
2794 ** AJAX SQL Row.
2795 **
2796 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
2797 **
2798 ** @return [ajuint] Number of current column of an AJAX SQL Row
2799 **
2800 ** @release 6.2.0
2801 ** @@
2802 ******************************************************************************/
2803
ajSqlrowGetCurrent(const AjPSqlrow sqlr)2804 ajuint ajSqlrowGetCurrent(const AjPSqlrow sqlr)
2805 {
2806 if(!sqlr)
2807 return 0;
2808
2809 return sqlr->Current;
2810 }
2811
2812
2813
2814
2815 /* @func ajSqlrowGetLengths ***************************************************
2816 **
2817 ** Get the AJAX Long Integer Array of column value lengths in an AJAX SQL Row.
2818 **
2819 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
2820 **
2821 ** @return [AjPLong] AJAX Long Integer Array
2822 **
2823 ** @release 6.2.0
2824 ** @@
2825 ******************************************************************************/
2826
ajSqlrowGetLengths(const AjPSqlrow sqlr)2827 AjPLong ajSqlrowGetLengths(const AjPSqlrow sqlr)
2828 {
2829 if(!sqlr)
2830 return NULL;
2831
2832 return sqlr->Lengths;
2833 }
2834
2835
2836
2837
2838 /* @func ajSqlrowGetValues ****************************************************
2839 **
2840 ** Get the AJAX Void Pointer Array of column values in an AJAX SQL Row.
2841 **
2842 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
2843 **
2844 ** @return [AjPVoid] AJAX Void Pointer Array
2845 **
2846 ** @release 6.2.0
2847 ** @@
2848 ******************************************************************************/
2849
ajSqlrowGetValues(const AjPSqlrow sqlr)2850 AjPVoid ajSqlrowGetValues(const AjPSqlrow sqlr)
2851 {
2852 if(!sqlr)
2853 return NULL;
2854
2855 return sqlr->Values;
2856 }
2857
2858
2859
2860
2861 /* @datasection [AjPSqlrow] AJAX SQL Column ***********************************
2862 **
2863 ** Functions for manipulating AJAX SQL Row Columns
2864 **
2865 ** @nam2rule Sqlcolumn Functions for manipulating AJAX SQL Row COlumns
2866 **
2867 ******************************************************************************/
2868
2869
2870
2871
2872 /* @section column modifiers **************************************************
2873 **
2874 ** @fdata [AjPSqlrow]
2875 **
2876 ** @nam3rule Rewind Rewind an AJAX SQL Column Iterator
2877 **
2878 ** @argrule Rewind sqlr [AjPSqlrow] AJAX SQL Row
2879 **
2880 ** @valrule * [AjBool] ajTrue upon success, ajFalse otherwise
2881 **
2882 ** @fcategory modify
2883 ******************************************************************************/
2884
2885
2886
2887
2888 /* @func ajSqlcolumnRewind ****************************************************
2889 **
2890 ** Rewind an AJAX SQL Column Iterator to the start position.
2891 **
2892 ** @param [u] sqlr [AjPSqlrow] AJAX SQL Row
2893 **
2894 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
2895 **
2896 ** @release 6.2.0
2897 ** @@
2898 ******************************************************************************/
2899
ajSqlcolumnRewind(AjPSqlrow sqlr)2900 AjBool ajSqlcolumnRewind(AjPSqlrow sqlr)
2901 {
2902 if(!sqlr)
2903 return ajFalse;
2904
2905 sqlr->Current = 0;
2906
2907 return ajTrue;
2908 }
2909
2910
2911
2912
2913 /* @section column retrieval **************************************************
2914 **
2915 ** @fdata [AjPSqlrow]
2916 **
2917 ** @nam3rule Get column element
2918 ** @nam4rule Value Get the value of the next column
2919 **
2920 ** @argrule Get sqlr [AjPSqlrow] AJAX SQL Row
2921 ** @argrule Value Pvalue [void**] Value address
2922 ** @argrule Value Plength [ajulong*] Value length address
2923 **
2924 ** @valrule * [AjBool] ajTrue upon success, ajFalse otherwise
2925 **
2926 ** @fcategory use
2927 ******************************************************************************/
2928
2929
2930
2931
2932 /* @func ajSqlcolumnGetValue **************************************************
2933 **
2934 ** Get the value of the next column of an AJAX SQL Row.
2935 ** Calling this function also advances the column iterator.
2936 **
2937 ** @param [u] sqlr [AjPSqlrow] AJAX SQL Row
2938 ** @param [u] Pvalue [void**] Value address
2939 ** @param [u] Plength [ajulong*] Value length address
2940 **
2941 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
2942 **
2943 ** @release 6.2.0
2944 ** @@
2945 ******************************************************************************/
2946
ajSqlcolumnGetValue(AjPSqlrow sqlr,void ** Pvalue,ajulong * Plength)2947 AjBool ajSqlcolumnGetValue(AjPSqlrow sqlr,
2948 void **Pvalue, ajulong *Plength)
2949 {
2950 if(!sqlr)
2951 return ajFalse;
2952
2953 if(!Pvalue)
2954 return ajFalse;
2955
2956 if(!Plength)
2957 return ajFalse;
2958
2959 if(sqlr->Current >= sqlr->Columns)
2960 return ajFalse;
2961
2962 *Pvalue = ajVoidGet(sqlr->Values, sqlr->Current);
2963
2964 *Plength = ajLongGet(sqlr->Lengths, sqlr->Current);
2965
2966 sqlr->Current++;
2967
2968 return ajTrue;
2969 }
2970
2971
2972
2973
2974 /* @section column to datatype conversion functions ***************************
2975 **
2976 ** Functions for converting SQL Column values to other datatypes.
2977 **
2978 ** @fdata [AjPSqlrow]
2979 ** @fnote None
2980 **
2981 ** @nam3rule To Convert to another type
2982 ** @nam4rule ToBool Convert to AJAX Boolean
2983 ** @nam4rule ToDouble Convert to C-type double
2984 ** @nam4rule ToFloat Convert to C-type float
2985 ** @nam4rule ToInt Convert to AJAX Signed Integer
2986 ** @nam4rule ToLong Convert to AJAX Signed Long Integer
2987 ** @nam4rule ToStr Convert to AJAX String
2988 ** @nam4rule ToTime Conver to AJAX Time
2989 ** @nam4rule ToUint Convert ot AJAX Unsigned Integer
2990 ** @nam4rule ToUlong Convert to AJAX Unsigned Long Integer
2991 **
2992 ** @argrule * sqlr [AjPSqlrow] SQL Row
2993 ** @argrule ToBool Pvalue [AjBool*] AJAX Bool address
2994 ** @argrule ToDouble Pvalue [double*] C-type double address
2995 ** @argrule ToFloat Pvalue [float*] C-type float address
2996 ** @argrule ToInt Pvalue [ajint*] AJAX Signed Integer address
2997 ** @argrule ToLong Pvalue [ajlong*] AJAX Signed Long Integer address
2998 ** @argrule ToStr Pvalue [AjPStr*] AJAX String address
2999 ** @argrule ToTime Pvalue [AjPTime*] AJAX Time address
3000 ** @argrule ToUint Pvalue [ajuint*] AJAX Unsigned Integer address
3001 ** @argrule ToUlong Pvalue [ajulong*] AJAX Unsigned Long Integer address
3002 **
3003 ** @valrule * [AjBool] ajTrue upon success, ajFalse otherwise
3004 **
3005 ** @fcategory use
3006 ******************************************************************************/
3007
3008
3009
3010
3011 /* @func ajSqlcolumnToBool ****************************************************
3012 **
3013 ** Converts the value in the next column of an AJAX SQL Row into an
3014 ** AJAX Boolean value.
3015 **
3016 ** This function uses ajStrToBool to convert the AJAX String representing the
3017 ** column value into an AJAX boolean value. The function converts 'yes' and
3018 ** 'true', as well as 'no' and 'false' into its corresponding AJAX Bool values.
3019 ** It also assumes any numeric value as true and 0 as false.
3020 **
3021 ** @param [u] sqlr [AjPSqlrow] AJAX SQL Row
3022 ** @param [w] Pvalue [AjBool*] AJAX Boolean address
3023 ** @see ajStrToBool
3024 **
3025 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3026 **
3027 ** @release 6.2.0
3028 ** @@
3029 ******************************************************************************/
3030
ajSqlcolumnToBool(AjPSqlrow sqlr,AjBool * Pvalue)3031 AjBool ajSqlcolumnToBool(AjPSqlrow sqlr, AjBool *Pvalue)
3032 {
3033 AjBool bool = ajFalse;
3034
3035 AjPStr str = NULL;
3036
3037 if(!sqlr)
3038 return ajFalse;
3039
3040 if(!Pvalue)
3041 return ajFalse;
3042
3043 if(sqlr->Current >= sqlr->Columns)
3044 return ajFalse;
3045
3046 str = ajStrNew();
3047
3048 bool = ajSqlcolumnToStr(sqlr, &str);
3049
3050 if(bool)
3051 ajStrToBool(str, Pvalue);
3052
3053 ajStrDel(&str);
3054
3055 return bool;
3056 }
3057
3058
3059
3060
3061 /* @func ajSqlcolumnToDouble **************************************************
3062 **
3063 ** Converts the value in the next column of an AJAX SQL Row into a
3064 ** C-type double value.
3065 **
3066 ** @param [u] sqlr [AjPSqlrow] AJAX SQL Row
3067 ** @param [w] Pvalue [double*] C-type double address
3068 **
3069 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3070 **
3071 ** @release 6.2.0
3072 ** @@
3073 ******************************************************************************/
3074
ajSqlcolumnToDouble(AjPSqlrow sqlr,double * Pvalue)3075 AjBool ajSqlcolumnToDouble(AjPSqlrow sqlr, double *Pvalue)
3076 {
3077 AjBool bool = ajFalse;
3078
3079 AjPStr str = NULL;
3080
3081 if(!sqlr)
3082 return ajFalse;
3083
3084 if(!Pvalue)
3085 return ajFalse;
3086
3087 if(sqlr->Current >= sqlr->Columns)
3088 return ajFalse;
3089
3090 str = ajStrNew();
3091
3092 bool = ajSqlcolumnToStr(sqlr, &str);
3093
3094 if(bool)
3095 ajStrToDouble(str, Pvalue);
3096
3097 ajStrDel(&str);
3098
3099 return bool;
3100 }
3101
3102
3103
3104
3105 /* @func ajSqlcolumnToFloat ***************************************************
3106 **
3107 ** Converts the value in the next column of an AJAX SQL Row into a
3108 ** C-type float value.
3109 **
3110 ** @param [u] sqlr [AjPSqlrow] AJAX SQL Row
3111 ** @param [w] Pvalue [float*] C-type float address
3112 **
3113 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3114 **
3115 ** @release 6.2.0
3116 ** @@
3117 ******************************************************************************/
3118
ajSqlcolumnToFloat(AjPSqlrow sqlr,float * Pvalue)3119 AjBool ajSqlcolumnToFloat(AjPSqlrow sqlr, float *Pvalue)
3120 {
3121 AjBool bool = ajFalse;
3122
3123 AjPStr str = NULL;
3124
3125 if(!sqlr)
3126 return ajFalse;
3127
3128 if(!Pvalue)
3129 return ajFalse;
3130
3131 if(sqlr->Current >= sqlr->Columns)
3132 return ajFalse;
3133
3134 str = ajStrNew();
3135
3136 bool = ajSqlcolumnToStr(sqlr, &str);
3137
3138 if(bool)
3139 ajStrToFloat(str, Pvalue);
3140
3141 ajStrDel(&str);
3142
3143 return bool;
3144 }
3145
3146
3147
3148
3149 /* @func ajSqlcolumnToInt *****************************************************
3150 **
3151 ** Converts the value in the next column of an AJAX SQL Row into an
3152 ** AJAX Integer value.
3153 **
3154 ** @param [u] sqlr [AjPSqlrow] AJAX SQL Row
3155 ** @param [w] Pvalue [ajint*] AJAX Integer address
3156 **
3157 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3158 **
3159 ** @release 6.2.0
3160 ** @@
3161 ******************************************************************************/
3162
ajSqlcolumnToInt(AjPSqlrow sqlr,ajint * Pvalue)3163 AjBool ajSqlcolumnToInt(AjPSqlrow sqlr, ajint *Pvalue)
3164 {
3165 AjBool bool = ajFalse;
3166
3167 AjPStr str = NULL;
3168
3169 if(!sqlr)
3170 return ajFalse;
3171
3172 if(!Pvalue)
3173 return ajFalse;
3174
3175 if(sqlr->Current >= sqlr->Columns)
3176 return ajFalse;
3177
3178 str = ajStrNew();
3179
3180 bool = ajSqlcolumnToStr(sqlr, &str);
3181
3182 if(bool)
3183 ajStrToInt(str, Pvalue);
3184
3185 ajStrDel(&str);
3186
3187 return bool;
3188 }
3189
3190
3191
3192
3193 /* @func ajSqlcolumnToLong ****************************************************
3194 **
3195 ** Converts the value in the next column of an AJAX SQL Row into an
3196 ** AJAX Long Integer value.
3197 **
3198 ** @param [u] sqlr [AjPSqlrow] AJAX SQL Row
3199 ** @param [w] Pvalue [ajlong*] AJAX Long Integer address
3200 **
3201 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3202 **
3203 ** @release 6.2.0
3204 ** @@
3205 ******************************************************************************/
3206
ajSqlcolumnToLong(AjPSqlrow sqlr,ajlong * Pvalue)3207 AjBool ajSqlcolumnToLong(AjPSqlrow sqlr, ajlong *Pvalue)
3208 {
3209 AjBool bool = ajFalse;
3210
3211 AjPStr str = NULL;
3212
3213 if(!sqlr)
3214 return ajFalse;
3215
3216 if(!Pvalue)
3217 return ajFalse;
3218
3219 if(sqlr->Current >= sqlr->Columns)
3220 return ajFalse;
3221
3222 str = ajStrNew();
3223
3224 bool = ajSqlcolumnToStr(sqlr, &str);
3225
3226 if(bool)
3227 ajStrToLong(str, Pvalue);
3228
3229 ajStrDel(&str);
3230
3231 return bool;
3232 }
3233
3234
3235
3236
3237 /* @func ajSqlcolumnToStr *****************************************************
3238 **
3239 ** Converts the value of the next column of an AJAX SQL Row into an
3240 ** AJAX String value.
3241 **
3242 ** @param [u] sqlr [AjPSqlrow] AJAX SQL Row
3243 ** @param [w] Pvalue [AjPStr*] AJAX String address
3244 **
3245 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3246 **
3247 ** @release 6.2.0
3248 ** @@
3249 ******************************************************************************/
3250
ajSqlcolumnToStr(AjPSqlrow sqlr,AjPStr * Pvalue)3251 AjBool ajSqlcolumnToStr(AjPSqlrow sqlr, AjPStr *Pvalue)
3252 {
3253 void *value = NULL;
3254
3255 ajulong length = 0;
3256
3257 if(!sqlr)
3258 return ajFalse;
3259
3260 if(!Pvalue)
3261 return ajFalse;
3262
3263 if(sqlr->Current >= sqlr->Columns)
3264 return ajFalse;
3265
3266 ajStrAssignClear(Pvalue);
3267
3268 if(ajSqlcolumnGetValue(sqlr, &value, &length))
3269 {
3270 if(value == NULL)
3271 return ajFalse;
3272
3273 if(length > UINT_MAX)
3274 return ajFalse;
3275
3276 ajStrAssignLenC(Pvalue, (char *) value, (size_t) length);
3277
3278 return ajTrue;
3279 }
3280
3281 return ajFalse;
3282 }
3283
3284
3285
3286
3287 /* @func ajSqlcolumnToTime ****************************************************
3288 **
3289 ** Converts the value in the next column of an AJAX SQL Row into an
3290 ** AJAX Time value.
3291 **
3292 ** @param [u] sqlr [AjPSqlrow] AJAX SQL Row
3293 ** @param [w] Pvalue [AjPTime*] AJAX Time address
3294 **
3295 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3296 **
3297 ** @release 6.2.0
3298 ** @@
3299 ******************************************************************************/
3300
ajSqlcolumnToTime(AjPSqlrow sqlr,AjPTime * Pvalue)3301 AjBool ajSqlcolumnToTime(AjPSqlrow sqlr, AjPTime *Pvalue)
3302 {
3303 AjBool bool = ajFalse;
3304
3305 AjPStr str = NULL;
3306
3307 if(!sqlr)
3308 return ajFalse;
3309
3310 if(!Pvalue)
3311 return ajFalse;
3312
3313 if(!*Pvalue)
3314 return ajFalse;
3315
3316 if(sqlr->Current >= sqlr->Columns)
3317 return ajFalse;
3318
3319 str = ajStrNew();
3320
3321 bool = ajSqlcolumnToStr(sqlr, &str);
3322
3323 if(bool)
3324 ajTimeSetS(*Pvalue, str);
3325
3326 ajStrDel(&str);
3327
3328 return bool;
3329 }
3330
3331
3332
3333
3334 /* @func ajSqlcolumnToUint ****************************************************
3335 **
3336 ** Converts the value in the next column of an AJAX SQL Row into an
3337 ** AJAX Unsigned Integer value.
3338 **
3339 ** @param [u] sqlr [AjPSqlrow] AJAX SQL Row
3340 ** @param [w] Pvalue [ajuint*] AJAX Unsigned Integer address
3341 **
3342 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3343 **
3344 ** @release 6.2.0
3345 ** @@
3346 ******************************************************************************/
3347
ajSqlcolumnToUint(AjPSqlrow sqlr,ajuint * Pvalue)3348 AjBool ajSqlcolumnToUint(AjPSqlrow sqlr, ajuint *Pvalue)
3349 {
3350 AjBool bool = ajFalse;
3351
3352 AjPStr str = NULL;
3353
3354 if(!sqlr)
3355 return ajFalse;
3356
3357 if(!Pvalue)
3358 return ajFalse;
3359
3360 if(sqlr->Current >= sqlr->Columns)
3361 return ajFalse;
3362
3363 str = ajStrNew();
3364
3365 bool = ajSqlcolumnToStr(sqlr, &str);
3366
3367 if(bool)
3368 ajStrToUint(str, Pvalue);
3369
3370 ajStrDel(&str);
3371
3372 return bool;
3373 }
3374
3375
3376
3377
3378 /* @func ajSqlcolumnToUlong ***************************************************
3379 **
3380 ** Converts the value in the next column of an AJAX SQL Row into an
3381 ** AJAX Unsigned Long Integer value.
3382 **
3383 ** @param [u] sqlr [AjPSqlrow] AJAX SQL Row
3384 ** @param [w] Pvalue [ajulong*] AJAX Unsigned Long Integer address
3385 **
3386 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3387 **
3388 ** @release 6.3.0
3389 ** @@
3390 ******************************************************************************/
3391
ajSqlcolumnToUlong(AjPSqlrow sqlr,ajulong * Pvalue)3392 AjBool ajSqlcolumnToUlong(AjPSqlrow sqlr, ajulong *Pvalue)
3393 {
3394 AjBool bool = ajFalse;
3395
3396 AjPStr str = NULL;
3397
3398 if(!sqlr)
3399 return ajFalse;
3400
3401 if(!Pvalue)
3402 return ajFalse;
3403
3404 if(sqlr->Current >= sqlr->Columns)
3405 return ajFalse;
3406
3407 str = ajStrNew();
3408
3409 bool = ajSqlcolumnToStr(sqlr, &str);
3410
3411 if(bool)
3412 ajStrToUlong(str, Pvalue);
3413
3414 ajStrDel(&str);
3415
3416 return bool;
3417 }
3418
3419
3420
3421
3422 /* @section column retrieval **************************************************
3423 **
3424 ** @fdata [AjPSqlrow]
3425 **
3426 ** @nam3rule Number Select a particular column of an AJAX SQL Row.
3427 ** @nam4rule Get Get an element
3428 ** @nam5rule Value Get the value of a particular column
3429 **
3430 ** @argrule * sqlr [const AjPSqlrow] AJAX SQL Row
3431 ** @argrule * column [ajuint] Column number
3432 **
3433 ** @argrule GetValue Pvalue [void**] Value address
3434 ** @argrule GetValue Plength [ajulong*] Value length address
3435 **
3436 ** @valrule * [AjBool] True on success
3437 **
3438 ** @fcategory use
3439 ******************************************************************************/
3440
3441
3442
3443
3444 /* @func ajSqlcolumnNumberGetValue ********************************************
3445 **
3446 ** Get the value of a particular column of an AJAX SQL Row.
3447 **
3448 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
3449 ** @param [r] column [ajuint] Column number
3450 ** @param [u] Pvalue [void**] Value address
3451 ** @param [u] Plength [ajulong*] Value length address
3452 **
3453 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3454 **
3455 ** @release 6.2.0
3456 ** @@
3457 ******************************************************************************/
3458
ajSqlcolumnNumberGetValue(const AjPSqlrow sqlr,ajuint column,void ** Pvalue,ajulong * Plength)3459 AjBool ajSqlcolumnNumberGetValue(const AjPSqlrow sqlr,
3460 ajuint column,
3461 void **Pvalue,
3462 ajulong *Plength)
3463 {
3464 if(!sqlr)
3465 return ajFalse;
3466
3467 if(column >= sqlr->Columns)
3468 return ajFalse;
3469
3470 if(!Pvalue)
3471 return ajFalse;
3472
3473 if(!Plength)
3474 return ajFalse;
3475
3476 *Pvalue = ajVoidGet(sqlr->Values, column);
3477
3478 *Plength = ajLongGet(sqlr->Lengths, column);
3479
3480 return ajTrue;
3481 }
3482
3483
3484
3485
3486 /* @section column to datatype conversion functions ***************************
3487 **
3488 ** Functions for converting SQL Column values to other datatypes.
3489 **
3490 ** @fdata [AjPSqlrow]
3491 ** @fnote None
3492 **
3493 ** @nam3rule Number Convert a particular column to a differnt datatype
3494 ** @nam4rule To Convert to another type
3495 ** @nam5rule ToBool Convert to AJAX Boolean
3496 ** @nam5rule ToDouble Convert to C-type double
3497 ** @nam5rule ToFloat Convert to C-type float
3498 ** @nam5rule ToInt Convert to AJAX Signed Integer
3499 ** @nam5rule ToLong Convert to AJAX Signed Long Integer
3500 ** @nam5rule ToStr Convert to AJAX String
3501 ** @nam5rule ToTime Conver to AJAX Time
3502 ** @nam5rule ToUint Convert ot AJAX Unsigned Integer
3503 ** @nam5rule ToUlong Convert to AJAX Unsigned Long Integer
3504 **
3505 ** @argrule * sqlr [const AjPSqlrow] SQL Row
3506 ** @argrule * column [ajuint] Column number
3507 ** @argrule ToBool Pvalue [AjBool*] AJAX Bool address
3508 ** @argrule ToDouble Pvalue [double*] C-type double address
3509 ** @argrule ToFloat Pvalue [float*] C-type float address
3510 ** @argrule ToInt Pvalue [ajint*] AJAX Signed Integer address
3511 ** @argrule ToLong Pvalue [ajlong*] AJAX Signed Long Integer address
3512 ** @argrule ToTime Pvalue [AjPTime*] AJAX Time address
3513 ** @argrule ToStr Pvalue [AjPStr*] AJAX String address
3514 ** @argrule ToUint Pvalue [ajuint*] AJAX Unsigned Integer address
3515 ** @argrule ToUlong Pvalue [ajulong*] AJAX Unsigned Long Integer address
3516 **
3517 ** @valrule * [AjBool] ajTrue upon success, ajFalse otherwise
3518 **
3519 ** @fcategory use
3520 ******************************************************************************/
3521
3522
3523
3524
3525 /* @func ajSqlcolumnNumberToBool **********************************************
3526 **
3527 ** Converts the value in a particular column of an AJAX SQL Row into an
3528 ** AJAX Boolean value.
3529 **
3530 ** This function uses ajStrToBool to convert the AJAX String representing the
3531 ** column value into an AJAX boolean value. The function converts 'yes' and
3532 ** 'true', as well as 'no' and 'false' into its corresponding AJAX Bool values.
3533 ** It also assumes any numeric value as true and 0 as false.
3534 **
3535 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
3536 ** @param [r] column [ajuint] Column number
3537 ** @param [w] Pvalue [AjBool*] AJAX Boolean address
3538 ** @see ajStrToBool
3539 **
3540 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3541 **
3542 ** @release 6.2.0
3543 ** @@
3544 ******************************************************************************/
3545
ajSqlcolumnNumberToBool(const AjPSqlrow sqlr,ajuint column,AjBool * Pvalue)3546 AjBool ajSqlcolumnNumberToBool(const AjPSqlrow sqlr, ajuint column,
3547 AjBool *Pvalue)
3548 {
3549 AjBool bool = ajFalse;
3550
3551 AjPStr str = NULL;
3552
3553 if(!sqlr)
3554 return ajFalse;
3555
3556 if(!Pvalue)
3557 return ajFalse;
3558
3559 if(column >= sqlr->Columns)
3560 return ajFalse;
3561
3562 str = ajStrNew();
3563
3564 bool = ajSqlcolumnNumberToStr(sqlr, column, &str);
3565
3566 if(bool)
3567 ajStrToBool(str, Pvalue);
3568
3569 ajStrDel(&str);
3570
3571 return bool;
3572 }
3573
3574
3575
3576
3577 /* @func ajSqlcolumnNumberToDouble ********************************************
3578 **
3579 ** Converts the value in a particular column of an AJAX SQL Row into a
3580 ** C-type double value.
3581 **
3582 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
3583 ** @param [r] column [ajuint] Column number
3584 ** @param [w] Pvalue [double*] C-type double address
3585 **
3586 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3587 **
3588 ** @release 6.2.0
3589 ** @@
3590 ******************************************************************************/
3591
ajSqlcolumnNumberToDouble(const AjPSqlrow sqlr,ajuint column,double * Pvalue)3592 AjBool ajSqlcolumnNumberToDouble(const AjPSqlrow sqlr, ajuint column,
3593 double *Pvalue)
3594 {
3595 AjBool bool = ajFalse;
3596
3597 AjPStr str = NULL;
3598
3599 if(!sqlr)
3600 return ajFalse;
3601
3602 if(!Pvalue)
3603 return ajFalse;
3604
3605 if(column >= sqlr->Columns)
3606 return ajFalse;
3607
3608 str = ajStrNew();
3609
3610 bool = ajSqlcolumnNumberToStr(sqlr, column, &str);
3611
3612 if(bool)
3613 ajStrToDouble(str, Pvalue);
3614
3615 ajStrDel(&str);
3616
3617 return bool;
3618 }
3619
3620
3621
3622
3623 /* @func ajSqlcolumnNumberToFloat *********************************************
3624 **
3625 ** Converts the value in a particular column of an AJAX SQL Row into a
3626 ** C-type float value.
3627 **
3628 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
3629 ** @param [r] column [ajuint] Column number
3630 ** @param [w] Pvalue [float*] C-type float address
3631 **
3632 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3633 **
3634 ** @release 6.2.0
3635 ** @@
3636 ******************************************************************************/
3637
ajSqlcolumnNumberToFloat(const AjPSqlrow sqlr,ajuint column,float * Pvalue)3638 AjBool ajSqlcolumnNumberToFloat(const AjPSqlrow sqlr, ajuint column,
3639 float *Pvalue)
3640 {
3641 AjBool bool = ajFalse;
3642
3643 AjPStr str = NULL;
3644
3645 if(!sqlr)
3646 return ajFalse;
3647
3648 if(!Pvalue)
3649 return ajFalse;
3650
3651 if(column >= sqlr->Columns)
3652 return ajFalse;
3653
3654 str = ajStrNew();
3655
3656 bool = ajSqlcolumnNumberToStr(sqlr, column, &str);
3657
3658 if(bool)
3659 ajStrToFloat(str, Pvalue);
3660
3661 ajStrDel(&str);
3662
3663 return bool;
3664 }
3665
3666
3667
3668
3669 /* @func ajSqlcolumnNumberToInt ***********************************************
3670 **
3671 ** Converts the value in a particular column of an AJAX SQL Row into an
3672 ** AJAX Integer value.
3673 **
3674 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
3675 ** @param [r] column [ajuint] Column number
3676 ** @param [w] Pvalue [ajint*] AJAX Integer address
3677 **
3678 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3679 **
3680 ** @release 6.2.0
3681 ** @@
3682 ******************************************************************************/
3683
ajSqlcolumnNumberToInt(const AjPSqlrow sqlr,ajuint column,ajint * Pvalue)3684 AjBool ajSqlcolumnNumberToInt(const AjPSqlrow sqlr, ajuint column,
3685 ajint *Pvalue)
3686 {
3687 AjBool bool = ajFalse;
3688
3689 AjPStr str = NULL;
3690
3691 if(!sqlr)
3692 return ajFalse;
3693
3694 if(!Pvalue)
3695 return ajFalse;
3696
3697 if(column >= sqlr->Columns)
3698 return ajFalse;
3699
3700 str = ajStrNew();
3701
3702 bool = ajSqlcolumnNumberToStr(sqlr, column, &str);
3703
3704 if(bool)
3705 ajStrToInt(str, Pvalue);
3706
3707 ajStrDel(&str);
3708
3709 return bool;
3710 }
3711
3712
3713
3714
3715 /* @func ajSqlcolumnNumberToLong **********************************************
3716 **
3717 ** Converts the value in a particular column of an AJAX SQL Row into an
3718 ** AJAX Long Integer value.
3719 **
3720 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
3721 ** @param [r] column [ajuint] Column number
3722 ** @param [w] Pvalue [ajlong*] AJAX Long Integer address
3723 **
3724 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3725 **
3726 ** @release 6.2.0
3727 ** @@
3728 ******************************************************************************/
3729
ajSqlcolumnNumberToLong(const AjPSqlrow sqlr,ajuint column,ajlong * Pvalue)3730 AjBool ajSqlcolumnNumberToLong(const AjPSqlrow sqlr, ajuint column,
3731 ajlong *Pvalue)
3732 {
3733 AjBool bool = ajFalse;
3734
3735 AjPStr str = NULL;
3736
3737 if(!sqlr)
3738 return ajFalse;
3739
3740 if(!Pvalue)
3741 return ajFalse;
3742
3743 if(column >= sqlr->Columns)
3744 return ajFalse;
3745
3746 str = ajStrNew();
3747
3748 bool = ajSqlcolumnNumberToStr(sqlr, column, &str);
3749
3750 if(bool)
3751 ajStrToLong(str, Pvalue);
3752
3753 ajStrDel(&str);
3754
3755 return bool;
3756 }
3757
3758
3759
3760
3761 /* @func ajSqlcolumnNumberToStr ***********************************************
3762 **
3763 ** Converts the value in a particular column of an AJAX SQL Row into an
3764 ** AJAX String value.
3765 **
3766 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
3767 ** @param [r] column [ajuint] Column number
3768 ** @param [w] Pvalue [AjPStr*] AJAX String address
3769 **
3770 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3771 **
3772 ** @release 6.2.0
3773 ** @@
3774 ******************************************************************************/
3775
ajSqlcolumnNumberToStr(const AjPSqlrow sqlr,ajuint column,AjPStr * Pvalue)3776 AjBool ajSqlcolumnNumberToStr(const AjPSqlrow sqlr, ajuint column,
3777 AjPStr *Pvalue)
3778 {
3779 void *value = NULL;
3780
3781 ajulong length = 0;
3782
3783 if(!sqlr)
3784 return ajFalse;
3785
3786 if(!Pvalue)
3787 return ajFalse;
3788
3789 if(column >= sqlr->Columns)
3790 return ajFalse;
3791
3792 ajStrAssignClear(Pvalue);
3793
3794 if(ajSqlcolumnNumberGetValue(sqlr, column, &value, &length))
3795 {
3796 if(value == NULL)
3797 return ajFalse;
3798
3799 if(length > UINT_MAX)
3800 return ajFalse;
3801
3802 ajStrAssignLenC(Pvalue, (char *) value, (size_t) length);
3803
3804 return ajTrue;
3805 }
3806
3807 return ajFalse;
3808 }
3809
3810
3811
3812
3813 /* @func ajSqlcolumnNumberToTime **********************************************
3814 **
3815 ** Converts the value in a particular column of an AJAX SQL Row into an
3816 ** AJAX Time value.
3817 **
3818 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
3819 ** @param [r] column [ajuint] Column number
3820 ** @param [w] Pvalue [AjPTime*] AJAX Time address
3821 **
3822 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3823 **
3824 ** @release 6.2.0
3825 ** @@
3826 ******************************************************************************/
3827
ajSqlcolumnNumberToTime(const AjPSqlrow sqlr,ajuint column,AjPTime * Pvalue)3828 AjBool ajSqlcolumnNumberToTime(const AjPSqlrow sqlr, ajuint column,
3829 AjPTime *Pvalue)
3830 {
3831 AjBool bool = ajFalse;
3832
3833 AjPStr str = NULL;
3834
3835 if(!sqlr)
3836 return ajFalse;
3837
3838 if(!Pvalue)
3839 return ajFalse;
3840
3841 if(!*Pvalue)
3842 return ajFalse;
3843
3844 if(column >= sqlr->Columns)
3845 return ajFalse;
3846
3847 str = ajStrNew();
3848
3849 bool = ajSqlcolumnNumberToStr(sqlr, column, &str);
3850
3851 if(bool)
3852 ajTimeSetS(*Pvalue, str);
3853
3854 ajStrDel(&str);
3855
3856 return bool;
3857 }
3858
3859
3860
3861
3862 /* @func ajSqlcolumnNumberToUint **********************************************
3863 **
3864 ** Converts the value in a particular column of an AJAX SQL Row into an
3865 ** AJAX Unsigned Integer value.
3866 **
3867 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
3868 ** @param [r] column [ajuint] Column number
3869 ** @param [w] Pvalue [ajuint*] AJAX Unsigned Integer address
3870 **
3871 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3872 **
3873 ** @release 6.2.0
3874 ** @@
3875 ******************************************************************************/
3876
ajSqlcolumnNumberToUint(const AjPSqlrow sqlr,ajuint column,ajuint * Pvalue)3877 AjBool ajSqlcolumnNumberToUint(const AjPSqlrow sqlr, ajuint column,
3878 ajuint *Pvalue)
3879 {
3880 AjBool bool = ajFalse;
3881
3882 AjPStr str = NULL;
3883
3884 if(!sqlr)
3885 return ajFalse;
3886
3887 if(!Pvalue)
3888 return ajFalse;
3889
3890 if(column >= sqlr->Columns)
3891 return ajFalse;
3892
3893 str = ajStrNew();
3894
3895 bool = ajSqlcolumnNumberToStr(sqlr, column, &str);
3896
3897 if(bool)
3898 ajStrToUint(str, Pvalue);
3899
3900 ajStrDel(&str);
3901
3902 return bool;
3903 }
3904
3905
3906
3907
3908 /* @func ajSqlcolumnNumberToUlong *********************************************
3909 **
3910 ** Converts the value in a particular column of an AJAX SQL Row into an
3911 ** AJAX Unsigned Long Integer value.
3912 **
3913 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
3914 ** @param [r] column [ajuint] Column number
3915 ** @param [w] Pvalue [ajulong*] AJAX Unsigned Long Integer address
3916 **
3917 ** @return [AjBool] ajTrue upon success, ajFalse otherwise
3918 **
3919 ** @release 6.3.0
3920 ** @@
3921 ******************************************************************************/
3922
ajSqlcolumnNumberToUlong(const AjPSqlrow sqlr,ajuint column,ajulong * Pvalue)3923 AjBool ajSqlcolumnNumberToUlong(const AjPSqlrow sqlr, ajuint column,
3924 ajulong *Pvalue)
3925 {
3926 AjBool bool = ajFalse;
3927
3928 AjPStr str = NULL;
3929
3930 if(!sqlr)
3931 return ajFalse;
3932
3933 if(!Pvalue)
3934 return ajFalse;
3935
3936 if(column >= sqlr->Columns)
3937 return ajFalse;
3938
3939 str = ajStrNew();
3940
3941 bool = ajSqlcolumnNumberToStr(sqlr, column, &str);
3942
3943 if(bool)
3944 ajStrToUlong(str, Pvalue);
3945
3946 ajStrDel(&str);
3947
3948 return bool;
3949 }
3950
3951
3952
3953
3954 /* @section tests *************************************************************
3955 **
3956 ** @fdata [AjPSqlrow]
3957 **
3958 ** @nam3rule Number Column number
3959 ** @nam4rule Is Property of culumn
3960 ** @nam5rule IsDefined Test if the value in a particular column of
3961 ** an AJAX SQL Row is defined.
3962 **
3963 ** @argrule IsDefined sqlr [const AjPSqlrow] AJAX SQL Row
3964 ** @argrule IsDefined column [ajuint] Column number
3965 **
3966 ** @valrule IsDefined [AjBool] Result of test
3967 **
3968 ** @fcategory use
3969 ******************************************************************************/
3970
3971
3972
3973
3974 /* @func ajSqlcolumnNumberIsDefined *******************************************
3975 **
3976 ** Test if the value in a particular column of an AJAX SQL Row is defined.
3977 **
3978 ** @param [r] sqlr [const AjPSqlrow] AJAX SQL Row
3979 ** @param [r] column [ajuint] Column number
3980 **
3981 ** @return [AjBool] ajTrue if the value is defined,
3982 ** ajFalse if the value is undefined (\N)
3983 **
3984 ** @release 6.2.0
3985 ** @@
3986 ******************************************************************************/
3987
ajSqlcolumnNumberIsDefined(const AjPSqlrow sqlr,ajuint column)3988 AjBool ajSqlcolumnNumberIsDefined(const AjPSqlrow sqlr, ajuint column)
3989 {
3990 if(!sqlr)
3991 return ajFalse;
3992
3993 if(column >= sqlr->Columns)
3994 return ajFalse;
3995
3996 if(ajVoidGet(sqlr->Values, column) == NULL)
3997 return ajFalse;
3998
3999 return ajTrue;
4000 }
4001
4002
4003
4004
4005 /*
4006 ** FIXME: Move the AJAX Void Pointer Array into ajarr.c.
4007 **
4008 ** FIXME: Should we rename this to AjPArrayVoid? All the other arrays should be
4009 ** renamed as well? AjPLong should be an alias for ajlong *, while
4010 ** AjPArrayLong would be the AJAX Array holding AJAX Long Integer values??
4011 */
4012
4013 #define RESERVED_SIZE 32
4014
4015
4016
4017
4018 /* @datasection [AjPVoid] Void pointer *****************************************
4019 **
4020 ** Functions for void pointer arrays
4021 **
4022 ** @nam2rule Void Void pointer array function
4023 **
4024 ******************************************************************************/
4025
4026
4027
4028
4029 /* @section constructors ******************************************************
4030 **
4031 ** @fdata [AjPVoid]
4032 ** @fcategory new
4033 **
4034 ** @nam3rule New Constructor
4035 ** @nam4rule Res length specified
4036 **
4037 ** @argrule Res size [ajuint] Size of array
4038 **
4039 ** @valrule * [AjPVoid] void pointer array
4040 **
4041 ******************************************************************************/
4042
4043
4044
4045
4046 /* @func ajVoidNew ************************************************************
4047 **
4048 ** Default constructor for empty AJAX Void Pointer Arrays.
4049 **
4050 ** @return [AjPVoid] Pointer to an empty Pointer Array structure
4051 ** @category new [AjPVoid] Default constructor
4052 **
4053 ** @release 6.2.0
4054 ** @@
4055 ******************************************************************************/
4056
ajVoidNew(void)4057 AjPVoid ajVoidNew(void)
4058 {
4059 AjPVoid thys = NULL;
4060
4061 AJNEW0(thys);
4062
4063 thys->Ptr = AJALLOC0(RESERVED_SIZE * sizeof(void *));
4064 thys->Len = 0;
4065 thys->Res = RESERVED_SIZE;
4066
4067 /*
4068 ** FIXME: This works only in ajarr.c
4069 arrTotal++;
4070 arrAlloc += RESERVED_SIZE * sizeof(void *);
4071 */
4072
4073 return thys;
4074 }
4075
4076
4077
4078
4079 /* @func ajVoidNewRes *********************************************************
4080 **
4081 ** Constructor given an initial reserved size.
4082 **
4083 ** @param [r] size [ajuint] Reserved size
4084 ** @return [AjPVoid] Pointer to an empty Pointer Array struct
4085 ** of specified size
4086 ** @category new [AjPVoid] Constructor with reserved size
4087 **
4088 ** @release 6.2.0
4089 ** @@
4090 ******************************************************************************/
4091
ajVoidNewRes(ajuint size)4092 AjPVoid ajVoidNewRes(ajuint size)
4093 {
4094 AjPVoid thys = NULL;
4095
4096 size = ajRound(size, RESERVED_SIZE);
4097
4098 AJNEW0(thys);
4099
4100 thys->Ptr = AJALLOC0(size * sizeof(void *));
4101 thys->Len = 0;
4102 thys->Res = size;
4103
4104 /*
4105 ** FIXME: This works only in ajarr.c
4106 arrTotal++;
4107 arrAlloc += size * sizeof(void *);
4108 */
4109
4110 return thys;
4111 }
4112
4113
4114
4115
4116 /* @section destructors *******************************************************
4117 **
4118 ** Functions for destruction of void pointer arrays.
4119 **
4120 ** @fdata [AjPVoid]
4121 **
4122 ** @nam3rule Del Destroy (free) an existing AjPVoid
4123 **
4124 ** @argrule Del thys [AjPVoid*] Void pointer array
4125 **
4126 ** @valrule * [void]
4127 **
4128 ** @fcategory delete
4129 ******************************************************************************/
4130
4131
4132
4133
4134 /* @func ajVoidDel ************************************************************
4135 **
4136 ** Default destructor for AJAX Pointer arrays.
4137 **
4138 ** If the given array is a NULL pointer, simply returns.
4139 **
4140 ** @param [d] thys [AjPVoid*] Pointer to the Pointer Array to be deleted.
4141 ** The pointer is always deleted.
4142 ** @return [void]
4143 ** @category delete [AjPVoid] Default destructor
4144 **
4145 ** @release 6.2.0
4146 ** @@
4147 ******************************************************************************/
4148
ajVoidDel(AjPVoid * thys)4149 void ajVoidDel(AjPVoid *thys)
4150 {
4151 if(!thys || !*thys)
4152 return;
4153
4154 /*ajDebug("ajVoidDel Len %u Res %u\n",
4155 (*thys)->Len, (*thys)->Res);*/
4156
4157 AJFREE((*thys)->Ptr);
4158 AJFREE(*thys);
4159
4160 *thys = NULL;
4161
4162 /*
4163 ** FIXME: This works only in ajarr.c
4164 arrFreeCount++;
4165 */
4166
4167 return;
4168 }
4169
4170
4171
4172
4173 /* @section Cast **************************************************************
4174 **
4175 ** Functions for returning elements of an AJAX SQL Connection object.
4176 **
4177 ** @fdata [AjPVoid]
4178 **
4179 ** @nam3rule Get Return AJAX SQL Connection elements
4180 ** @nam3rule Len Return the length
4181 **
4182 ** @argrule * thys [const AjPVoid] AJAX void pointer array
4183 ** @argrule Get elem [ajuint] Element number
4184 **
4185 ** @valrule Get [void*] Void array
4186 ** @valrule Len [ajuint] Length
4187 **
4188 ** @fcategory cast
4189 ******************************************************************************/
4190
4191
4192
4193
4194 /* @func ajVoidGet ************************************************************
4195 **
4196 ** Retrieve an element from an AJAX Pointer Array.
4197 **
4198 ** If the given array is a NULL pointer, simply returns.
4199 **
4200 ** @param [r] thys [const AjPVoid] Pointer to the Pointer array
4201 ** @param [r] elem [ajuint] array element
4202 **
4203 ** @return [void*] contents of array element
4204 ** @category cast [AjPVoid] Retrieve an address from an array
4205 **
4206 ** @release 6.2.0
4207 ** @@
4208 ******************************************************************************/
4209
ajVoidGet(const AjPVoid thys,ajuint elem)4210 void* ajVoidGet(const AjPVoid thys, ajuint elem)
4211 {
4212 if(!thys || elem >= thys->Len)
4213 ajErr("Attempt to access bad Pointer array index %d\n", elem);
4214
4215 return thys->Ptr[elem];
4216 }
4217
4218
4219
4220
4221 /* @func ajVoidLen ************************************************************
4222 **
4223 ** Get length of dynamic 1d AJAX Pointer Array.
4224 **
4225 ** @param [r] thys [const AjPVoid] AJAX Pointer Array
4226 ** @return [ajuint] length
4227 **
4228 ** @release 6.4.0
4229 ** @@
4230 ******************************************************************************/
4231
ajVoidLen(const AjPVoid thys)4232 ajuint ajVoidLen(const AjPVoid thys)
4233 {
4234 return thys->Len;
4235 }
4236
4237
4238
4239
4240 /* @section modifiers *********************************************************
4241 **
4242 ** @fdata [AjPVoid]
4243 **
4244 ** @nam3rule Put Put a value in an array
4245 ** @nam3rule Resize Resize array
4246 **
4247 ** @argrule * thys [AjPVoid*] Void pointer array
4248 ** @argrule Resize size [ajuint] New size of array
4249 ** @argrule Put elem [ajuint] Element number
4250 ** @argrule Put v [void*] Value to load
4251 **
4252 ** @valrule * [AjBool] True on success
4253 **
4254 ** @fcategory modify
4255 ******************************************************************************/
4256
4257
4258
4259
4260 /* @func ajVoidPut ************************************************************
4261 **
4262 ** Load a void pointer array element.
4263 **
4264 ** If the given array is a NULL pointer an error is generated.
4265 ** If the array is of insufficient size then the array is extended.
4266 ** Negative indices generate an error.
4267 **
4268 ** @param [w] thys [AjPVoid*] Pointer to the void pointer array
4269 ** @param [r] elem [ajuint] array element
4270 ** @param [r] v [void*] value to load
4271 **
4272 ** @return [AjBool] true if the array was extended
4273 ** @category modify [AjPChar] Load a character array element
4274 **
4275 ** @release 6.2.0
4276 ** @@
4277 ******************************************************************************/
4278
ajVoidPut(AjPVoid * thys,ajuint elem,void * v)4279 AjBool ajVoidPut(AjPVoid *thys, ajuint elem, void *v)
4280 {
4281 if(!thys || !*thys)
4282 ajErr("Attempt to write to illegal array value %d\n", elem);
4283
4284 if(elem < (*thys)->Res)
4285 {
4286 if(elem >= (*thys)->Len)
4287 (*thys)->Len = elem + 1;
4288
4289 (*thys)->Ptr[elem] = v;
4290
4291 return ajFalse;
4292 }
4293
4294 arrVoidResize(thys, elem);
4295
4296 (*thys)->Ptr[elem] = v;
4297
4298 return ajTrue;
4299 }
4300
4301
4302
4303
4304
4305 /* @funcstatic arrVoidResize **************************************************
4306 **
4307 ** Resize a void pointer array.
4308 **
4309 ** If the given array is a NULL pointer an error is generated.
4310 ** Negative indices generate an error.
4311 **
4312 ** @param [w] thys [AjPVoid*] Pointer to the void pointer array
4313 ** @param [r] size [ajuint] new size
4314 **
4315 ** @return [AjBool] true if the array was extended
4316 **
4317 ** @release 6.2.0
4318 ** @@
4319 ******************************************************************************/
4320
arrVoidResize(AjPVoid * thys,ajuint size)4321 static AjBool arrVoidResize(AjPVoid *thys, ajuint size)
4322 {
4323 AjPVoid p = NULL;
4324 ajuint s;
4325 ajuint clen;
4326 ajuint limit;
4327
4328
4329 if(!thys || !*thys)
4330 ajErr("Illegal attempt to resize void pointer array");
4331
4332 clen = ajRound((*thys)->Len - 1, RESERVED_SIZE);
4333 s = ajRound(size + 1, RESERVED_SIZE);
4334 if(s <= clen)
4335 return ajFalse;
4336
4337 /*ajDebug("ajVoidResize %d (%d) -> %d (%d)\n",
4338 (*thys)->Len, clen, size, s);*/
4339
4340 p = *thys;
4341
4342 *thys = ajVoidNewRes(s);
4343
4344 if(size < p->Len)
4345 limit = size + 1;
4346 else
4347 limit = p->Len;
4348
4349 memmove((*thys)->Ptr, p->Ptr, limit * sizeof(void *));
4350
4351 (*thys)->Len = size + 1;
4352
4353 ajVoidDel(&p);
4354
4355 /*
4356 ** FIXME: This works only in ajarr.c
4357 arrResize++;
4358 */
4359
4360 return ajTrue;
4361 }
4362