source: trunk/tools/database/db.cpp@ 2818

Last change on this file since 2818 was 2818, checked in by bird, 26 years ago

Read more of the function header into the database.
Stateupd is changed to do this and the database is expanded with new fields.
The sample is partly updated.

File size: 60.7 KB
Line 
1/* $Id: db.cpp,v 1.11 2000-02-18 12:42:06 bird Exp $ *
2 *
3 * DB - contains all database routines.
4 *
5 * Copyright (c) 1999 knut st. osmundsen
6 *
7 */
8
9/*******************************************************************************
10* Defined Constants *
11*******************************************************************************/
12#define CheckLogContinue(sprintfargs) \
13 if (rc < 0) \
14 { \
15 if (pszError[1] == '\xFE') \
16 { \
17 strcat(pszError, "\n\t"); \
18 pszError += 2; \
19 } \
20 sprintf sprintfargs; \
21 ulRc++; \
22 pszError += strlen(pszError); \
23 pszError[1] = '\xFE'; \
24 } \
25 rc=rc
26
27
28#define CheckFKError(table, msg) \
29 pres2 = mysql_store_result(pmysql);\
30 if (rc < 0 || pres2 == NULL || \
31 mysql_num_rows(pres2) == 0) \
32 { \
33 if (pszError[1] == '\xFE') \
34 { \
35 strcat(pszError, "\n\t"); \
36 pszError += 2; \
37 } \
38 sprintf(pszError, table ":" \
39 msg \
40 " (refcode=%s) " \
41 "(sql=%s)", \
42 row1[0], \
43 pszQuery); \
44 ulRc++; \
45 pszError += strlen(pszError); \
46 pszError[1] = '\xFE'; \
47 } \
48 if (pres2 != NULL) \
49 mysql_free_result(pres2)
50
51
52/*******************************************************************************
53* Header Files *
54*******************************************************************************/
55#define INCL_DOSMISC
56#include <os2.h>
57#include <stdio.h>
58#include <stdlib.h>
59#include <string.h>
60#include <memory.h>
61#include <signal.h>
62#include <assert.h>
63#include <limits.h>
64#include <mysql.h>
65
66#include "db.h"
67
68
69/*@Global***********************************************************************
70* Global Variables *
71*******************************************************************************/
72static MYSQL mysql;
73static MYSQL *pmysql = NULL;
74
75
76/*@IntFunc**********************************************************************
77* Internal Functions *
78*******************************************************************************/
79static long getvalue(int iField, MYSQL_ROW pRow);
80static unsigned long CheckAuthorError(char * &pszError, const char *pszFieldName, const char *pszFieldValue, const char *pszQuery);
81static unsigned long logDbError(char * &pszError, const char *pszQuery);
82static char *sqlstrcat(char *pszQuery, const char *pszBefore, const char *pszStr, const char *pszAfter = NULL);
83
84#ifndef DLL
85 extern "C" void dbHandler(int sig);
86#endif
87
88
89/**
90 * Gets the descriptions of the last database error.
91 * @returns Readonly string.
92 */
93char * _System dbGetLastErrorDesc(void)
94{
95 return mysql_error(&mysql);
96}
97
98
99/**
100 * Connects to local database.
101 * @returns Success indicator, TRUE / FALSE.
102 * @param pszDatabase Name of database to use.
103 */
104BOOL _System dbConnect(const char *pszHost, const char *pszUser, const char *pszPassword, const char *pszDatabase)
105{
106 BOOL fRet = FALSE;
107 #ifndef DLL
108 static fHandler = FALSE;
109 /* signal handler */
110 if (!fHandler)
111 {
112 if ( SIG_ERR == signal(SIGBREAK, dbHandler)
113 || SIG_ERR == signal(SIGINT, dbHandler)
114 || SIG_ERR == signal(SIGTERM, dbHandler)
115 || SIG_ERR == signal(SIGABRT, dbHandler)
116 || SIG_ERR == signal(SIGSEGV, dbHandler)
117 || SIG_ERR == signal(SIGILL, dbHandler)
118 )
119 fprintf(stderr, "Error installing signalhandler...");
120 else
121 fHandler = TRUE;
122 }
123 #endif
124
125 /* connect to server */
126 memset(&mysql, 0, sizeof(mysql));
127 pmysql = mysql_connect(&mysql, pszHost, pszUser, pszPassword);
128 if (pmysql != NULL)
129 {
130 /* connect to database */
131 fRet = mysql_select_db(pmysql, pszDatabase) >= 0;
132 if (fRet)
133 mysql_refresh(pmysql, REFRESH_TABLES);
134 }
135
136 return fRet;
137}
138
139
140/**
141 * Disconnects from database.
142 * @returns Success indicator. TRUE / FALSE.
143 */
144BOOL _System dbDisconnect(void)
145{
146 if (pmysql != NULL)
147 {
148 mysql_refresh(pmysql, REFRESH_TABLES);
149 mysql_close(pmysql);
150 pmysql = NULL;
151 }
152 return TRUE;
153}
154
155/**
156 * Gets the refid for the give dll name.
157 * @returns Dll refid. -1 on error.
158 * @param pszDllName Dll name.
159 */
160signed short _System dbGetDll(const char *pszDllName)
161{
162 int rc;
163 char szQuery[256];
164 MYSQL_RES * pres;
165
166 sprintf(&szQuery[0], "SELECT refcode FROM dll WHERE name = '%s'\n", pszDllName);
167 rc = mysql_query(pmysql, &szQuery[0]);
168 pres = mysql_store_result(pmysql);
169
170 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) == 1)
171 rc = (int)getvalue(0, mysql_fetch_row(pres));
172 else
173 rc = -1;
174 mysql_free_result(pres);
175 return (short)rc;
176}
177
178
179/**
180 * Count the function in a given dll.
181 * @returns Number of functions. -1 on error.
182 * @param usDll Dll refcode.
183 * @param fNotAliases TRUE: don't count aliased functions.
184 */
185signed long _System dbCountFunctionInDll(signed long ulDll, BOOL fNotAliases)
186{
187 signed long rc;
188 char szQuery[256];
189 MYSQL_RES * pres;
190
191 if (ulDll >= 0)
192 {
193 sprintf(&szQuery[0], "SELECT count(refcode) FROM function WHERE dll = %ld\n", ulDll);
194 if (fNotAliases)
195 strcat(&szQuery[0], " AND aliasfn < 0");
196 rc = mysql_query(pmysql, &szQuery[0]);
197 pres = mysql_store_result(pmysql);
198
199 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) == 1)
200 rc = (int)getvalue(0, mysql_fetch_row(pres));
201 else
202 rc = -1;
203 mysql_free_result(pres);
204 }
205 else
206 rc = -1;
207 return rc;
208}
209
210
211
212/**
213 * Checks if dll exists. If not exists the dll is inserted.
214 * @returns Dll refcode. -1 on errors.
215 * @param pszDll Dll name.
216 * @remark This search must be case insensitive.
217 * (In the mysql-world everything is case insensitive!)
218 */
219signed short _System dbCheckInsertDll(const char *pszDll)
220{
221 int rc;
222 char szQuery[256];
223 MYSQL_RES * pres;
224
225 /* try find match */
226 sprintf(&szQuery[0], "SELECT refcode, name FROM dll WHERE name = '%s'\n", pszDll);
227 rc = mysql_query(pmysql, &szQuery[0]);
228 pres = mysql_store_result(pmysql);
229
230 /* not found? - insert dll */
231 if (rc < 0 || pres == NULL || mysql_num_rows(pres) == 0)
232 {
233 mysql_free_result(pres);
234
235 sprintf(&szQuery[0], "INSERT INTO dll(name) VALUES('%s')\n", pszDll);
236 rc = mysql_query(pmysql, &szQuery[0]);
237
238 /* select row to get refcode */
239 sprintf(&szQuery[0], "SELECT refcode, name FROM dll WHERE name = '%s'\n", pszDll);
240 rc = mysql_query(pmysql, &szQuery[0]);
241 pres = mysql_store_result(pmysql);
242 }
243
244 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) == 1)
245 rc = (int)getvalue(0, mysql_fetch_row(pres));
246 else
247 rc = -1;
248 mysql_free_result(pres);
249
250 return (short)rc;
251}
252
253
254/**
255 * Simple select for a long value.
256 * @returns long value
257 * @param pszTable From part.
258 * @param pszGetColumn Name of column to retreive.
259 * @param pszMatch1 Match column/expression
260 * @param pszMatchValue1 Match value.
261 * @remark Dirty! Don't use this!
262 */
263unsigned short _System dbGet(const char *pszTable, const char *pszGetColumn,
264 const char *pszMatch1, const char *pszMatchValue1)
265{
266 int rc;
267 char szQuery[256];
268 MYSQL_RES *pres;
269
270 /* try find match */
271 sprintf(&szQuery[0], "SELECT %s FROM %s WHERE %s = '%s'\n",
272 pszGetColumn, pszTable, pszMatch1, pszMatchValue1);
273 rc = mysql_query(pmysql, &szQuery[0]);
274 pres = mysql_store_result(pmysql);
275
276 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) == 1)
277 rc = (int)getvalue(0, mysql_fetch_row(pres));
278 else
279 rc = -1;
280 mysql_free_result(pres);
281
282 return (short)rc;
283}
284
285
286/**
287 * Updates or inserts a function name into the database.
288 * @returns Success indicator. TRUE / FALSE.
289 * @param usDll Dll refcode.
290 * @param pszFunction Function name.
291 * @param pszIntFunction Internal function name. (required!)
292 * @param ulOrdinal Ordinal value.
293 * @param fIgnoreOrdinal Do not update ordinal value.
294 */
295BOOL _System dbInsertUpdateFunction(unsigned short usDll,
296 const char *pszFunction, const char *pszIntFunction,
297 unsigned long ulOrdinal, BOOL fIgnoreOrdinal)
298{
299 int rc;
300 long lFunction = -1;
301 char szQuery[512];
302 MYSQL_RES *pres;
303
304 /* when no internal name fail! */
305 if (pszIntFunction == NULL || *pszIntFunction == '\0')
306 return FALSE;
307
308 /* try find function */
309 sprintf(&szQuery[0], "SELECT refcode, intname FROM function WHERE dll = %d AND name = '%s'", usDll, pszFunction);
310 rc = mysql_query(pmysql, &szQuery[0]);
311 pres = mysql_store_result(pmysql);
312 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) != 0)
313 { /* update function (function is found) */
314 MYSQL_ROW parow;
315 if (mysql_num_rows(pres) > 1)
316 {
317 fprintf(stderr, "internal database integrity error(%s): More function by the same name for the same dll. "
318 "usDll = %d, pszFunction = %s\n", __FUNCTION__, usDll, pszFunction);
319 return FALSE;
320 }
321
322 parow = mysql_fetch_row(pres);
323 if (parow != NULL)
324 lFunction = getvalue(0, parow);
325 mysql_free_result(pres);
326
327 if (strcmp(parow[1], pszIntFunction) != 0)
328 {
329 sprintf(&szQuery[0], "UPDATE function SET intname = '%s' WHERE refcode = %ld",
330 pszIntFunction, lFunction);
331 rc = mysql_query(pmysql, &szQuery[0]);
332 }
333
334 if (rc >= 0 && !fIgnoreOrdinal)
335 {
336 sprintf(&szQuery[0], "UPDATE function SET ordinal = %ld WHERE refcode = %ld",
337 ulOrdinal, lFunction);
338 rc = mysql_query(pmysql, &szQuery[0]);
339 }
340
341 }
342 else
343 { /* insert */
344 sprintf(&szQuery[0], "INSERT INTO function(dll, name, intname, ordinal) VALUES(%d, '%s', '%s', %ld)",
345 usDll, pszFunction, pszIntFunction, ulOrdinal);
346 rc = mysql_query(pmysql, &szQuery[0]);
347 }
348
349 return rc >= 0;
350}
351
352
353/**
354 * Get a long value.
355 * @returns Number value of pRow[iField]. -1 on error.
356 * @param iField Index into pRow.
357 * @param pRow Pointer to array (of string pointers).
358 */
359static long getvalue(int iField, MYSQL_ROW papszRow)
360{
361 if (papszRow[iField] != NULL)
362 return atol((char*)papszRow[iField]);
363
364 return -1;
365}
366
367
368#if 0
369/*
370 * Stubs used while optimizing sqls.
371 */
372int mysql_query1(MYSQL *mysql, const char *q)
373{ return mysql_query(mysql, q); }
374int mysql_query2(MYSQL *mysql, const char *q)
375{ return mysql_query(mysql, q); }
376int mysql_query3(MYSQL *mysql, const char *q)
377{ return mysql_query(mysql, q); }
378int mysql_query4(MYSQL *mysql, const char *q)
379{ return mysql_query(mysql, q); }
380int mysql_query5(MYSQL *mysql, const char *q)
381{ return mysql_query(mysql, q); }
382int mysql_query6(MYSQL *mysql, const char *q)
383{ return mysql_query(mysql, q); }
384
385#else
386
387#define mysql_query1 mysql_query
388#define mysql_query2 mysql_query
389#define mysql_query3 mysql_query
390#define mysql_query4 mysql_query
391#define mysql_query5 mysql_query
392#define mysql_query6 mysql_query
393
394#endif
395
396
397
398/**
399 * Find occurences of a function, given by internal name.
400 * @returns success indicator, TRUE / FALSE.
401 * @param pszFunctionName
402 * @param pFnFindBuf
403 * @param lDll
404 * @sketch 1) Get functions for this dll(if given).
405 * 2) Get functions which aliases the functions found in (1).
406 * 3) Get new aliases by intname
407 * 4) Get new aliases by name
408 * 5) Update all functions from (1) to have aliasfn -2 (DONTMIND)
409 * 6) Update all functions from (3) and (4) to alias the first function from 1.
410 */
411BOOL _System dbFindFunction(const char *pszFunctionName, PFNFINDBUF pFnFindBuf, signed long lDll)
412{
413 MYSQL_RES *pres;
414 MYSQL_ROW row;
415 int rc;
416 char szQuery[1024];
417
418 /*
419 * 1) Get functions for this dll(if given).
420 */
421 if (lDll < 0)
422 sprintf(&szQuery[0], "SELECT refcode, dll, aliasfn, name FROM function WHERE intname = '%s'",
423 pszFunctionName);
424 else
425 sprintf(&szQuery[0], "SELECT refcode, dll, aliasfn, name FROM function "
426 "WHERE intname = '%s' AND dll = %ld",
427 pszFunctionName, lDll);
428
429 rc = mysql_query1(pmysql, &szQuery[0]);
430 if (rc >= 0)
431 {
432 pres = mysql_store_result(pmysql);
433 if (pres != NULL)
434 {
435 char szFnName[NBR_FUNCTIONS][80];
436
437 pFnFindBuf->cFns = 0;
438 while ((row = mysql_fetch_row(pres)) != NULL)
439 {
440 pFnFindBuf->alRefCode[pFnFindBuf->cFns] = atol(row[0]);
441 pFnFindBuf->alDllRefCode[pFnFindBuf->cFns] = atol(row[1]);
442 pFnFindBuf->alAliasFn[pFnFindBuf->cFns] = atol(row[2]);
443 strcpy(szFnName[pFnFindBuf->cFns], row[3]);
444
445 /* next */
446 pFnFindBuf->cFns++;
447 }
448 mysql_free_result(pres);
449
450 /* alias check and fix */
451 if (lDll >= 0 && pFnFindBuf->cFns != 0)
452 {
453 int cFnsThisDll, cFnsAliasesAndThisDll, i, f;
454
455 /*
456 * 2) Get functions which aliases the functions found in (1).
457 */
458 cFnsThisDll = (int)pFnFindBuf->cFns;
459 strcpy(&szQuery[0], "SELECT refcode, dll, aliasfn, name FROM function WHERE aliasfn IN (");
460 for (i = 0; i < cFnsThisDll; i++)
461 {
462 if (i > 0) strcat(&szQuery[0], " OR ");
463 sprintf(&szQuery[strlen(szQuery)], "(%ld)", pFnFindBuf->alRefCode[i]);
464 }
465 strcat(&szQuery[0], ")");
466
467 rc = mysql_query2(pmysql, &szQuery[0]);
468 if (rc >= 0)
469 {
470 pres = mysql_store_result(pmysql);
471 if (pres != NULL)
472 {
473 while ((row = mysql_fetch_row(pres)) != NULL)
474 {
475 pFnFindBuf->alRefCode[pFnFindBuf->cFns] = atol(row[0]);
476 pFnFindBuf->alDllRefCode[pFnFindBuf->cFns] = atol(row[1]);
477 pFnFindBuf->alAliasFn[pFnFindBuf->cFns] = atol(row[2]);
478 strcpy(szFnName[pFnFindBuf->cFns], row[3]);
479
480 /* next */
481 pFnFindBuf->cFns++;
482 }
483 mysql_free_result(pres);
484
485 /*
486 * 3) Get new aliases by intname
487 */
488 cFnsAliasesAndThisDll = (int)pFnFindBuf->cFns;
489 sprintf(&szQuery[0], "SELECT refcode, dll, aliasfn FROM function "
490 "WHERE aliasfn = (-1) AND dll <> %ld AND (intname = '%s'",
491 lDll, pszFunctionName);
492 for (i = 0; i < cFnsAliasesAndThisDll; i++)
493 sprintf(&szQuery[strlen(&szQuery[0])], " OR intname = '%s'", szFnName[i]);
494 strcat(&szQuery[0], ")");
495
496 rc = mysql_query3(pmysql, &szQuery[0]);
497 if (rc >= 0)
498 {
499 pres = mysql_store_result(pmysql);
500 if (pres != NULL)
501 {
502 while ((row = mysql_fetch_row(pres)) != NULL)
503 {
504 pFnFindBuf->alRefCode[pFnFindBuf->cFns] = atol(row[0]);
505 pFnFindBuf->alDllRefCode[pFnFindBuf->cFns] = atol(row[1]);
506 if (row[2] != NULL)
507 pFnFindBuf->alAliasFn[pFnFindBuf->cFns] = atol(row[2]);
508 else
509 pFnFindBuf->alAliasFn[pFnFindBuf->cFns] = ALIAS_NULL;
510
511 /* next */
512 pFnFindBuf->cFns++;
513 }
514 mysql_free_result(pres);
515
516
517 /*
518 * 4) Get new aliases by name
519 */
520 sprintf(&szQuery[0], "SELECT refcode, dll, aliasfn FROM function "
521 "WHERE aliasfn = (-1) AND dll <> %ld AND (name = '%s'",
522 lDll, pszFunctionName);
523 for (i = 0; i < cFnsAliasesAndThisDll; i++)
524 sprintf(&szQuery[strlen(&szQuery[0])], " OR name = '%s'", szFnName[i]);
525 strcat(&szQuery[0], ")");
526
527 rc = mysql_query4(pmysql, &szQuery[0]);
528 if (rc >= 0)
529 {
530 pres = mysql_store_result(pmysql);
531 if (pres != NULL)
532 {
533 while ((row = mysql_fetch_row(pres)) != NULL)
534 {
535 pFnFindBuf->alRefCode[pFnFindBuf->cFns] = atol(row[0]);
536 pFnFindBuf->alDllRefCode[pFnFindBuf->cFns] = atol(row[1]);
537 if (row[2] != NULL)
538 pFnFindBuf->alAliasFn[pFnFindBuf->cFns] = atol(row[2]);
539 else
540 pFnFindBuf->alAliasFn[pFnFindBuf->cFns] = ALIAS_NULL;
541
542 /* next */
543 pFnFindBuf->cFns++;
544 }
545 mysql_free_result(pres);
546
547 /*
548 * 5) Update all functions from (1) to have aliasfn -2 (DONTMIND)
549 */
550 sprintf(&szQuery[0], "UPDATE function SET aliasfn = (-2) "
551 "WHERE refcode IN (",
552 lDll, pszFunctionName);
553 for (f = 0, i = 0; i < cFnsThisDll; i++)
554 if (pFnFindBuf->alAliasFn[i] != ALIAS_DONTMIND)
555 sprintf(&szQuery[strlen(&szQuery[0])],
556 f++ != 0 ? ", %ld" : "%ld", pFnFindBuf->alRefCode[i]);
557 strcat(&szQuery[0], ") AND aliasfn <> (-2)");
558 if (f > 0)
559 rc = mysql_query5(pmysql, &szQuery[0]);
560 else
561 rc = 0;
562 if (rc >= 0 && cFnsAliasesAndThisDll < pFnFindBuf->cFns)
563 {
564 /*
565 * 6) Update all functions from (3) and (4) to alias the first function from 1.
566 */
567 sprintf(&szQuery[0], "UPDATE function SET aliasfn = (%ld) "
568 "WHERE aliasfn = (-1) AND refcode IN (",
569 pFnFindBuf->alRefCode[0]);
570 for (i = cFnsAliasesAndThisDll; i < pFnFindBuf->cFns; i++)
571 {
572 sprintf(&szQuery[strlen(&szQuery[0])],
573 i > cFnsAliasesAndThisDll ? ", %ld" : "%ld", pFnFindBuf->alRefCode[i]);
574 }
575 strcat(&szQuery[0], ")");
576 rc = mysql_query6(pmysql, &szQuery[0]);
577 } /* query 5 */
578 }
579 } /* query 4 */
580 }
581 } /* query 3 */
582 }
583 } /* query 2 */
584 }
585 } /* query 1 */
586 else
587 rc = -1;
588 }
589
590 return rc >= 0;
591}
592
593
594/**
595 * Finds the refcode for an author, if the author exists.
596 * @returns Author 'refcode'.
597 * @param pszAuthor String which holds the identifier of an author.
598 * This doesn't have to be the name. Initials, alias and email
599 * is also searched.
600 * @param pszEmail Email address. Might be NULL!
601 */
602signed long _System dbFindAuthor(const char *pszAuthor, const char *pszEmail)
603{
604 signed long refcode = -1;
605 MYSQL_RES *pres;
606 char szQuery[512];
607
608 /*
609 * parameter validations
610 */
611 if (pszAuthor == NULL || strlen(pszAuthor) > 64)
612 return -1;
613 if (pszEmail != NULL && strlen(pszEmail) > 64)
614 {
615 fprintf(stderr, "email too long!");
616 return -1;
617 }
618
619 /*
620 * Query
621 */
622 sprintf(&szQuery[0],
623 "SELECT refcode FROM author "
624 "WHERE name = '%s' OR "
625 " initials = '%s' OR "
626 " alias = '%s' OR "
627 " email = '%s'",
628 pszAuthor, pszAuthor, pszAuthor, pszAuthor);
629
630 if (pszEmail != NULL)
631 sprintf(&szQuery[strlen(&szQuery[0])], " OR email = '%s'", pszEmail);
632
633 if (mysql_query(pmysql, &szQuery[0]) >= 0)
634 {
635 pres = mysql_store_result(pmysql);
636 if (pres != NULL)
637 {
638 MYSQL_ROW parow;
639
640 /* integrety check */
641 if (mysql_num_rows(pres) > 1)
642 fprintf(stderr, "Integrety: author '%s' is not unique!\n", pszAuthor);
643 parow = mysql_fetch_row(pres);
644 if (parow != NULL)
645 refcode = getvalue(0, parow);
646
647 mysql_free_result(pres);
648 }
649 }
650
651 return refcode;
652}
653
654
655/**
656 * Gets the state of a function.
657 * @returns state code. On error -1.
658 * @param lRefCode Function refcode.
659 */
660signed long _System dbGetFunctionState(signed long lRefCode)
661{
662 signed long lState = -1;
663 MYSQL_RES *pres;
664 char szQuery[128];
665
666 sprintf(&szQuery[0], "SELECT state FROM function WHERE refcode = %ld", lRefCode);
667 if (mysql_query(pmysql, &szQuery[0]) >= 0)
668 {
669 pres = mysql_store_result(pmysql);
670 if (pres != NULL)
671 {
672 MYSQL_ROW parow = mysql_fetch_row(pres);
673 if (parow != NULL)
674 lState = getvalue(0, parow);
675 mysql_free_result(pres);
676 }
677 }
678
679 return lState;
680}
681
682#if 1
683/*
684 * Stubs used while optimizing sqls.
685 */
686int mysql_queryu1(MYSQL *mysql, const char *q)
687{ return mysql_query(mysql, q); }
688int mysql_queryu2(MYSQL *mysql, const char *q)
689{ return mysql_query(mysql, q); }
690int mysql_queryu3(MYSQL *mysql, const char *q)
691{ return mysql_query(mysql, q); }
692int mysql_queryu4(MYSQL *mysql, const char *q)
693{ return mysql_query(mysql, q); }
694int mysql_queryu5(MYSQL *mysql, const char *q)
695{ return mysql_query(mysql, q); }
696int mysql_queryu6(MYSQL *mysql, const char *q)
697{ return mysql_query(mysql, q); }
698int mysql_queryu7(MYSQL *mysql, const char *q)
699{ return mysql_query(mysql, q); }
700int mysql_queryu8(MYSQL *mysql, const char *q)
701{ return mysql_query(mysql, q); }
702#else
703#define mysql_queryu1 mysql_query
704#define mysql_queryu2 mysql_query
705#define mysql_queryu3 mysql_query
706#define mysql_queryu4 mysql_query
707#define mysql_queryu5 mysql_query
708#define mysql_queryu6 mysql_query
709#define mysql_queryu7 mysql_query
710#define mysql_queryu8 mysql_query
711#endif
712
713/**
714 * Updates function information.
715 * @returns number of errors.
716 * @param pFnDesc Function description struct.
717 * @param lDll Dll which we are working at.
718 * @param pszError Buffer for error messages
719 * @result on error(s) pszError will hold information about the error(s).
720 */
721unsigned long _System dbUpdateFunction(PFNDESC pFnDesc, signed long lDll, char *pszError)
722{
723 MYSQL_RES * pres;
724 MYSQL_ROW row;
725 char * pszQuery2 = (char*)malloc(65500);
726 char * pszQuery = pszQuery2;
727 long lCurrentState;
728 int i,k,rc;
729 unsigned long ulRc = 0;
730
731 /* check if malloc have failed allocating memory for us. */
732 if (pszQuery2 == NULL)
733 {
734 strcpy(pszError, "internal dbUpdateFunction error - malloc failed!\n");
735 return 1;
736 }
737
738
739 /*
740 * Loop thru all functions in the array of refocodes.
741 */
742 for (k = 0; k < pFnDesc->cRefCodes; k++)
743 {
744 BOOL f = FALSE;
745
746 /*
747 * Set updated flag
748 */
749 sprintf(pszQuery, "UPDATE function SET updated = updated + 1 WHERE refcode = %ld",
750 pFnDesc->alRefCode[k]);
751 rc = mysql_queryu1(pmysql, pszQuery2);
752
753
754 /*
755 * Get current status
756 */
757 lCurrentState = dbGetFunctionState(pFnDesc->alRefCode[k]);
758 if (lCurrentState == -1 && dbGetLastErrorDesc() != NULL && strlen(dbGetLastErrorDesc()) != 0)
759 {
760 strcpy(pszError, dbGetLastErrorDesc());
761 free(pszQuery2);
762 return 1;
763 }
764
765
766 /*
767 * Update function table first
768 */
769 strcpy(pszQuery, "UPDATE function SET ");
770 pszQuery += strlen(pszQuery);
771
772 /* Status */
773 if (lCurrentState != pFnDesc->lStatus
774 && pFnDesc->lStatus != 0
775 && (lCurrentState == 0 || pFnDesc->lStatus != 99))
776 {
777 sprintf(pszQuery, "state = %ld", pFnDesc->lStatus);
778 f = TRUE;
779 }
780 pszQuery += strlen(pszQuery);
781
782 /* return type */
783 if (pFnDesc->pszReturnType != NULL)
784 {
785 if (f) strcat(pszQuery, ", ");
786 pszQuery = sqlstrcat(pszQuery, "return = ", pFnDesc->pszReturnType);
787 f = TRUE;
788 }
789
790 /* Description */
791 if (pFnDesc->pszDescription != NULL)
792 {
793 if (f) strcat(pszQuery, ", ");
794 pszQuery = sqlstrcat(pszQuery, "description = ", pFnDesc->pszDescription);
795 f = TRUE;
796 }
797
798 /* Remark */
799 if (pFnDesc->pszRemark != NULL)
800 {
801 if (f) strcat(pszQuery, ", ");
802 pszQuery = sqlstrcat(pszQuery, "remark = ", pFnDesc->pszRemark);
803 f = TRUE;
804 }
805
806 /* Description */
807 if (pFnDesc->pszReturnDesc != NULL)
808 {
809 if (f) strcat(pszQuery, ", ");
810 pszQuery = sqlstrcat(pszQuery, "returndesc = ", pFnDesc->pszReturnDesc);
811 f = TRUE;
812 }
813
814 /* Sketch */
815 if (pFnDesc->pszSketch != NULL)
816 {
817 if (f) strcat(pszQuery, ", ");
818 pszQuery = sqlstrcat(pszQuery, "sketch = ", pFnDesc->pszSketch);
819 f = TRUE;
820 }
821
822 /* Equiv */
823 if (pFnDesc->pszEquiv != NULL)
824 {
825 if (f) strcat(pszQuery, ", ");
826 pszQuery = sqlstrcat(pszQuery, "equiv = ", pFnDesc->pszEquiv);
827 f = TRUE;
828 }
829
830 /* Equiv */
831 if (pFnDesc->pszTime != NULL)
832 {
833 if (f) strcat(pszQuery, ", ");
834 pszQuery = sqlstrcat(pszQuery, "time = ", pFnDesc->pszTime);
835 f = TRUE;
836 }
837
838 /* Execute update query? */
839 if (f)
840 {
841 sprintf(pszQuery + strlen(pszQuery), " WHERE refcode = %ld", pFnDesc->alRefCode[k]);
842 rc = mysql_queryu2(pmysql, pszQuery2);
843 if (rc < 0)
844 {
845 sprintf(pszError, "Updating functiontable failed with error: %s - (sql=%s) ",
846 dbGetLastErrorDesc(), pszQuery2);
847 pszError += strlen(pszError) - 1;
848 ulRc++;
849 }
850 }
851
852
853
854 /*
855 * Parameters
856 */
857 pszQuery = pszQuery2;
858 sprintf(pszQuery, "SELECT count(*) FROM parameter WHERE function = %ld", pFnDesc->alRefCode[k]);
859 rc = mysql_queryu3(pmysql, pszQuery);
860 if (rc >= 0)
861 {
862 pres = mysql_store_result(pmysql);
863 if (pres != NULL)
864 row = mysql_fetch_row(pres);
865 if (pres != NULL && row != NULL && mysql_num_rows(pres) == 1)
866 {
867 if (atol(row[0]) == pFnDesc->cParams)
868 { /* update parameters */
869 for (i = 0; i < pFnDesc->cParams; i++)
870 {
871 sprintf(pszQuery, "UPDATE parameter SET type = '%s', name = '%s'",
872 pFnDesc->apszParamType[i] != NULL ? pFnDesc->apszParamType[i] : "",
873 pFnDesc->apszParamName[i] != NULL ? pFnDesc->apszParamName[i] : "");
874 if (pFnDesc->apszParamDesc[i] != NULL)
875 sqlstrcat(pszQuery, ", description = ", pFnDesc->apszParamDesc[i]);
876 sprintf(pszQuery + strlen(pszQuery), " WHERE function = (%ld) AND sequencenbr = (%ld)",
877 pFnDesc->alRefCode[k], i);
878 rc = mysql_queryu4(pmysql, pszQuery);
879 if (rc < 0)
880 {
881 if (*pszError == ' ')
882 strcpy(pszError++, "\n\t");
883 sprintf(pszError, "Updateing parameter %i failed with error: %s - (sql=%s) ",
884 i, dbGetLastErrorDesc(), pszQuery);
885 pszError += strlen(pszError) - 1;
886 ulRc++;
887 }
888 }
889 }
890 else
891 {
892 if (atol(row[0]) != 0)
893 { /* delete old parameters */
894 sprintf(pszQuery, "DELETE FROM parameter WHERE function = %ld", pFnDesc->alRefCode[k]);
895 rc = mysql_queryu5(pmysql, pszQuery);
896 if (rc < 0)
897 {
898 if (*pszError == ' ')
899 strcpy(pszError++, "\n\t");
900 sprintf(pszError, "Deleting old parameters failed with error: %s - (sql=%s) ",
901 dbGetLastErrorDesc(), pszQuery);
902 pszError += strlen(pszError) - 1;
903 ulRc++;
904 }
905 }
906
907 /* insert parameters */
908 for (i = 0; i < pFnDesc->cParams; i++)
909 {
910 sprintf(pszQuery, "INSERT INTO parameter(function, sequencenbr, type, name, description) "
911 "VALUES (%ld, %d, '%s', '%s'",
912 pFnDesc->alRefCode[k], i,
913 pFnDesc->apszParamType[i] != NULL ? pFnDesc->apszParamType[i] : "",
914 pFnDesc->apszParamName[i] != NULL ? pFnDesc->apszParamName[i] : ""
915 );
916 if (pFnDesc->apszParamDesc[i] != NULL)
917 sqlstrcat(pszQuery, ", ", pFnDesc->apszParamDesc[i]);
918 else
919 strcat(pszQuery, ", NULL)");
920
921 rc = mysql_queryu6(pmysql, pszQuery2);
922 if (rc < 0)
923 {
924 if (*pszError == ' ')
925 strcpy(pszError++, "\n\t");
926 sprintf(pszError, "Inserting parameter %i failed with error: %s - (sql=%s) ",
927 i, dbGetLastErrorDesc(), pszQuery);
928 pszError += strlen(pszError) - 1;
929 ulRc++;
930 }
931 }
932 }
933 }
934 else
935 {
936 if (*pszError == ' ')
937 strcpy(pszError++, "\n\t");
938 sprintf(pszError, "failed to store result or to fetch a row , error: %s - (sql=%s) ",
939 dbGetLastErrorDesc(), pszQuery);
940 pszError += strlen(pszError) - 1;
941 ulRc++;
942 }
943 }
944 else
945 {
946 if (*pszError == ' ')
947 strcpy(pszError++, "\n\t");
948 sprintf(pszError, "Failed querying number of parameters, error: %s - (sql=%s) ",
949 dbGetLastErrorDesc(), pszQuery);
950 pszError += strlen(pszError) - 1;
951 ulRc++;
952 }
953
954
955 /*
956 * Authors
957 */
958 sprintf(pszQuery, "DELETE FROM fnauthor WHERE function = %ld", pFnDesc->alRefCode[k]);
959 rc = mysql_queryu7(pmysql, pszQuery);
960 if (rc < 0)
961 {
962 if (*pszError == ' ')
963 strcpy(pszError++, "\n\t");
964 sprintf(pszError, "Deleting old authors failed with error: %s - (sql=%s) ",
965 dbGetLastErrorDesc(), pszQuery);
966 pszError += strlen(pszError) - 1;
967 ulRc++;
968 }
969
970 for (i = 0; i < pFnDesc->cAuthors; i++)
971 {
972 if (pFnDesc->alAuthorRefCode[i] == -1)
973 continue;
974 sprintf(pszQuery, "INSERT INTO fnauthor(author, function) "
975 "VALUES (%ld, %ld)",
976 pFnDesc->alAuthorRefCode[i], pFnDesc->alRefCode[k]);
977 rc = mysql_queryu8(pmysql, pszQuery);
978 if (rc < 0)
979 {
980 if (*pszError == ' ')
981 strcpy(pszError++, "\n\t");
982 sprintf(pszError, "Inserting parameter %i failed with error: %s - (sql=%s) ",
983 i, dbGetLastErrorDesc(), pszQuery);
984 pszError += strlen(pszError) - 1;
985 ulRc++;
986 }
987 }
988 } /* for */
989
990 lDll = lDll;
991 free(pszQuery2);
992 return ulRc;
993}
994
995
996/**
997 * Updates the history tables.
998 * @returns Number of signals/errors.
999 * @param pszError Pointer to buffer which will hold the error messages.
1000 * @remark This should be called whenever updates have been completed.
1001 */
1002unsigned long _System dbCreateHistory(char *pszError)
1003{
1004 unsigned long ulRc = 0;
1005 MYSQL_RES *pres;
1006 MYSQL_ROW row;
1007 char szQuery[256];
1008 char *pszQuery = &szQuery[0];
1009 int rc;
1010 char szCurDt[20] = {0}; /*yyyy-mm-dd\0*/
1011
1012 mysql_refresh(pmysql, REFRESH_TABLES);
1013
1014 /* get currentdate - just in case the date changes between the delete and the update is completed. */
1015 strcpy(pszQuery, "SELECT CURDATE()");
1016 rc = mysql_query(pmysql, pszQuery);
1017 pres = mysql_use_result(pmysql);
1018 if (rc >= 0 && pres != NULL)
1019 {
1020 row = mysql_fetch_row(pres);
1021 if (row != NULL && mysql_num_rows(pres) == 1)
1022 {
1023 strcpy(&szCurDt[0], row[0]);
1024 while (mysql_fetch_row(pres) != NULL)
1025 pres=pres;
1026
1027 /* delete - all rows on this date in the history tables */
1028 sprintf(pszQuery, "DELETE FROM historydll WHERE date = '%s'", &szCurDt[0]);
1029 rc = mysql_query(pmysql, pszQuery);
1030 CheckLogContinue((pszError, "error removing old history rows: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1031
1032 sprintf(pszQuery, "DELETE FROM historyapigroup WHERE date = '%s'", &szCurDt[0]);
1033 rc = mysql_query(pmysql, pszQuery);
1034 CheckLogContinue((pszError, "error removing old history rows: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1035
1036 sprintf(pszQuery, "DELETE FROM historydlltotal WHERE date = '%s'", &szCurDt[0]);
1037 rc = mysql_query(pmysql, pszQuery);
1038 CheckLogContinue((pszError, "error removing old history rows: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1039
1040 sprintf(pszQuery, "DELETE FROM historyapigrouptotal WHERE date = '%s'", &szCurDt[0]);
1041 CheckLogContinue((pszError, "error removing old history rows: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1042
1043 /* insert new stats */
1044 sprintf(pszQuery, "INSERT INTO historydll(dll, state, date, count) "
1045 "SELECT dll, state, '%s', count(*) FROM function GROUP BY dll, state",
1046 &szCurDt[0]);
1047 rc = mysql_query(pmysql, pszQuery);
1048 CheckLogContinue((pszError, "error inserting: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1049
1050 sprintf(pszQuery, "INSERT INTO historyapigroup(apigroup, state, date, count) "
1051 "SELECT dll, state, '%s', count(*) FROM function WHERE apigroup IS NOT NULL "
1052 "GROUP BY apigroup, state",
1053 &szCurDt[0]);
1054 rc = mysql_query(pmysql, pszQuery);
1055 CheckLogContinue((pszError, "error inserting: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1056
1057 /* inserting new totals */
1058 sprintf(pszQuery, "INSERT INTO historydlltotal(dll, date, totalcount) "
1059 "SELECT dll, '%s', count(*) FROM function GROUP BY dll",
1060 &szCurDt[0]);
1061 rc = mysql_query(pmysql, pszQuery);
1062 CheckLogContinue((pszError, "error inserting: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1063
1064 sprintf(pszQuery, "INSERT INTO historyapigrouptotal(apigroup, date, totalcount) "
1065 "SELECT apigroup, '%s', count(*) FROM function WHERE apigroup IS NOT NULL "
1066 "GROUP BY apigroup",
1067 &szCurDt[0]);
1068 rc = mysql_query(pmysql, pszQuery);
1069 CheckLogContinue((pszError, "error inserting: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1070 }
1071 else
1072 {
1073 sprintf(pszError, "error getting current date (row == NULL): %s - (sql=%s) ",
1074 dbGetLastErrorDesc(), pszQuery);
1075 ulRc++;
1076 }
1077 }
1078 else
1079 {
1080 sprintf(pszError, "error getting current date: %s - (sql=%s) ",
1081 dbGetLastErrorDesc(), pszQuery);
1082 ulRc++;
1083 }
1084
1085 mysql_refresh(pmysql, REFRESH_TABLES);
1086
1087 return ulRc;
1088}
1089
1090
1091/**
1092 * Check that database integrety is ok. Verfies foreign keys.
1093 * @returns numbers of errors.
1094 * @param pszError Very large buffer which will hold error messges (if any).
1095 * @sketch
1096 * @remark current versions of mysql don't support 'SELECT ... WHERE id NOT IN(SELECT id FROM table)'
1097 */
1098unsigned long _System dbCheckIntegrity(char *pszError)
1099{
1100 char szQuery[384];
1101 char *pszQuery = &szQuery[0];
1102 MYSQL_RES *pres1;
1103 MYSQL_RES *pres2;
1104 MYSQL_ROW row1;
1105 int rc;
1106 unsigned long ulRc = 0;
1107
1108 mysql_refresh(pmysql, REFRESH_TABLES);
1109
1110 /* foreign keys in function table */
1111 strcpy(pszQuery, "SELECT refcode, dll, state, apigroup FROM function");
1112 rc = mysql_query(pmysql, pszQuery);
1113 if (rc >= 0)
1114 {
1115 pres1 = mysql_store_result(pmysql);
1116 if (pres1 != NULL)
1117 {
1118 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1119 {
1120 /* check dll */
1121 sprintf(pszQuery, "SELECT name FROM dll WHERE refcode = %s", row1[1]);
1122 rc = mysql_query(pmysql, pszQuery);
1123 CheckFKError("function/dll", "Foreign key 'dll' not found in the dll table");
1124
1125 /* check state */
1126 sprintf(pszQuery, "SELECT name FROM state WHERE refcode = %s", row1[2]);
1127 rc = mysql_query(pmysql, pszQuery);
1128 CheckFKError("function/state", "Foreign key 'state' not found in the state table");
1129
1130 /* check apigroup */
1131 if (row1[3] != NULL)
1132 {
1133 sprintf(pszQuery, "SELECT name FROM apigroup WHERE refcode = %s", row1[3]);
1134 rc = mysql_query(pmysql, pszQuery);
1135 CheckFKError("function/state", "Foreign key 'state' not found in the state table");
1136 }
1137 }
1138 mysql_free_result(pres1);
1139 }
1140 }
1141 else
1142 ulRc += logDbError(pszError, pszQuery);
1143
1144 /* foreign keys in apigroup */
1145 strcpy(pszQuery, "SELECT refcode, dll FROM apigroup");
1146 rc = mysql_query(pmysql, pszQuery);
1147 if (rc >= 0)
1148 {
1149 pres1 = mysql_store_result(pmysql);
1150 if (pres1 != NULL)
1151 {
1152 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1153 {
1154 /* check dll */
1155 sprintf(pszQuery, "SELECT refcode FROM dll WHERE refcode = %s", row1[1]);
1156 rc = mysql_query(pmysql, pszQuery);
1157 CheckFKError("apigroup/dll", "Foreign key 'dll' not found in the dll table");
1158 }
1159 mysql_free_result(pres1);
1160 }
1161 }
1162 else
1163 ulRc += logDbError(pszError, pszQuery);
1164
1165 /* foreign keys in fnauthor */
1166 strcpy(pszQuery, "SELECT function, author FROM fnauthor");
1167 rc = mysql_query(pmysql, pszQuery);
1168 if (rc >= 0)
1169 {
1170 pres1 = mysql_store_result(pmysql);
1171 if (pres1 != NULL)
1172 {
1173 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1174 {
1175 /* check function */
1176 sprintf(pszQuery, "SELECT refcode FROM function WHERE refcode = %s", row1[1]);
1177 rc = mysql_query(pmysql, pszQuery);
1178 CheckFKError("fnauthor/function", "Foreign key 'function' not found in the function table");
1179
1180 /* check author */
1181 sprintf(pszQuery, "SELECT refcode FROM author WHERE refcode = %s", row1[1]);
1182 rc = mysql_query(pmysql, pszQuery);
1183 CheckFKError("fnauthor/author", "Foreign key 'author' not found in the author table");
1184 }
1185 mysql_free_result(pres1);
1186 }
1187 }
1188 else
1189 ulRc += logDbError(pszError, pszQuery);
1190
1191 /* foreign keys in historydll table */
1192 strcpy(pszQuery, "SELECT date, dll, state FROM historydll");
1193 rc = mysql_query(pmysql, pszQuery);
1194 if (rc >= 0)
1195 {
1196 pres1 = mysql_store_result(pmysql);
1197 if (pres1 != NULL)
1198 {
1199 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1200 {
1201 /* check dll */
1202 sprintf(pszQuery, "SELECT refcode FROM dll WHERE refcode = %s", row1[1]);
1203 rc = mysql_query(pmysql, pszQuery);
1204 CheckFKError("historydll/dll", "Foreign key 'dll' not found in the dll table");
1205
1206 /* check state */
1207 sprintf(pszQuery, "SELECT refcode FROM state WHERE refcode = %s", row1[2]);
1208 rc = mysql_query(pmysql, pszQuery);
1209 CheckFKError("historydll/state", "Foreign key 'state' not found in the state table");
1210 }
1211 mysql_free_result(pres1);
1212 }
1213 }
1214 else
1215 ulRc += logDbError(pszError, pszQuery);
1216
1217 /* foreign keys in historyapigroup table */
1218 strcpy(pszQuery, "SELECT date, apigroup, state FROM historyapigroup");
1219 rc = mysql_query(pmysql, pszQuery);
1220 if (rc >= 0)
1221 {
1222 pres1 = mysql_store_result(pmysql);
1223 if (pres1 != NULL)
1224 {
1225 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1226 {
1227 /* check dll */
1228 sprintf(pszQuery, "SELECT refcode FROM apigroup WHERE refcode = %s", row1[1]);
1229 rc = mysql_query(pmysql, pszQuery);
1230 CheckFKError("historyapigroup/apigroup", "Foreign key 'apigroup' not found in the apigroup table");
1231
1232 /* check state */
1233 sprintf(pszQuery, "SELECT refcode FROM state WHERE refcode = %s", row1[2]);
1234 rc = mysql_query(pmysql, pszQuery);
1235 CheckFKError("historyapigroup/state", "Foreign key 'state' not found in the state table");
1236 }
1237 mysql_free_result(pres1);
1238 }
1239 }
1240 else
1241 ulRc += logDbError(pszError, pszQuery);
1242
1243 /* foreign keys in historydlltotal table */
1244 strcpy(pszQuery, "SELECT date, dll FROM historydlltotal");
1245 rc = mysql_query(pmysql, pszQuery);
1246 if (rc >= 0)
1247 {
1248 pres1 = mysql_store_result(pmysql);
1249 if (pres1 != NULL)
1250 {
1251 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1252 {
1253 /* check dll */
1254 sprintf(pszQuery, "SELECT refcode FROM dll WHERE refcode = %s", row1[1]);
1255 rc = mysql_query(pmysql, pszQuery);
1256 CheckFKError("historydlltotal/dll", "Foreign key 'dll' not found in the dll table");
1257 }
1258 mysql_free_result(pres1);
1259 }
1260 }
1261 else
1262 ulRc += logDbError(pszError, pszQuery);
1263
1264 /* foreign keys in historyapigroup table */
1265 strcpy(pszQuery, "SELECT date, apigroup FROM historyapigrouptotal");
1266 rc = mysql_query(pmysql, pszQuery);
1267 if (rc >= 0)
1268 {
1269 pres1 = mysql_store_result(pmysql);
1270 if (pres1 != NULL)
1271 {
1272 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1273 {
1274 /* check dll */
1275 sprintf(pszQuery, "SELECT refcode FROM apigroup WHERE refcode = %s", row1[1]);
1276 rc = mysql_query(pmysql, pszQuery);
1277 CheckFKError("historyapigrouptotal/apigroup", "Foreign key 'apigroup' not found in the apigroup table");
1278 }
1279 mysql_free_result(pres1);
1280 }
1281 }
1282 else
1283 ulRc += logDbError(pszError, pszQuery);
1284
1285 /* foreign keys in parameter table */
1286 strcpy(pszQuery, "SELECT sequencenbr, function FROM parameter");
1287 rc = mysql_query(pmysql, pszQuery);
1288 if (rc >= 0)
1289 {
1290 pres1 = mysql_store_result(pmysql);
1291 if (pres1 != NULL)
1292 {
1293 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1294 {
1295 /* check function */
1296 sprintf(pszQuery, "SELECT refcode FROM function WHERE refcode = %s", row1[1]);
1297 rc = mysql_query(pmysql, pszQuery);
1298 CheckFKError("parameter/function", "Foreign key 'function' not found in the function table");
1299 }
1300 mysql_free_result(pres1);
1301 }
1302 }
1303 else
1304 ulRc += logDbError(pszError, pszQuery);
1305
1306 /* Author table is special, since you should be able to interchangably reference an
1307 * author by any of the following tables:
1308 * name
1309 * initials
1310 * alias
1311 * email
1312 */
1313 strcpy(pszQuery, "SELECT name, initials, alias, email FROM author");
1314 rc = mysql_query(pmysql, pszQuery);
1315 if (rc >= 0)
1316 {
1317 pres1 = mysql_store_result(pmysql);
1318 if (pres1 != NULL)
1319 {
1320 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1321 {
1322 /* check name */
1323 sprintf(pszQuery, "SELECT name FROM author WHERE "
1324 "initials = '%s' OR alias = '%s' OR email = '%s'",
1325 row1[0], row1[0], row1[0]);
1326 ulRc += CheckAuthorError(pszError, "name", row1[0], pszQuery);
1327
1328 /* check initials */
1329 sprintf(pszQuery, "SELECT name FROM author WHERE "
1330 "alias = '%s' OR email = '%s'",
1331 row1[1], row1[1]);
1332 ulRc += CheckAuthorError(pszError, "initials", row1[1], pszQuery);
1333
1334 /* alias */
1335 if (row1[2] != NULL)
1336 {
1337 sprintf(pszQuery, "SELECT name FROM author WHERE "
1338 "email = '%s'",
1339 row1[2]);
1340 ulRc += CheckAuthorError(pszError, "alias", row1[2], pszQuery);
1341 }
1342 }
1343 mysql_free_result(pres1);
1344 }
1345 }
1346 else
1347 ulRc += logDbError(pszError, pszQuery);
1348
1349 return ulRc;
1350}
1351
1352
1353/**
1354 * Checks for duplicate key and sql error for a given author key in the author table... (arg!)
1355 * @returns Number of errors.
1356 * @param pszError Reference to error buffer pointer.
1357 * @param pszFieldName Key field name; used for logging.
1358 * @param pszFieldValue Key value; used for logging
1359 * @param pszQuery Query which is to be exectued to test for duplicate key.
1360 * @remark Uses pszError[1] == '\xFE' to detect when to insert '\n\t'.
1361 */
1362static unsigned long CheckAuthorError(char * &pszError, const char *pszFieldName, const char *pszFieldValue, const char *pszQuery)
1363{
1364 MYSQL_ROW row;
1365 MYSQL_RES *pres;
1366 unsigned long ulRc = 0;
1367 int rc;
1368
1369 rc = mysql_query(pmysql, pszQuery);
1370 pres = mysql_store_result(pmysql);
1371 if (rc < 0 || (pres != NULL && mysql_num_rows(pres) != 0))
1372 { /* some kind of error has occurred */
1373 if (pszError[1] == '\xFE')
1374 {
1375 strcat(pszError, "\n\t");
1376 pszError += 2;
1377 }
1378
1379 if (rc < 0) /* sql error or 'duplicate key' */
1380 {
1381 sprintf(pszError, "author/%s: select failed - %s (sql=%s)",
1382 pszFieldName, dbGetLastErrorDesc(), pszQuery);
1383 }
1384 else
1385 { /* 'duplicate key' - print duplicates */
1386 sprintf(pszError, "author/%s: 'duplicate key', %s='%s': ",
1387 pszFieldName, pszFieldValue, pszFieldName);
1388
1389 while ((row = mysql_fetch_row(pres)) != NULL)
1390 {
1391 pszError += strlen(pszError);
1392 sprintf(pszError, "'%s' ", row[0]);
1393 }
1394 }
1395
1396 pszError += strlen(pszError);
1397 pszError[1] = '\xFE';
1398 ulRc = 1;
1399 }
1400 if (pres != NULL)
1401 mysql_free_result(pres);
1402
1403 return ulRc;
1404}
1405
1406
1407/**
1408 * Writes db error (rc<0) to the log buffer.
1409 * @returns Number of signals.
1410 * @param pszError Reference to the error buffer pointer.
1411 * @param pszQuery Pointer to query which was executed.
1412 * @remark Uses pszError[1] == '\xFE' to detect when to insert '\n\t'.
1413 */
1414static unsigned long logDbError(char * &pszError, const char *pszQuery)
1415{
1416 if (pszError[1] == '\xFE')
1417 {
1418 strcat(pszError, "\n\t");
1419 pszError += 2;
1420 }
1421 sprintf(pszError, "select failed: %s - (sql=%s)", dbGetLastErrorDesc(), pszQuery);
1422
1423 pszError += strlen(pszError);
1424 pszError[1] = '\xFE';
1425
1426 return 1;
1427}
1428
1429
1430/**
1431 * Executes a give query and returns a result identifier/pointer.
1432 * @returns Query result identifier/pointer. NULL on error.
1433 * @param pszQuery Pointer to query.
1434 * @remark Used by and designed for kHtmlPC.
1435 */
1436void * _System dbExecuteQuery(const char *pszQuery)
1437{
1438 assert(pmysql != NULL);
1439 if (mysql_query(pmysql, pszQuery) >= 0)
1440 return mysql_store_result(pmysql);
1441
1442 return NULL;
1443}
1444
1445
1446/**
1447 * Asks for the number of rows in the result.
1448 * @returns Number of rows in the result. -1 on error.
1449 * @param pres Query result identifier/pointer.
1450 * @remark Used by and designed for kHtmlPC.
1451 */
1452signed long _System dbQueryResultRows(void *pres)
1453{
1454 if (pres == NULL)
1455 return -1;
1456 return mysql_num_rows((MYSQL_RES*)pres);
1457}
1458
1459
1460/**
1461 * Frees the storage allocated by the given result.
1462 * @returns Success indicator, TRUE/FALSE.
1463 * @param pres Query result identifier/pointer.
1464 * @remark Used by and designed for kHtmlPC.
1465 */
1466BOOL _System dbFreeResult(void *pres)
1467{
1468 if (pres != NULL)
1469 mysql_free_result((MYSQL_RES*)pres);
1470 else
1471 return FALSE;
1472 return TRUE;
1473}
1474
1475
1476/**
1477 * Fetch data from a result. Returns the data by calling the given callback function.
1478 * @returns Success indicator, TRUE/FALSE.
1479 * @param pres Query result identifier/pointer.
1480 * @param dbFetchCallBack Callback-function.
1481 * @param pvUser User parameter which is passed onto dbFetchCallBack.
1482 * @remark Used by and designed for kHtmlPC.
1483 */
1484BOOL _System dbFetch(void *pres, DBCALLBACKFETCH dbFetchCallBack, void *pvUser)
1485{
1486 BOOL fRc = FALSE;
1487 MYSQL_ROW row = mysql_fetch_row((MYSQL_RES*)pres);
1488
1489 if (row)
1490 {
1491 MYSQL_FIELD *pField;
1492 int i = 0;
1493 mysql_field_seek((MYSQL_RES*)pres, 0);
1494
1495 while ((pField = mysql_fetch_field((MYSQL_RES*)pres)) != NULL)
1496 if (dbFetchCallBack(row[i++], pField->name, pvUser) != 0)
1497 return FALSE;
1498
1499 fRc = TRUE;
1500 }
1501
1502 return fRc;
1503}
1504
1505
1506/**
1507 * Converts an ISO date to days after Christ, year 0.
1508 * @returns days. -1 on error;
1509 * @param pszDate ISO Date.
1510 */
1511signed long _System dbDateToDaysAfterChrist(const char *pszDate)
1512{
1513 signed long lRet = -1;
1514 char szQuery[128];
1515
1516 sprintf(&szQuery[0], "SELECT to_days('%s')", pszDate);
1517 if (mysql_query(pmysql, &szQuery[0]) >= 0)
1518 {
1519 MYSQL_ROW row;
1520 MYSQL_RES *pres = mysql_use_result(pmysql);
1521 row = mysql_fetch_row(pres);
1522 if (row != NULL)
1523 {
1524 lRet = atol(row[0]);
1525 do { row = mysql_fetch_row(pres); } while (row != NULL);
1526 }
1527 }
1528
1529 return lRet;
1530}
1531
1532
1533/**
1534 * Converts days after Christ (year 0) to ISO date.
1535 * @returns Success indicator. TRUE/FALSE;
1536 * @param lDays Days after Christ (year 0).
1537 * @param pszDate ISO Date. Result.
1538 */
1539BOOL _System dbDaysAfterChristToDate(signed long lDays, char *pszDate)
1540{
1541 BOOL fRet = FALSE;
1542 char szQuery[128];
1543
1544 if (lDays < 0)
1545 return FALSE;
1546
1547 sprintf(&szQuery[0], "SELECT from_days(%ld)", lDays);
1548 if (mysql_query(pmysql, &szQuery[0]) >= 0)
1549 {
1550 MYSQL_ROW row;
1551 MYSQL_RES *pres = mysql_use_result(pmysql);
1552 row = mysql_fetch_row(pres);
1553 if (row != NULL)
1554 {
1555 fRet = strlen(row[0]) == (4+1+2+1+2) && row[0][4] == '-' && row[0][7] == '-'
1556 && strcmp(row[0], "0000-00-00") != 0;
1557 if (fRet)
1558 strcpy(pszDate, row[0]);
1559 do { row = mysql_fetch_row(pres); } while (row != NULL);
1560 }
1561 }
1562
1563 return fRet;
1564}
1565
1566
1567/**
1568 * Display all functions for, the given dll, that is not updated.
1569 * @returns TRUE / FALSE.
1570 * @param lDll Dll reference number.
1571 * @param dbFetchCall Callback function which will be called once for each
1572 * field for all the functions not updated.
1573 * pvUser is NULL, pszValue field value, pszFieldName the field name.
1574 */
1575BOOL _System dbGetNotUpdatedFunction(signed long lDll, DBCALLBACKFETCH dbFetchCallBack)
1576{
1577 BOOL fRet = FALSE;
1578 void *pres;
1579 char szQuery[256];
1580
1581 /* not updated names */
1582 sprintf(&szQuery[0], "SELECT f1.name, f1.intname, f1.updated, f1.aliasfn, d.name, f2.name, f2.intname AS last "
1583 "FROM function f1 LEFT OUTER JOIN function f2 ON f1.aliasfn = f2.refcode "
1584 " LEFT JOIN dll d ON f2.dll = d.refcode "
1585 "WHERE f1.dll = %ld AND f1.updated = 0",
1586 lDll);
1587 pres = dbExecuteQuery(szQuery);
1588 if (pres != NULL)
1589 {
1590 BOOL f;
1591 do
1592 {
1593 f = dbFetch(pres, dbFetchCallBack, NULL);
1594 } while (f);
1595 dbFreeResult(pres);
1596 fRet = TRUE;
1597 }
1598
1599 /* warn about updated > 1 too */
1600 sprintf(&szQuery[0], "SELECT f1.name, f1.intname, f1.updated, f1.aliasfn, d.name, f2.name, f2.intname AS last "
1601 "FROM function f1 LEFT OUTER JOIN function f2 ON f1.aliasfn = f2.refcode "
1602 " LEFT JOIN dll d ON f2.dll = d.refcode "
1603 "WHERE f1.dll = %ld AND f1.updated > 1",
1604 lDll);
1605 pres = dbExecuteQuery(szQuery);
1606 if (pres != NULL)
1607 {
1608 BOOL f;
1609 do
1610 {
1611 f = dbFetch(pres, dbFetchCallBack, NULL);
1612 } while (f);
1613 dbFreeResult(pres);
1614 fRet = TRUE;
1615 }
1616
1617 strcpy(&szQuery[0], "UPDATE function SET updated = 0");
1618 mysql_query(pmysql, &szQuery[0]);
1619
1620 return fRet;
1621}
1622
1623
1624/**
1625 * Counts the function for the given DLL which has been updated.
1626 * @returns -1 on error, number of updated function on success.
1627 * @param lDll Dll reference number.
1628 */
1629signed long _System dbGetNumberOfUpdatedFunction(signed long lDll)
1630{
1631 int rc;
1632 char szQuery[128];
1633 MYSQL_RES * pres;
1634
1635 sprintf(&szQuery[0], "SELECT count(*) FROM function WHERE dll = (%ld) AND updated > 0\n", lDll);
1636 rc = mysql_query(pmysql, &szQuery[0]);
1637 pres = mysql_store_result(pmysql);
1638 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) == 1)
1639 rc = (int)getvalue(0, mysql_fetch_row(pres));
1640 else
1641 rc = -1;
1642 mysql_free_result(pres);
1643 return (signed long)rc;
1644}
1645
1646
1647/**
1648 *
1649 * @returns Pointer to end of the string.
1650 * @param pszQuery Outputbuffer
1651 * @param pszBefore Text before string, might be NULL.
1652 * @param pszStr String (NOT NULL)
1653 * @param pszAfter Text after, might be NULL.
1654 * @status completely implemented
1655 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1656 */
1657static char *sqlstrcat(char *pszQuery, const char *pszBefore, const char *pszStr, const char *pszAfter)
1658{
1659 register char ch;
1660
1661 pszQuery += strlen(pszQuery);
1662
1663 /*
1664 * String before
1665 */
1666 if (pszBefore != NULL)
1667 {
1668 strcpy(pszQuery, pszBefore);
1669 pszQuery += strlen(pszQuery);
1670 }
1671
1672 /*
1673 * THE String
1674 */
1675 *pszQuery++ = '\'';
1676 while ((ch = *pszStr++) != '\0')
1677 {
1678 if (ch == '\'')
1679 *pszQuery++ = '\\';
1680 *pszQuery++ = ch;
1681 }
1682 *pszQuery++ = '\'';
1683
1684 /*
1685 * String after
1686 */
1687 if (pszAfter != NULL)
1688 {
1689 strcpy(pszQuery, pszAfter);
1690 pszQuery += strlen(pszQuery);
1691 }
1692 else
1693 *pszQuery = '\0';
1694
1695
1696 return pszQuery;
1697}
1698
1699
1700#ifndef DLL
1701/**
1702 * Signal handler.
1703 * Ensures that the database connection is closed at termination.
1704 * @param sig Signal number.
1705 */
1706void dbHandler(int sig)
1707{
1708 if (pmysql != NULL)
1709 {
1710 fprintf(stderr, "\n\t!disconnecting from database!\n");
1711 dbDisconnect();
1712 }
1713
1714 flushall();
1715 switch (sig)
1716 {
1717 case SIGBREAK:
1718 printf("\nSIGBREAK\n");
1719 exit(-1);
1720 break;
1721 case SIGINT:
1722 printf("\nSIGINT\n");
1723 exit(-1);
1724 break;
1725 case SIGTERM:
1726 printf("\nSIGTERM\n");
1727 exit(-1);
1728 break;
1729 case SIGSEGV:
1730 raise(sig);
1731 break;
1732 case SIGILL:
1733 printf("\nSIGILL\n");
1734 exit(-1);
1735 break;
1736 }
1737}
1738
1739
1740#else
1741/*******/
1742/* DLL */
1743/*******/
1744/* prototypes used in the _DLL_InitTerm function */
1745extern "C"
1746{
1747 int _CRT_init(void);
1748 void _CRT_term(void);
1749 void __ctordtorInit( void );
1750 void __ctordtorTerm( void );
1751 unsigned long _System _DLL_InitTerm(unsigned long hModule, unsigned long ulFlag);
1752}
1753
1754
1755/**
1756 * Dll InitTerm function.
1757 * @returns 0 on success.
1758 * 1 on error.
1759 * @param hModule
1760 * @param ulFlags
1761 * @remark We'll ensure that the database connection is terminated as we terminate.
1762 */
1763unsigned long _System _DLL_InitTerm(unsigned long hModule, unsigned long ulFlag)
1764{
1765 /*-------------------------------------------------------------------------*/
1766 /* If ulFlag is zero then the DLL is being loaded so initialization should */
1767 /* be performed. If ulFlag is 1 then the DLL is being freed so */
1768 /* termination should be performed. */
1769 /*-------------------------------------------------------------------------*/
1770
1771 switch (ulFlag)
1772 {
1773 case 0:
1774 if (_CRT_init() == -1)
1775 return 0;
1776 __ctordtorInit();
1777 break;
1778
1779 case 1:
1780 /* ensure that db connection is terminated */
1781 if (pmysql != NULL)
1782 {
1783 fprintf(stderr, "\n\t!disconnecting from database!\n");
1784 dbDisconnect();
1785 }
1786 __ctordtorTerm();
1787 break;
1788
1789 default:
1790 return 0;
1791 }
1792 hModule = hModule;
1793 return 1;
1794}
1795
1796/*****************************************************************/
1797/* -why is this terminate function referenced but not defined??? */
1798/* and where is it referenced??? */
1799/* -Probably an export missing from the libraries. */
1800/*****************************************************************/
1801void terminate(void)
1802{
1803 DosPutMessage(0, sizeof("terminate")-1, "terminate");
1804 exit(-1);
1805}
1806
1807/****************************************/
1808/* EMX run-time trouble */
1809/* _environ is missing when using -Zomf */
1810/****************************************/
1811char **_environ = environ;
1812
1813#endif
Note: See TracBrowser for help on using the repository browser.