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