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

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

Odin32 DB.

File size: 42.2 KB
Line 
1/* $Id: db.cpp,v 1.5 2000-02-11 18:35:54 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);
82#ifdef NOTDLL
83 extern "C" void dbHandler(int sig);
84#endif
85
86
87/**
88 * Gets the descriptions of the last database error.
89 * @returns Readonly string.
90 */
91char * _System dbGetLastErrorDesc(void)
92{
93 return mysql_error(&mysql);
94}
95
96
97/**
98 * Connects to local database.
99 * @returns Success indicator, TRUE / FALSE.
100 * @param pszDatabase Name of database to use.
101 */
102BOOL _System dbConnect(const char *pszHost, const char *pszUser, const char *pszPassword, const char *pszDatabase)
103{
104 BOOL fRet = FALSE;
105 #ifdef NOTDLL
106 static fHandler = FALSE;
107 /* signal handler */
108 if (!fHandler)
109 {
110 if ( SIG_ERR == signal(SIGBREAK, dbHandler)
111 || SIG_ERR == signal(SIGINT, dbHandler)
112 || SIG_ERR == signal(SIGTERM, dbHandler)
113 || SIG_ERR == signal(SIGABRT, dbHandler)
114 || SIG_ERR == signal(SIGSEGV, dbHandler)
115 || SIG_ERR == signal(SIGILL, dbHandler)
116 )
117 fprintf(stderr, "Error installing signalhandler...");
118 else
119 fHandler = TRUE;
120 }
121 #endif
122
123 /* connect to server */
124 memset(&mysql, 0, sizeof(mysql));
125 pmysql = mysql_connect(&mysql, pszHost, pszUser, pszPassword);
126 if (pmysql != NULL)
127 {
128 /* connect to database */
129 fRet = mysql_select_db(pmysql, pszDatabase) >= 0;
130 if (fRet)
131 mysql_refresh(pmysql, REFRESH_TABLES);
132 }
133
134 return fRet;
135}
136
137
138/**
139 * Disconnects from database.
140 * @returns Success indicator. TRUE / FALSE.
141 */
142BOOL _System dbDisconnect(void)
143{
144 if (pmysql != NULL)
145 {
146 mysql_refresh(pmysql, REFRESH_TABLES);
147 mysql_close(pmysql);
148 pmysql = NULL;
149 }
150 return TRUE;
151}
152
153/**
154 * Gets the refid for the give dll name.
155 * @returns Dll refid. -1 on error.
156 * @param pszDllName Dll name.
157 */
158signed short _System dbGetDll(const char *pszDllName)
159{
160 int rc;
161 char szQuery[256];
162 MYSQL_RES * pres;
163
164 sprintf(&szQuery[0], "SELECT refcode FROM dll WHERE name = '%s'\n", pszDllName);
165 rc = mysql_query(pmysql, &szQuery[0]);
166 pres = mysql_store_result(pmysql);
167
168 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) == 1)
169 rc = (int)getvalue(0, mysql_fetch_row(pres));
170 else
171 rc = -1;
172 mysql_free_result(pres);
173 return (short)rc;
174}
175
176
177/**
178 * Count the function in a given dll.
179 * @returns Number of functions. -1 on error.
180 * @param usDll Dll refcode.
181 */
182signed long _System dbCountFunctionInDll(signed long ulDll)
183{
184 signed long rc;
185 char szQuery[256];
186 MYSQL_RES * pres;
187
188 if (ulDll >= 0)
189 {
190 sprintf(&szQuery[0], "SELECT count(refcode) FROM function WHERE dll = %d\n", ulDll);
191 rc = mysql_query(pmysql, &szQuery[0]);
192 pres = mysql_store_result(pmysql);
193
194 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) == 1)
195 rc = (int)getvalue(0, mysql_fetch_row(pres));
196 else
197 rc = -1;
198 mysql_free_result(pres);
199 }
200 else
201 rc = -1;
202 return rc;
203}
204
205
206
207/**
208 * Checks if dll exists. If not exists the dll is inserted.
209 * @returns Dll refcode. -1 on errors.
210 * @param pszDll Dll name.
211 * @remark This search must be case insensitive.
212 * (In the mysql-world everything is case insensitive!)
213 */
214signed short _System dbCheckInsertDll(const char *pszDll)
215{
216 int rc;
217 char szQuery[256];
218 MYSQL_RES * pres;
219
220 /* try find match */
221 sprintf(&szQuery[0], "SELECT refcode, name FROM dll WHERE name = '%s'\n", pszDll);
222 rc = mysql_query(pmysql, &szQuery[0]);
223 pres = mysql_store_result(pmysql);
224
225 /* not found? - insert dll */
226 if (rc < 0 || pres == NULL || mysql_num_rows(pres) == 0)
227 {
228 mysql_free_result(pres);
229
230 sprintf(&szQuery[0], "INSERT INTO dll(name) VALUES('%s')\n", pszDll);
231 rc = mysql_query(pmysql, &szQuery[0]);
232
233 /* select row to get refcode */
234 sprintf(&szQuery[0], "SELECT refcode, name FROM dll WHERE name = '%s'\n", pszDll);
235 rc = mysql_query(pmysql, &szQuery[0]);
236 pres = mysql_store_result(pmysql);
237 }
238
239 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) == 1)
240 rc = (int)getvalue(0, mysql_fetch_row(pres));
241 else
242 rc = -1;
243 mysql_free_result(pres);
244
245 return (short)rc;
246}
247
248
249/**
250 * Simple select for a long value.
251 * @returns long value
252 * @param pszTable From part.
253 * @param pszGetColumn Name of column to retreive.
254 * @param pszMatch1 Match column/expression
255 * @param pszMatchValue1 Match value.
256 * @remark Dirty! Don't use this!
257 */
258unsigned short _System dbGet(const char *pszTable, const char *pszGetColumn,
259 const char *pszMatch1, const char *pszMatchValue1)
260{
261 int rc;
262 char szQuery[256];
263 MYSQL_RES *pres;
264
265 /* try find match */
266 sprintf(&szQuery[0], "SELECT %s FROM %s WHERE %s = '%s'\n",
267 pszGetColumn, pszTable, pszMatch1, pszMatchValue1);
268 rc = mysql_query(pmysql, &szQuery[0]);
269 pres = mysql_store_result(pmysql);
270
271 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) == 1)
272 rc = (int)getvalue(0, mysql_fetch_row(pres));
273 else
274 rc = -1;
275 mysql_free_result(pres);
276
277 return (short)rc;
278}
279
280
281/**
282 * Updates or inserts a function name into the database.
283 * @returns Success indicator. TRUE / FALSE.
284 * @param usDll Dll refcode.
285 * @param pszFunction Function name.
286 * @param pszIntFunction Internal function name.
287 * @param ulOrdinal Ordinal value.
288 * @param fIgnoreOrdinal Do not update ordinal value.
289 */
290BOOL _System dbInsertUpdateFunction(unsigned short usDll,
291 const char *pszFunction, const char *pszIntFunction,
292 unsigned long ulOrdinal, BOOL fIgnoreOrdinal)
293{
294 int rc;
295 long lFunction = -1;
296 char szQuery[256];
297 MYSQL_RES *pres;
298
299 /* when no internal name, the exported name is the internal name too! */
300 if (pszIntFunction == NULL || *pszIntFunction == '\0')
301 pszIntFunction = pszFunction;
302
303 /* try find function */
304 sprintf(&szQuery[0], "SELECT refcode, intname FROM function WHERE dll = %d AND name = '%s'", usDll, pszFunction);
305 rc = mysql_query(pmysql, &szQuery[0]);
306 pres = mysql_store_result(pmysql);
307 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) != 0)
308 { /* update function (function is found) */
309 MYSQL_ROW parow;
310 if (mysql_num_rows(pres) > 1)
311 {
312 fprintf(stderr, "internal database integrity error(%s): More function by the same name for the same dll. "
313 "usDll = %d, pszFunction = %s\n", __FUNCTION__, usDll, pszFunction);
314 return FALSE;
315 }
316
317 parow = mysql_fetch_row(pres);
318 if (parow != NULL)
319 lFunction = getvalue(0, parow);
320 mysql_free_result(pres);
321
322 if (strcmp(parow[1], pszIntFunction) != 0)
323 {
324 sprintf(&szQuery[0], "UPDATE function SET intname = '%s' WHERE refcode = %ld",
325 pszIntFunction, lFunction);
326 rc = mysql_query(pmysql, &szQuery[0]);
327 }
328
329 if (rc >= 0 && !fIgnoreOrdinal)
330 {
331 sprintf(&szQuery[0], "UPDATE function SET ordinal = %ld WHERE refcode = %ld",
332 ulOrdinal, lFunction);
333 rc = mysql_query(pmysql, &szQuery[0]);
334 }
335
336 }
337 else
338 { /* insert */
339 sprintf(&szQuery[0], "INSERT INTO function(dll, name, intname, ordinal) VALUES(%d, '%s', '%s', %ld)",
340 usDll, pszFunction, pszIntFunction, ulOrdinal);
341 rc = mysql_query(pmysql, &szQuery[0]);
342 }
343
344 return rc >= 0;
345}
346
347
348/**
349 * Get a long value.
350 * @returns Number value of pRow[iField]. -1 on error.
351 * @param iField Index into pRow.
352 * @param pRow Pointer to array (of string pointers).
353 */
354static long getvalue(int iField, MYSQL_ROW papszRow)
355{
356 if (papszRow[iField] != NULL)
357 return atol((char*)papszRow[iField]);
358
359 return -1;
360}
361
362
363/**
364 * Find occurences of a function, given by internal name.
365 * @returns success indicator, TRUE / FALSE.
366 * @param pszFunctionName
367 * @param pFnFindBuf
368 */
369BOOL _System dbFindFunction(const char *pszFunctionName, PFNFINDBUF pFnFindBuf)
370{
371 MYSQL_RES *pres;
372 MYSQL_ROW row;
373 int rc;
374 char szQuery[256];
375
376 sprintf(&szQuery[0], "SELECT refcode, dll FROM function WHERE intname = '%s'",
377 pszFunctionName, pszFunctionName);
378
379 rc = mysql_query(pmysql, &szQuery[0]);
380 if (rc >= 0)
381 {
382 pres = mysql_store_result(pmysql);
383 if (pres != NULL)
384 {
385 pFnFindBuf->cFns = 0;
386 while ((row = mysql_fetch_row(pres)) != NULL)
387 {
388 pFnFindBuf->alRefCode[pFnFindBuf->cFns] = atol(row[0]);
389 pFnFindBuf->alDllRefCode[pFnFindBuf->cFns] = atol(row[1]);
390
391 /* next */
392 pFnFindBuf->cFns++;
393 }
394 mysql_free_result(pres);
395 }
396 else
397 rc = -1;
398 }
399
400 return rc >= 0;
401}
402
403
404/**
405 * Finds the refcode for an author, if the author exists.
406 * @returns Author 'refcode'.
407 * @param pszAuthor String which holds the identifier of an author.
408 * This doesn't have to be the name. Initials, alias and email
409 * is also searched.
410 */
411signed long _System dbFindAuthor(const char *pszAuthor)
412{
413 signed long refcode = -1;
414 MYSQL_RES *pres;
415 char szQuery[256];
416
417 sprintf(&szQuery[0],
418 "SELECT refcode FROM author "
419 "WHERE name = '%s' OR "
420 " initials = '%s' OR "
421 " alias = '%s' OR "
422 " email = '%s'",
423 pszAuthor, pszAuthor, pszAuthor, pszAuthor);
424 if (mysql_query(pmysql, &szQuery[0]) >= 0)
425 {
426 pres = mysql_store_result(pmysql);
427 if (pres != NULL)
428 {
429 MYSQL_ROW parow;
430
431 /* integrety check */
432 if (mysql_num_rows(pres) > 1)
433 fprintf(stderr, "Integrety: author '%s' is not unique!\n", pszAuthor);
434 parow = mysql_fetch_row(pres);
435 if (parow != NULL)
436 refcode = getvalue(0, parow);
437
438 mysql_free_result(pres);
439 }
440 }
441
442 return refcode;
443}
444
445
446/**
447 * Gets the state of a function.
448 * @returns state code. On error -1.
449 * @param lRefCode Function refcode.
450 */
451signed long _System dbGetFunctionState(signed long lRefCode)
452{
453 signed long lState = -1;
454 MYSQL_RES *pres;
455 char szQuery[128];
456
457 sprintf(&szQuery[0], "SELECT state FROM function WHERE refcode = %ld", lRefCode);
458 if (mysql_query(pmysql, &szQuery[0]) >= 0)
459 {
460 pres = mysql_store_result(pmysql);
461 if (pres != NULL)
462 {
463 MYSQL_ROW parow = mysql_fetch_row(pres);
464 if (parow != NULL)
465 lState = getvalue(0, parow);
466 mysql_free_result(pres);
467 }
468 }
469
470 return lState;
471}
472
473
474/**
475 * Updates function information.
476 * @returns number of errors.
477 * @param pFnDesc
478 * @param pszError
479 * @result on error(s) pszError will hold information about the error(s).
480 */
481unsigned long _System dbUpdateFunction(PFNDESC pFnDesc, char *pszError)
482{
483 char szQuery[256];
484 char *pszQuery = &szQuery[0];
485 long lCurrentState;
486 int i,k,rc;
487 unsigned long ulRc = 0;
488 BOOL f = FALSE;
489
490 for (k = 0; k < pFnDesc->cRefCodes; k++)
491 {
492 /* set updated flag */
493 sprintf(pszQuery, "UPDATE function SET updated = updated + 1 WHERE refcode = %d",
494 pFnDesc->alRefCode[k]);
495 rc = mysql_query(pmysql, &szQuery[0]);
496
497 /* get current status */
498 lCurrentState = dbGetFunctionState(pFnDesc->alRefCode[k]);
499 if (lCurrentState == -1)
500 {
501 strcpy(pszError, dbGetLastErrorDesc());
502 return 1;
503 }
504
505 /* update function table first */
506 strcpy(pszQuery, "UPDATE function SET ");
507 pszQuery += strlen(pszQuery);
508 if (pFnDesc->lStatus != 99 || lCurrentState == 0)
509 {
510 sprintf(pszQuery, "state = %ld ", pFnDesc->lStatus);
511 f = TRUE;
512 }
513 pszQuery += strlen(pszQuery);
514
515 if (pFnDesc->pszReturnType != NULL)
516 {
517 if (f)
518 {
519 strcat(pszQuery, ", ");
520 pszQuery += strlen(pszQuery);
521 }
522 sprintf(pszQuery, "return = '%s' ", pFnDesc->pszReturnType);
523 pszQuery += strlen(pszQuery);
524 f = TRUE;
525 }
526
527 if (f)
528 {
529 sprintf(pszQuery, "WHERE refcode = %ld", pFnDesc->alRefCode[k]);
530 rc = mysql_query(pmysql, &szQuery[0]);
531 if (rc < 0)
532 {
533 sprintf(pszError, "Updating functiontable failed with error: %s - (sql=%s) ",
534 dbGetLastErrorDesc(), &szQuery[0]);
535 pszError += strlen(pszError) - 1;
536 ulRc++;
537 }
538 }
539
540 /* parameters */
541 pszQuery = &szQuery[0];
542 sprintf(pszQuery, "DELETE FROM parameter WHERE function = %ld", pFnDesc->alRefCode[k]);
543 rc = mysql_query(pmysql, &szQuery[0]);
544 if (rc < 0)
545 {
546 if (*pszError == ' ')
547 strcpy(pszError++, "\n\t");
548 sprintf(pszError, "Deleting old parameters failed with error: %s - (sql=%s) ",
549 dbGetLastErrorDesc(), &szQuery[0]);
550 pszError += strlen(pszError) - 1;
551 ulRc++;
552 }
553
554 for (i = 0; i < pFnDesc->cParams; i++)
555 {
556 sprintf(pszQuery, "INSERT INTO parameter(function, sequencenbr, type, name) "
557 "VALUES (%ld, %d, '%s', '%s')",
558 pFnDesc->alRefCode[k], i,
559 pFnDesc->apszParamType[i] != NULL ? pFnDesc->apszParamType[i] : "",
560 pFnDesc->apszParamName[i] != NULL ? pFnDesc->apszParamName[i] : ""
561 );
562 rc = mysql_query(pmysql, pszQuery);
563 if (rc < 0)
564 {
565 if (*pszError == ' ')
566 strcpy(pszError++, "\n\t");
567 sprintf(pszError, "Inserting parameter %i failed with error: %s - (sql=%s) ",
568 i, dbGetLastErrorDesc(), &szQuery[0]);
569 pszError += strlen(pszError) - 1;
570 ulRc++;
571 }
572 }
573
574 /* authors */
575 pszQuery = &szQuery[0];
576 sprintf(pszQuery, "DELETE FROM fnauthor WHERE function = %ld", pFnDesc->alRefCode[k]);
577 rc = mysql_query(pmysql, &szQuery[0]);
578 if (rc < 0)
579 {
580 if (*pszError == ' ')
581 strcpy(pszError++, "\n\t");
582 sprintf(pszError, "Deleting old authors failed with error: %s - (sql=%s) ",
583 dbGetLastErrorDesc(), &szQuery[0]);
584 pszError += strlen(pszError) - 1;
585 ulRc++;
586 }
587
588 for (i = 0; i < pFnDesc->cAuthors; i++)
589 {
590 if (pFnDesc->alAuthorRefCode[i] == -1)
591 continue;
592 sprintf(pszQuery, "INSERT INTO fnauthor(author, function) "
593 "VALUES (%ld, %ld)",
594 pFnDesc->alAuthorRefCode[i], pFnDesc->alRefCode[k]);
595 rc = mysql_query(pmysql, pszQuery);
596 if (rc < 0)
597 {
598 if (*pszError == ' ')
599 strcpy(pszError++, "\n\t");
600 sprintf(pszError, "Inserting parameter %i failed with error: %s - (sql=%s) ",
601 i, dbGetLastErrorDesc(), &szQuery[0]);
602 pszError += strlen(pszError) - 1;
603 ulRc++;
604 }
605 }
606 } /* for */
607 return ulRc;
608}
609
610
611/**
612 * Updates the history tables.
613 * @returns Number of signals/errors.
614 * @param pszError Pointer to buffer which will hold the error messages.
615 * @remark This should be called whenever updates have been completed.
616 */
617unsigned long _System dbCreateHistory(char *pszError)
618{
619 unsigned long ulRc = 0;
620 MYSQL_RES *pres;
621 MYSQL_ROW row;
622 char szQuery[256];
623 char *pszQuery = &szQuery[0];
624 int rc;
625 char szCurDt[20] = {0}; /*yyyy-mm-dd\0*/
626
627 mysql_refresh(pmysql, REFRESH_TABLES);
628
629 /* get currentdate - just in case the date changes between the delete and the update is completed. */
630 strcpy(pszQuery, "SELECT CURDATE()");
631 rc = mysql_query(pmysql, pszQuery);
632 pres = mysql_use_result(pmysql);
633 if (rc >= 0 && pres != NULL)
634 {
635 row = mysql_fetch_row(pres);
636 if (row != NULL && mysql_num_rows(pres) == 1)
637 {
638 strcpy(&szCurDt[0], row[0]);
639 while (mysql_fetch_row(pres) != NULL)
640 pres=pres;
641
642 /* delete - all rows on this date in the history tables */
643 sprintf(pszQuery, "DELETE FROM historydll WHERE date = '%s'", &szCurDt[0]);
644 rc = mysql_query(pmysql, pszQuery);
645 CheckLogContinue((pszError, "error removing old history rows: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
646
647 sprintf(pszQuery, "DELETE FROM historyapigroup WHERE date = '%s'", &szCurDt[0]);
648 rc = mysql_query(pmysql, pszQuery);
649 CheckLogContinue((pszError, "error removing old history rows: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
650
651 sprintf(pszQuery, "DELETE FROM historydlltotal WHERE date = '%s'", &szCurDt[0]);
652 rc = mysql_query(pmysql, pszQuery);
653 CheckLogContinue((pszError, "error removing old history rows: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
654
655 sprintf(pszQuery, "DELETE FROM historyapigrouptotal WHERE date = '%s'", &szCurDt[0]);
656 CheckLogContinue((pszError, "error removing old history rows: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
657
658 /* insert new stats */
659 sprintf(pszQuery, "INSERT INTO historydll(dll, state, date, count) "
660 "SELECT dll, state, '%s', count(*) FROM function GROUP BY dll, state",
661 &szCurDt[0]);
662 rc = mysql_query(pmysql, pszQuery);
663 CheckLogContinue((pszError, "error inserting: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
664
665 sprintf(pszQuery, "INSERT INTO historyapigroup(apigroup, state, date, count) "
666 "SELECT dll, state, '%s', count(*) FROM function WHERE apigroup IS NOT NULL "
667 "GROUP BY apigroup, state",
668 &szCurDt[0]);
669 rc = mysql_query(pmysql, pszQuery);
670 CheckLogContinue((pszError, "error inserting: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
671
672 /* inserting new totals */
673 sprintf(pszQuery, "INSERT INTO historydlltotal(dll, date, totalcount) "
674 "SELECT dll, '%s', count(*) FROM function GROUP BY dll",
675 &szCurDt[0]);
676 rc = mysql_query(pmysql, pszQuery);
677 CheckLogContinue((pszError, "error inserting: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
678
679 sprintf(pszQuery, "INSERT INTO historyapigrouptotal(apigroup, date, totalcount) "
680 "SELECT apigroup, '%s', count(*) FROM function WHERE apigroup IS NOT NULL "
681 "GROUP BY apigroup",
682 &szCurDt[0]);
683 rc = mysql_query(pmysql, pszQuery);
684 CheckLogContinue((pszError, "error inserting: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
685 }
686 else
687 {
688 sprintf(pszError, "error getting current date (row == NULL): %s - (sql=%s) ",
689 dbGetLastErrorDesc(), pszQuery);
690 ulRc++;
691 }
692 }
693 else
694 {
695 sprintf(pszError, "error getting current date: %s - (sql=%s) ",
696 dbGetLastErrorDesc(), pszQuery);
697 ulRc++;
698 }
699
700 mysql_refresh(pmysql, REFRESH_TABLES);
701
702 return ulRc;
703}
704
705
706/**
707 * Check that database integrety is ok. Verfies foreign keys.
708 * @returns numbers of errors.
709 * @param pszError Very large buffer which will hold error messges (if any).
710 * @sketch
711 * @remark current versions of mysql don't support 'SELECT ... WHERE id NOT IN(SELECT id FROM table)'
712 */
713unsigned long _System dbCheckIntegrity(char *pszError)
714{
715 char szQuery[384];
716 char *pszQuery = &szQuery[0];
717 MYSQL_RES *pres1;
718 MYSQL_RES *pres2;
719 MYSQL_ROW row1;
720 int rc;
721 unsigned long ulRc = 0;
722
723 mysql_refresh(pmysql, REFRESH_TABLES);
724
725 /* foreign keys in function table */
726 strcpy(pszQuery, "SELECT refcode, dll, state, apigroup FROM function");
727 rc = mysql_query(pmysql, pszQuery);
728 if (rc >= 0)
729 {
730 pres1 = mysql_store_result(pmysql);
731 if (pres1 != NULL)
732 {
733 while ((row1 = mysql_fetch_row(pres1)) != NULL)
734 {
735 /* check dll */
736 sprintf(pszQuery, "SELECT name FROM dll WHERE refcode = %s", row1[1]);
737 rc = mysql_query(pmysql, pszQuery);
738 CheckFKError("function/dll", "Foreign key 'dll' not found in the dll table");
739
740 /* check state */
741 sprintf(pszQuery, "SELECT name FROM state WHERE refcode = %s", row1[2]);
742 rc = mysql_query(pmysql, pszQuery);
743 CheckFKError("function/state", "Foreign key 'state' not found in the state table");
744
745 /* check apigroup */
746 if (row1[3] != NULL)
747 {
748 sprintf(pszQuery, "SELECT name FROM apigroup WHERE refcode = %s", row1[3]);
749 rc = mysql_query(pmysql, pszQuery);
750 CheckFKError("function/state", "Foreign key 'state' not found in the state table");
751 }
752 }
753 mysql_free_result(pres1);
754 }
755 }
756 else
757 ulRc += logDbError(pszError, pszQuery);
758
759 /* foreign keys in apigroup */
760 strcpy(pszQuery, "SELECT refcode, dll FROM apigroup");
761 rc = mysql_query(pmysql, pszQuery);
762 if (rc >= 0)
763 {
764 pres1 = mysql_store_result(pmysql);
765 if (pres1 != NULL)
766 {
767 while ((row1 = mysql_fetch_row(pres1)) != NULL)
768 {
769 /* check dll */
770 sprintf(pszQuery, "SELECT refcode FROM dll WHERE refcode = %s", row1[1]);
771 rc = mysql_query(pmysql, pszQuery);
772 CheckFKError("apigroup/dll", "Foreign key 'dll' not found in the dll table");
773 }
774 mysql_free_result(pres1);
775 }
776 }
777 else
778 ulRc += logDbError(pszError, pszQuery);
779
780 /* foreign keys in fnauthor */
781 strcpy(pszQuery, "SELECT function, author FROM fnauthor");
782 rc = mysql_query(pmysql, pszQuery);
783 if (rc >= 0)
784 {
785 pres1 = mysql_store_result(pmysql);
786 if (pres1 != NULL)
787 {
788 while ((row1 = mysql_fetch_row(pres1)) != NULL)
789 {
790 /* check function */
791 sprintf(pszQuery, "SELECT refcode FROM function WHERE refcode = %s", row1[1]);
792 rc = mysql_query(pmysql, pszQuery);
793 CheckFKError("fnauthor/function", "Foreign key 'function' not found in the function table");
794
795 /* check author */
796 sprintf(pszQuery, "SELECT refcode FROM author WHERE refcode = %s", row1[1]);
797 rc = mysql_query(pmysql, pszQuery);
798 CheckFKError("fnauthor/author", "Foreign key 'author' not found in the author table");
799 }
800 mysql_free_result(pres1);
801 }
802 }
803 else
804 ulRc += logDbError(pszError, pszQuery);
805
806 /* foreign keys in historydll table */
807 strcpy(pszQuery, "SELECT date, dll, state FROM historydll");
808 rc = mysql_query(pmysql, pszQuery);
809 if (rc >= 0)
810 {
811 pres1 = mysql_store_result(pmysql);
812 if (pres1 != NULL)
813 {
814 while ((row1 = mysql_fetch_row(pres1)) != NULL)
815 {
816 /* check dll */
817 sprintf(pszQuery, "SELECT refcode FROM dll WHERE refcode = %s", row1[1]);
818 rc = mysql_query(pmysql, pszQuery);
819 CheckFKError("historydll/dll", "Foreign key 'dll' not found in the dll table");
820
821 /* check state */
822 sprintf(pszQuery, "SELECT refcode FROM state WHERE refcode = %s", row1[2]);
823 rc = mysql_query(pmysql, pszQuery);
824 CheckFKError("historydll/state", "Foreign key 'state' not found in the state table");
825 }
826 mysql_free_result(pres1);
827 }
828 }
829 else
830 ulRc += logDbError(pszError, pszQuery);
831
832 /* foreign keys in historyapigroup table */
833 strcpy(pszQuery, "SELECT date, apigroup, state FROM historyapigroup");
834 rc = mysql_query(pmysql, pszQuery);
835 if (rc >= 0)
836 {
837 pres1 = mysql_store_result(pmysql);
838 if (pres1 != NULL)
839 {
840 while ((row1 = mysql_fetch_row(pres1)) != NULL)
841 {
842 /* check dll */
843 sprintf(pszQuery, "SELECT refcode FROM apigroup WHERE refcode = %s", row1[1]);
844 rc = mysql_query(pmysql, pszQuery);
845 CheckFKError("historyapigroup/apigroup", "Foreign key 'apigroup' not found in the apigroup table");
846
847 /* check state */
848 sprintf(pszQuery, "SELECT refcode FROM state WHERE refcode = %s", row1[2]);
849 rc = mysql_query(pmysql, pszQuery);
850 CheckFKError("historyapigroup/state", "Foreign key 'state' not found in the state table");
851 }
852 mysql_free_result(pres1);
853 }
854 }
855 else
856 ulRc += logDbError(pszError, pszQuery);
857
858 /* foreign keys in historydlltotal table */
859 strcpy(pszQuery, "SELECT date, dll FROM historydlltotal");
860 rc = mysql_query(pmysql, pszQuery);
861 if (rc >= 0)
862 {
863 pres1 = mysql_store_result(pmysql);
864 if (pres1 != NULL)
865 {
866 while ((row1 = mysql_fetch_row(pres1)) != NULL)
867 {
868 /* check dll */
869 sprintf(pszQuery, "SELECT refcode FROM dll WHERE refcode = %s", row1[1]);
870 rc = mysql_query(pmysql, pszQuery);
871 CheckFKError("historydlltotal/dll", "Foreign key 'dll' not found in the dll table");
872 }
873 mysql_free_result(pres1);
874 }
875 }
876 else
877 ulRc += logDbError(pszError, pszQuery);
878
879 /* foreign keys in historyapigroup table */
880 strcpy(pszQuery, "SELECT date, apigroup FROM historyapigrouptotal");
881 rc = mysql_query(pmysql, pszQuery);
882 if (rc >= 0)
883 {
884 pres1 = mysql_store_result(pmysql);
885 if (pres1 != NULL)
886 {
887 while ((row1 = mysql_fetch_row(pres1)) != NULL)
888 {
889 /* check dll */
890 sprintf(pszQuery, "SELECT refcode FROM apigroup WHERE refcode = %s", row1[1]);
891 rc = mysql_query(pmysql, pszQuery);
892 CheckFKError("historyapigrouptotal/apigroup", "Foreign key 'apigroup' not found in the apigroup table");
893 }
894 mysql_free_result(pres1);
895 }
896 }
897 else
898 ulRc += logDbError(pszError, pszQuery);
899
900 /* foreign keys in parameter table */
901 strcpy(pszQuery, "SELECT sequencenbr, function FROM parameter");
902 rc = mysql_query(pmysql, pszQuery);
903 if (rc >= 0)
904 {
905 pres1 = mysql_store_result(pmysql);
906 if (pres1 != NULL)
907 {
908 while ((row1 = mysql_fetch_row(pres1)) != NULL)
909 {
910 /* check function */
911 sprintf(pszQuery, "SELECT refcode FROM function WHERE refcode = %s", row1[1]);
912 rc = mysql_query(pmysql, pszQuery);
913 CheckFKError("parameter/function", "Foreign key 'function' not found in the function table");
914 }
915 mysql_free_result(pres1);
916 }
917 }
918 else
919 ulRc += logDbError(pszError, pszQuery);
920
921 /* Author table is special, since you should be able to interchangably reference an
922 * author by any of the following tables:
923 * name
924 * initials
925 * alias
926 * email
927 */
928 strcpy(pszQuery, "SELECT name, initials, alias, email FROM author");
929 rc = mysql_query(pmysql, pszQuery);
930 if (rc >= 0)
931 {
932 pres1 = mysql_store_result(pmysql);
933 if (pres1 != NULL)
934 {
935 while ((row1 = mysql_fetch_row(pres1)) != NULL)
936 {
937 /* check name */
938 sprintf(pszQuery, "SELECT name FROM author WHERE "
939 "initials = '%s' OR alias = '%s' OR email = '%s'",
940 row1[0], row1[0], row1[0]);
941 ulRc += CheckAuthorError(pszError, "name", row1[0], pszQuery);
942
943 /* check initials */
944 sprintf(pszQuery, "SELECT name FROM author WHERE "
945 "alias = '%s' OR email = '%s'",
946 row1[1], row1[1]);
947 ulRc += CheckAuthorError(pszError, "initials", row1[1], pszQuery);
948
949 /* alias */
950 if (row1[2] != NULL)
951 {
952 sprintf(pszQuery, "SELECT name FROM author WHERE "
953 "email = '%s'",
954 row1[2]);
955 ulRc += CheckAuthorError(pszError, "alias", row1[2], pszQuery);
956 }
957 }
958 mysql_free_result(pres1);
959 }
960 }
961 else
962 ulRc += logDbError(pszError, pszQuery);
963
964 return ulRc;
965}
966
967
968/**
969 * Checks for duplicate key and sql error for a given author key in the author table... (arg!)
970 * @returns Number of errors.
971 * @param pszError Reference to error buffer pointer.
972 * @param pszFieldName Key field name; used for logging.
973 * @param pszFieldValue Key value; used for logging
974 * @param pszQuery Query which is to be exectued to test for duplicate key.
975 * @remark Uses pszError[1] == '\xFE' to detect when to insert '\n\t'.
976 */
977static unsigned long CheckAuthorError(char * &pszError, const char *pszFieldName, const char *pszFieldValue, const char *pszQuery)
978{
979 MYSQL_ROW row;
980 MYSQL_RES *pres;
981 unsigned long ulRc = 0;
982 int rc;
983
984 rc = mysql_query(pmysql, pszQuery);
985 pres = mysql_store_result(pmysql);
986 if (rc < 0 || (pres != NULL && mysql_num_rows(pres) != 0))
987 { /* some kind of error has occurred */
988 if (pszError[1] == '\xFE')
989 {
990 strcat(pszError, "\n\t");
991 pszError += 2;
992 }
993
994 if (rc < 0) /* sql error or 'duplicate key' */
995 {
996 sprintf(pszError, "author/%s: select failed - %s (sql=%s)",
997 pszFieldName, dbGetLastErrorDesc(), pszQuery);
998 }
999 else
1000 { /* 'duplicate key' - print duplicates */
1001 sprintf(pszError, "author/%s: 'duplicate key', %s='%s': ",
1002 pszFieldName, pszFieldValue, pszFieldName);
1003
1004 while ((row = mysql_fetch_row(pres)) != NULL)
1005 {
1006 pszError += strlen(pszError);
1007 sprintf(pszError, "'%s' ", row[0]);
1008 }
1009 }
1010
1011 pszError += strlen(pszError);
1012 pszError[1] = '\xFE';
1013 ulRc = 1;
1014 }
1015 if (pres != NULL)
1016 mysql_free_result(pres);
1017
1018 return ulRc;
1019}
1020
1021
1022/**
1023 * Writes db error (rc<0) to the log buffer.
1024 * @returns Number of signals.
1025 * @param pszError Reference to the error buffer pointer.
1026 * @param pszQuery Pointer to query which was executed.
1027 * @remark Uses pszError[1] == '\xFE' to detect when to insert '\n\t'.
1028 */
1029static unsigned long logDbError(char * &pszError, const char *pszQuery)
1030{
1031 if (pszError[1] == '\xFE')
1032 {
1033 strcat(pszError, "\n\t");
1034 pszError += 2;
1035 }
1036 sprintf(pszError, "select failed: %s - (sql=%s)", dbGetLastErrorDesc(), pszQuery);
1037
1038 pszError += strlen(pszError);
1039 pszError[1] = '\xFE';
1040
1041 return 1;
1042}
1043
1044
1045/**
1046 * Executes a give query and returns a result identifier/pointer.
1047 * @returns Query result identifier/pointer. NULL on error.
1048 * @param pszQuery Pointer to query.
1049 * @remark Used by and designed for kHtmlPC.
1050 */
1051void * _System dbExecuteQuery(const char *pszQuery)
1052{
1053 assert(pmysql != NULL);
1054 if (mysql_query(pmysql, pszQuery) >= 0)
1055 return mysql_store_result(pmysql);
1056
1057 return NULL;
1058}
1059
1060
1061/**
1062 * Asks for the number of rows in the result.
1063 * @returns Number of rows in the result. -1 on error.
1064 * @param pres Query result identifier/pointer.
1065 * @remark Used by and designed for kHtmlPC.
1066 */
1067signed long _System dbQueryResultRows(void *pres)
1068{
1069 if (pres == NULL)
1070 return -1;
1071 return mysql_num_rows((MYSQL_RES*)pres);
1072}
1073
1074
1075/**
1076 * Frees the storage allocated by the given result.
1077 * @returns Success indicator, TRUE/FALSE.
1078 * @param pres Query result identifier/pointer.
1079 * @remark Used by and designed for kHtmlPC.
1080 */
1081BOOL _System dbFreeResult(void *pres)
1082{
1083 if (pres != NULL)
1084 mysql_free_result((MYSQL_RES*)pres);
1085 else
1086 return FALSE;
1087 return TRUE;
1088}
1089
1090
1091/**
1092 * Fetch data from a result. Returns the data by calling the given callback function.
1093 * @returns Success indicator, TRUE/FALSE.
1094 * @param pres Query result identifier/pointer.
1095 * @param dbFetchCallBack Callback-function.
1096 * @param pvUser User parameter which is passed onto dbFetchCallBack.
1097 * @remark Used by and designed for kHtmlPC.
1098 */
1099BOOL _System dbFetch(void *pres, DBCALLBACKFETCH dbFetchCallBack, void *pvUser)
1100{
1101 BOOL fRc = FALSE;
1102 MYSQL_ROW row = mysql_fetch_row((MYSQL_RES*)pres);
1103
1104 if (row)
1105 {
1106 MYSQL_FIELD *pField;
1107 int i = 0;
1108 mysql_field_seek((MYSQL_RES*)pres, 0);
1109
1110 while ((pField = mysql_fetch_field((MYSQL_RES*)pres)) != NULL)
1111 if (dbFetchCallBack(row[i++], pField->name, pvUser) != 0)
1112 return FALSE;
1113
1114 fRc = TRUE;
1115 }
1116
1117 return fRc;
1118}
1119
1120
1121/**
1122 * Converts an ISO date to days after Christ, year 0.
1123 * @returns days. -1 on error;
1124 * @param pszDate ISO Date.
1125 */
1126signed long _System dbDateToDaysAfterChrist(const char *pszDate)
1127{
1128 signed long lRet = -1;
1129 char szQuery[128];
1130
1131 sprintf(&szQuery[0], "SELECT to_days('%s')", pszDate);
1132 if (mysql_query(pmysql, &szQuery[0]) >= 0)
1133 {
1134 MYSQL_ROW row;
1135 MYSQL_RES *pres = mysql_use_result(pmysql);
1136 row = mysql_fetch_row(pres);
1137 if (row != NULL)
1138 {
1139 lRet = atol(row[0]);
1140 do { row = mysql_fetch_row(pres); } while (row != NULL);
1141 }
1142 }
1143
1144 return lRet;
1145}
1146
1147
1148/**
1149 * Converts days after Christ (year 0) to ISO date.
1150 * @returns Success indicator. TRUE/FALSE;
1151 * @param lDays Days after Christ (year 0).
1152 * @param pszDate ISO Date. Result.
1153 */
1154BOOL _System dbDaysAfterChristToDate(signed long lDays, char *pszDate)
1155{
1156 BOOL fRet = FALSE;
1157 char szQuery[128];
1158
1159 if (lDays < 0)
1160 return FALSE;
1161
1162 sprintf(&szQuery[0], "SELECT from_days(%ld)", lDays);
1163 if (mysql_query(pmysql, &szQuery[0]) >= 0)
1164 {
1165 MYSQL_ROW row;
1166 MYSQL_RES *pres = mysql_use_result(pmysql);
1167 row = mysql_fetch_row(pres);
1168 if (row != NULL)
1169 {
1170 fRet = strlen(row[0]) == (4+1+2+1+2) && row[0][4] == '-' && row[0][7] == '-'
1171 && strcmp(row[0], "0000-00-00") != 0;
1172 if (fRet)
1173 strcpy(pszDate, row[0]);
1174 do { row = mysql_fetch_row(pres); } while (row != NULL);
1175 }
1176 }
1177
1178 return fRet;
1179}
1180
1181
1182/**
1183 * Display all functions for, the given dll, that is not updated.
1184 * @returns TRUE / FALSE.
1185 * @param lDll Dll reference number.
1186 * @param dbFetchCall Callback function which will be called once for each
1187 * field for all the functions not updated.
1188 * pvUser is NULL, pszValue field value, pszFieldName the field name.
1189 */
1190BOOL _System dbGetNotUpdatedFunction(signed long lDll, DBCALLBACKFETCH dbFetchCallBack)
1191{
1192 BOOL fRet = FALSE;
1193 void *pres;
1194 char szQuery[128];
1195
1196 /* not updated names */
1197 sprintf(&szQuery[0], "SELECT name, intname FROM function WHERE dll = %d AND updated = 0",
1198 lDll);
1199 pres = dbExecuteQuery(szQuery);
1200 if (pres != NULL)
1201 {
1202 BOOL f;
1203 do
1204 {
1205 f = dbFetch(pres, dbFetchCallBack, NULL);
1206 } while (f);
1207 dbFreeResult(pres);
1208 fRet = TRUE;
1209 }
1210
1211 /* warn about updated > 1 too */
1212 sprintf(&szQuery[0], "SELECT updated, name, intname FROM function WHERE dll = %d AND updated > 1",
1213 lDll);
1214 pres = dbExecuteQuery(szQuery);
1215 if (pres != NULL)
1216 {
1217 BOOL f;
1218 do
1219 {
1220 f = dbFetch(pres, dbFetchCallBack, NULL);
1221 } while (f);
1222 dbFreeResult(pres);
1223 fRet = TRUE;
1224 }
1225
1226 sprintf(&szQuery[0], "UPDATE function SET updated = 0",
1227 lDll);
1228 mysql_query(pmysql, &szQuery[0]);
1229
1230 return fRet;
1231}
1232
1233
1234#ifdef NOTDLL
1235/**
1236 * Signal handler.
1237 * Ensures that the database connection is closed at termination.
1238 * @param sig Signal number.
1239 */
1240void dbHandler(int sig)
1241{
1242 if (pmysql != NULL)
1243 {
1244 fprintf(stderr, "\n\t!disconnecting from database!\n");
1245 dbDisconnect();
1246 }
1247
1248 flushall();
1249 switch (sig)
1250 {
1251 case SIGBREAK:
1252 printf("\nSIGBREAK\n");
1253 exit(-1);
1254 break;
1255 case SIGINT:
1256 printf("\nSIGINT\n");
1257 exit(-1);
1258 break;
1259 case SIGTERM:
1260 printf("\nSIGTERM\n");
1261 exit(-1);
1262 break;
1263 case SIGSEGV:
1264 raise(sig);
1265 break;
1266 case SIGILL:
1267 printf("\nSIGILL\n");
1268 exit(-1);
1269 break;
1270 }
1271}
1272
1273
1274#else
1275/*******/
1276/* DLL */
1277/*******/
1278/* prototypes used in the _DLL_InitTerm function */
1279extern "C"
1280{
1281 int _CRT_init(void);
1282 void _CRT_term(void);
1283 void __ctordtorInit( void );
1284 void __ctordtorTerm( void );
1285 unsigned long _System _DLL_InitTerm(unsigned long hModule, unsigned long ulFlag);
1286}
1287
1288
1289/**
1290 * Dll InitTerm function.
1291 * @returns 0 on success.
1292 * 1 on error.
1293 * @param hModule
1294 * @param ulFlags
1295 * @remark We'll ensure that the database connection is terminated as we terminate.
1296 */
1297unsigned long _System _DLL_InitTerm(unsigned long hModule, unsigned long ulFlag)
1298{
1299 /*-------------------------------------------------------------------------*/
1300 /* If ulFlag is zero then the DLL is being loaded so initialization should */
1301 /* be performed. If ulFlag is 1 then the DLL is being freed so */
1302 /* termination should be performed. */
1303 /*-------------------------------------------------------------------------*/
1304
1305 switch (ulFlag)
1306 {
1307 case 0:
1308 if (_CRT_init() == -1)
1309 return 0;
1310 __ctordtorInit();
1311 break;
1312
1313 case 1:
1314 /* ensure that db connection is terminated */
1315 if (pmysql != NULL)
1316 {
1317 fprintf(stderr, "\n\t!disconnecting from database!\n");
1318 dbDisconnect();
1319 }
1320 __ctordtorTerm();
1321 break;
1322
1323 default:
1324 return 0;
1325 }
1326 hModule = hModule;
1327 return 1;
1328}
1329
1330/*****************************************************************/
1331/* -why is this terminate function referenced but not defined??? */
1332/* and where is it referenced??? */
1333/* -Probably an export missing from the libraries. */
1334/*****************************************************************/
1335void terminate(void)
1336{
1337 DosPutMessage(0, sizeof("terminate")-1, "terminate");
1338 exit(-1);
1339}
1340
1341/****************************************/
1342/* EMX run-time trouble */
1343/* _environ is missing when using -Zomf */
1344/****************************************/
1345char **_environ = environ;
1346
1347#endif
Note: See TracBrowser for help on using the repository browser.