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

Last change on this file since 6677 was 6677, checked in by bird, 24 years ago

dll to module conversion.

File size: 79.1 KB
Line 
1/* $Id: db.cpp,v 1.26 2001-09-07 10:24:07 bird Exp $ *
2 *
3 * DB - contains all database routines.
4 *
5 * Copyright (c) 1999-2000 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 mod name.
157 * @returns Module refid. -1 on error.
158 * @param pszModName Module name.
159 */
160signed long _System dbGetModule(const char *pszModName)
161{
162 int rc;
163 char szQuery[256];
164 MYSQL_RES * pres;
165
166 sprintf(&szQuery[0], "SELECT refcode FROM module WHERE name = '%s'\n", pszModName);
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 (signed long)rc;
176}
177
178
179/**
180 * Count the function in a given module.
181 * @returns Number of functions. -1 on error.
182 * @param lModule Module refcode.
183 * @param fNotAliases TRUE: don't count aliased functions.
184 */
185signed long _System dbCountFunctionInModule(signed long lModule, BOOL fNotAliases)
186{
187 signed long rc;
188 char szQuery[256];
189 MYSQL_RES * pres;
190
191 if (lModule >= 0)
192 {
193 sprintf(&szQuery[0], "SELECT count(refcode) FROM function WHERE module = %ld\n", lModule);
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 module exists. If not exists the module is inserted.
214 * @returns Module refcode. -1 on errors.
215 * @param pszModule Module name.
216 * @param fchType Module type.
217 * @remark This search must be case insensitive.
218 * (In the mysql-world everything is case insensitive!)
219 */
220signed long _System dbCheckInsertModule(const char *pszModule, char fchType)
221{
222 int rc;
223 char szQuery[256];
224 MYSQL_RES * pres;
225
226 /* try find match */
227 sprintf(&szQuery[0], "SELECT refcode, name FROM module WHERE name = '%s'\n", pszModule);
228 rc = mysql_query(pmysql, &szQuery[0]);
229 pres = mysql_store_result(pmysql);
230
231 /* not found? - insert module */
232 if (rc < 0 || pres == NULL || mysql_num_rows(pres) == 0)
233 {
234 mysql_free_result(pres);
235
236 sprintf(&szQuery[0], "INSERT INTO module(name, type) VALUES('%s', '%c')\n", pszModule, fchType);
237 rc = mysql_query(pmysql, &szQuery[0]);
238 if (rc < 0)
239 return -1;
240
241 /* select row to get refcode */
242 sprintf(&szQuery[0], "SELECT refcode, name FROM module WHERE name = '%s'\n", pszModule);
243 rc = mysql_query(pmysql, &szQuery[0]);
244 pres = mysql_store_result(pmysql);
245 }
246
247 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) == 1)
248 rc = (int)getvalue(0, mysql_fetch_row(pres));
249 else
250 rc = -1;
251 mysql_free_result(pres);
252
253 return (long)rc;
254}
255
256
257/**
258 * Simple select for a long value.
259 * @returns long value
260 * @param pszTable From part.
261 * @param pszGetColumn Name of column to retreive.
262 * @param pszMatch1 Match column/expression
263 * @param pszMatchValue1 Match value.
264 * @remark Dirty! Don't use this!
265 */
266unsigned short _System dbGet(const char *pszTable, const char *pszGetColumn,
267 const char *pszMatch1, const char *pszMatchValue1)
268{
269 int rc;
270 char szQuery[256];
271 MYSQL_RES *pres;
272
273 /* try find match */
274 sprintf(&szQuery[0], "SELECT %s FROM %s WHERE %s = '%s'\n",
275 pszGetColumn, pszTable, pszMatch1, pszMatchValue1);
276 rc = mysql_query(pmysql, &szQuery[0]);
277 pres = mysql_store_result(pmysql);
278
279 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) == 1)
280 rc = (int)getvalue(0, mysql_fetch_row(pres));
281 else
282 rc = -1;
283 mysql_free_result(pres);
284
285 return (unsigned short)rc;
286}
287
288
289/**
290 * Updates or inserts a function name into the database.
291 * The update flags is always updated.
292 * @returns Success indicator. TRUE / FALSE.
293 * @param lModule Module refcode.
294 * @param pszFunction Function name.
295 * @param pszIntFunction Internal function name. (required!)
296 * @param ulOrdinal Ordinal value.
297 * @param fIgnoreOrdinal Do not update ordinal value.
298 * @param fchType Function type flag. One of the FUNCTION_* defines.
299 */
300BOOL _System dbInsertUpdateFunction(signed long lModule,
301 const char *pszFunction, const char *pszIntFunction,
302 unsigned long ulOrdinal, BOOL fIgnoreOrdinal, char fchType)
303{
304 int rc;
305 long lFunction = -1;
306 char szQuery[512];
307 char * pszQuery = &szQuery[0];
308 MYSQL_RES *pres;
309
310 /* when no internal name fail! */
311 if (pszIntFunction == NULL || *pszIntFunction == '\0')
312 return FALSE;
313
314 /* try find function */
315 sprintf(pszQuery, "SELECT refcode, intname FROM function WHERE module = %d AND name = '%s'", lModule, pszFunction);
316 rc = mysql_query(pmysql, pszQuery);
317 pres = mysql_store_result(pmysql);
318 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) != 0)
319 { /*
320 * Found the function. So now we'll update it.
321 */
322 MYSQL_ROW parow;
323 if (mysql_num_rows(pres) > 1)
324 {
325 fprintf(stderr, "internal database integrity error(%s): More function by the same name for the same module. "
326 "lModule = %d, pszFunction = %s\n", __FUNCTION__, lModule, pszFunction);
327 return FALSE;
328 }
329
330 parow = mysql_fetch_row(pres);
331 lFunction = getvalue(0, parow);
332 mysql_free_result(pres);
333
334 strcpy(pszQuery, "UPDATE function SET updated = updated + 1");
335 pszQuery += strlen(pszQuery);
336 if (strcmp(parow[1], pszIntFunction) != 0)
337 pszQuery += sprintf(pszQuery, ", intname = '%s'", pszIntFunction);
338
339 if (!fIgnoreOrdinal)
340 pszQuery += sprintf(pszQuery, ", ordinal = %ld", ulOrdinal);
341
342 sprintf(pszQuery, ", type = '%c' WHERE refcode = %ld", fchType, lFunction);
343 rc = mysql_query(pmysql, &szQuery[0]);
344 }
345 else
346 { /*
347 * The function was not found. (or maybe an error occured?)
348 * Insert it.
349 */
350 sprintf(&szQuery[0], "INSERT INTO function(module, name, intname, ordinal, updated, type) VALUES(%d, '%s', '%s', %ld, 1, '%c')",
351 lModule, pszFunction, pszIntFunction, ulOrdinal, fchType);
352 rc = mysql_query(pmysql, &szQuery[0]);
353 }
354
355 return rc >= 0;
356}
357
358
359
360/**
361 * Inserts or updates (existing) file information.
362 * @returns Success indicator (TRUE / FALSE).
363 * @param lModule Module reference code.
364 * @param pszFilename Filename.
365 * @param pszDescription Pointer to file description.
366 * @param pszLastDateTime Date and time for last change (ISO).
367 * @param lLastAuthor Author number. (-1 if not found.)
368 * @param pszRevision Pointer to revision string.
369 * @sketch
370 * @remark
371 */
372BOOL _System dbInsertUpdateFile(signed long lModule,
373 const char *pszFilename,
374 const char *pszDescription,
375 const char *pszLastDateTime,
376 signed long lLastAuthor,
377 const char *pszRevision)
378{
379 int rc;
380 long lFile = -1;
381 char szQuery[0x10000];
382 MYSQL_RES *pres;
383
384 /* parameter assertions */
385 assert(lModule != 0);
386 assert(pszFilename != NULL);
387 assert(*pszFilename != '\0');
388
389 /* try find file */
390 sprintf(&szQuery[0], "SELECT refcode, name FROM file WHERE module = %d AND name = '%s'", lModule, pszFilename);
391 rc = mysql_query(pmysql, &szQuery[0]);
392 pres = mysql_store_result(pmysql);
393 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) != 0)
394 { /* update file (file is found) */
395 MYSQL_ROW parow;
396 if (mysql_num_rows(pres) > 1)
397 {
398 fprintf(stderr, "internal database integrity error(%s): More files by the same name in the same module. "
399 "lModule = %d, pszFilename = %s\n", __FUNCTION__, lModule, pszFilename);
400 return FALSE;
401 }
402
403 parow = mysql_fetch_row(pres);
404 assert(parow);
405 lFile = getvalue(0, parow);
406 mysql_free_result(pres);
407
408 if (strcmp(parow[1], pszFilename) != 0) /* case might have changed... */
409 {
410 sprintf(&szQuery[0], "UPDATE file SET name = '%s' WHERE refcode = %ld",
411 pszFilename, lFile);
412 rc = mysql_query(pmysql, &szQuery[0]);
413 }
414
415 if (rc >= 0)
416 {
417 if (pszDescription != NULL && pszDescription != '\0')
418 {
419 szQuery[0] = '\0';
420 sqlstrcat(&szQuery[0], "UPDATE file SET description = ", pszDescription, NULL);
421 sprintf(&szQuery[strlen(szQuery)], " WHERE refcode = %ld", lFile);
422 }
423 else
424 sprintf(&szQuery[0], "UPDATE file SET description = NULL WHERE refcode = %ld",
425 lFile);
426 rc = mysql_query(pmysql, &szQuery[0]);
427 }
428
429 if (rc >= 0 && pszLastDateTime != NULL && *pszLastDateTime != '\0')
430 {
431 sprintf(&szQuery[0], "UPDATE file SET lastdatetime = '%s' WHERE refcode = %ld",
432 pszLastDateTime, lFile);
433 rc = mysql_query(pmysql, &szQuery[0]);
434 }
435
436 if (rc >= 0)
437 {
438 sprintf(&szQuery[0], "UPDATE file SET lastauthor = %ld WHERE refcode = %ld",
439 lLastAuthor, lFile);
440 rc = mysql_query(pmysql, &szQuery[0]);
441 }
442
443 if (rc >= 0 && pszRevision != NULL && *pszRevision != '\0')
444 {
445 sprintf(&szQuery[0], "UPDATE file SET revision = '%s' WHERE refcode = %ld",
446 pszRevision, lFile);
447 rc = mysql_query(pmysql, &szQuery[0]);
448 }
449
450 }
451 else
452 { /* insert */
453 sprintf(&szQuery[0], "INSERT INTO file(module, name, lastauthor, description, lastdatetime, revision) VALUES(%d, '%s', %ld, ",
454 lModule, pszFilename, lLastAuthor);
455 if (pszDescription != NULL && *pszDescription != '\0')
456 sqlstrcat(&szQuery[0], NULL, pszDescription);
457 else
458 strcat(&szQuery[0], "NULL");
459
460 if (pszLastDateTime != NULL && *pszLastDateTime != '\0')
461 sqlstrcat(&szQuery[0], ", ", pszLastDateTime);
462 else
463 strcat(&szQuery[0], ", '1975-03-13 14:00:00'"); /* dummy */
464
465 if (pszRevision != NULL && *pszRevision != '\0')
466 sqlstrcat(&szQuery[0], ", ", pszRevision, ")");
467 else
468 strcat(&szQuery[0], ", '')");
469
470 rc = mysql_query(pmysql, &szQuery[0]);
471 }
472
473 return rc >= 0;
474}
475
476
477/**
478 * Get a long value.
479 * @returns Number value of pRow[iField]. -1 on error.
480 * @param iField Index into pRow.
481 * @param pRow Pointer to array (of string pointers).
482 */
483static long getvalue(int iField, MYSQL_ROW papszRow)
484{
485 if (papszRow[iField] != NULL)
486 return atol((char*)papszRow[iField]);
487
488 return -1;
489}
490
491
492#if 0
493/*
494 * Stubs used while optimizing sqls.
495 */
496int mysql_query1(MYSQL *mysql, const char *q)
497{ return mysql_query(mysql, q); }
498int mysql_query2(MYSQL *mysql, const char *q)
499{ return mysql_query(mysql, q); }
500int mysql_query3(MYSQL *mysql, const char *q)
501{ return mysql_query(mysql, q); }
502int mysql_query4(MYSQL *mysql, const char *q)
503{ return mysql_query(mysql, q); }
504int mysql_query5(MYSQL *mysql, const char *q)
505{ return mysql_query(mysql, q); }
506int mysql_query6(MYSQL *mysql, const char *q)
507{ return mysql_query(mysql, q); }
508
509#else
510
511#define mysql_query1 mysql_query
512#define mysql_query2 mysql_query
513#define mysql_query3 mysql_query
514#define mysql_query4 mysql_query
515#define mysql_query5 mysql_query
516#define mysql_query6 mysql_query
517
518#endif
519
520
521
522/**
523 * Find occurences of a function, given by internal name.
524 * @returns success indicator, TRUE / FALSE.
525 * @param pszFunctionName Pointer to a function name string. (input)
526 * @param pFnFindBuf Pointer to a find buffer. (output)
527 * @param lModule Module refcode (optional). If given the search is limited to
528 * the given module and aliasing functions is updated (slow!).
529 * @sketch 1) Get functions for this module(if given).
530 * 2) Get functions which aliases the functions found in (1).
531 * 3) Get new aliases by intname
532 * 4) Get new aliases by name
533 * 5) Update all functions from (1) to have aliasfn -2 (DONTMIND)
534 * 6) Update all functions from (3) and (4) to alias the first function from 1.
535 */
536BOOL _System dbFindFunction(const char *pszFunctionName, PFNFINDBUF pFnFindBuf, signed long lModule)
537{
538 MYSQL_RES *pres;
539 MYSQL_ROW row;
540 int rc;
541 char szQuery[1024];
542
543 /*
544 * 1) Get functions for this module(if given).
545 */
546 if (lModule < 0)
547 sprintf(&szQuery[0], "SELECT refcode, module, aliasfn, file, name, type FROM function WHERE intname = '%s'",
548 pszFunctionName);
549 else
550 sprintf(&szQuery[0], "SELECT refcode, module, aliasfn, file, name, type FROM function "
551 "WHERE intname = '%s' AND module = %ld",
552 pszFunctionName, lModule);
553
554 rc = mysql_query1(pmysql, &szQuery[0]);
555 if (rc >= 0)
556 {
557 pres = mysql_store_result(pmysql);
558 if (pres != NULL)
559 {
560 char szFnName[NBR_FUNCTIONS][80];
561 BOOL fAPI = FALSE;
562
563 pFnFindBuf->cFns = 0;
564 while ((row = mysql_fetch_row(pres)) != NULL)
565 {
566 pFnFindBuf->alRefCode[pFnFindBuf->cFns] = atol(row[0]);
567 pFnFindBuf->alModRefCode[pFnFindBuf->cFns] = atol(row[1]);
568 pFnFindBuf->alAliasFn[pFnFindBuf->cFns] = atol(row[2]);
569 pFnFindBuf->alFileRefCode[pFnFindBuf->cFns] = atol(row[3]);
570 strcpy(szFnName[pFnFindBuf->cFns], row[4]);
571 pFnFindBuf->achType[pFnFindBuf->cFns] = *row[5];
572 if (pFnFindBuf->achType[pFnFindBuf->cFns] == FUNCTION_ODIN32_API ||
573 pFnFindBuf->achType[pFnFindBuf->cFns] == FUNCTION_INTERNAL_ODIN32_API)
574 fAPI = TRUE;
575
576 /* next */
577 pFnFindBuf->cFns++;
578 }
579 mysql_free_result(pres);
580
581 /* alias check and fix for apis. */
582 if (fAPI && lModule >= 0 && pFnFindBuf->cFns != 0)
583 {
584 int cFnsThisModule, cFnsAliasesAndThisModule, i, f;
585
586 /*
587 * 2) Get functions which aliases the functions found in (1).
588 */
589 cFnsThisModule = (int)pFnFindBuf->cFns;
590 strcpy(&szQuery[0], "SELECT refcode, module, aliasfn, file, name FROM function WHERE aliasfn IN (");
591 for (i = 0; i < cFnsThisModule; i++)
592 {
593 if (i > 0) strcat(&szQuery[0], " OR ");
594 sprintf(&szQuery[strlen(szQuery)], "(%ld)", pFnFindBuf->alRefCode[i]);
595 }
596 strcat(&szQuery[0], ")");
597
598 rc = mysql_query2(pmysql, &szQuery[0]);
599 if (rc >= 0)
600 {
601 pres = mysql_store_result(pmysql);
602 if (pres != NULL)
603 {
604 while ((row = mysql_fetch_row(pres)) != NULL)
605 {
606 pFnFindBuf->alRefCode[pFnFindBuf->cFns] = atol(row[0]);
607 pFnFindBuf->alModRefCode[pFnFindBuf->cFns] = atol(row[1]);
608 pFnFindBuf->alAliasFn[pFnFindBuf->cFns] = atol(row[2]);
609 pFnFindBuf->alFileRefCode[pFnFindBuf->cFns] = atol(row[3]);
610 strcpy(szFnName[pFnFindBuf->cFns], row[4]);
611
612 /* next */
613 pFnFindBuf->cFns++;
614 }
615 mysql_free_result(pres);
616
617 /*
618 * 3) Get new aliases by intname
619 */
620 cFnsAliasesAndThisModule = (int)pFnFindBuf->cFns;
621 sprintf(&szQuery[0], "SELECT refcode, module, aliasfn, file FROM function "
622 "WHERE aliasfn = (-1) AND module <> %ld AND (intname = '%s'",
623 lModule, pszFunctionName);
624 for (i = 0; i < cFnsAliasesAndThisModule; i++)
625 sprintf(&szQuery[strlen(&szQuery[0])], " OR intname = '%s'", szFnName[i]);
626 strcat(&szQuery[0], ")");
627
628 rc = mysql_query3(pmysql, &szQuery[0]);
629 if (rc >= 0)
630 {
631 pres = mysql_store_result(pmysql);
632 if (pres != NULL)
633 {
634 while ((row = mysql_fetch_row(pres)) != NULL)
635 {
636 pFnFindBuf->alRefCode[pFnFindBuf->cFns] = atol(row[0]);
637 pFnFindBuf->alModRefCode[pFnFindBuf->cFns] = atol(row[1]);
638 if (row[2] != NULL)
639 pFnFindBuf->alAliasFn[pFnFindBuf->cFns] = atol(row[2]);
640 else
641 pFnFindBuf->alAliasFn[pFnFindBuf->cFns] = ALIAS_NULL;
642 pFnFindBuf->alFileRefCode[pFnFindBuf->cFns] = atol(row[3]);
643
644 /* next */
645 pFnFindBuf->cFns++;
646 }
647 mysql_free_result(pres);
648
649
650 /*
651 * 4) Get new aliases by name
652 */
653 sprintf(&szQuery[0], "SELECT refcode, module, aliasfn, file FROM function "
654 "WHERE aliasfn = (-1) AND module <> %ld AND (name = '%s'",
655 lModule, pszFunctionName);
656 for (i = 0; i < cFnsAliasesAndThisModule; i++)
657 sprintf(&szQuery[strlen(&szQuery[0])], " OR name = '%s'", szFnName[i]);
658 strcat(&szQuery[0], ")");
659
660 rc = mysql_query4(pmysql, &szQuery[0]);
661 if (rc >= 0)
662 {
663 pres = mysql_store_result(pmysql);
664 if (pres != NULL)
665 {
666 while ((row = mysql_fetch_row(pres)) != NULL)
667 {
668 pFnFindBuf->alRefCode[pFnFindBuf->cFns] = atol(row[0]);
669 pFnFindBuf->alModRefCode[pFnFindBuf->cFns] = atol(row[1]);
670 if (row[2] != NULL)
671 pFnFindBuf->alAliasFn[pFnFindBuf->cFns] = atol(row[2]);
672 else
673 pFnFindBuf->alAliasFn[pFnFindBuf->cFns] = ALIAS_NULL;
674 pFnFindBuf->alFileRefCode[pFnFindBuf->cFns] = atol(row[3]);
675
676 /* next */
677 pFnFindBuf->cFns++;
678 }
679 mysql_free_result(pres);
680
681 /*
682 * 5) Update all functions from (1) to have aliasfn -2 (DONTMIND)
683 */
684 sprintf(&szQuery[0], "UPDATE function SET aliasfn = (-2) "
685 "WHERE refcode IN (",
686 lModule, pszFunctionName);
687 for (f = 0, i = 0; i < cFnsThisModule; i++)
688 if (pFnFindBuf->alAliasFn[i] != ALIAS_DONTMIND)
689 sprintf(&szQuery[strlen(&szQuery[0])],
690 f++ != 0 ? ", %ld" : "%ld", pFnFindBuf->alRefCode[i]);
691 strcat(&szQuery[0], ") AND aliasfn <> (-2)");
692 if (f > 0)
693 rc = mysql_query5(pmysql, &szQuery[0]);
694 else
695 rc = 0;
696 if (rc >= 0 && cFnsAliasesAndThisModule < pFnFindBuf->cFns)
697 {
698 /*
699 * 6) Update all functions from (3) and (4) to alias the first function from 1.
700 */
701 sprintf(&szQuery[0], "UPDATE function SET aliasfn = (%ld), file = (%ld) "
702 "WHERE aliasfn = (-1) AND refcode IN (",
703 pFnFindBuf->alRefCode[0], pFnFindBuf->alFileRefCode[0]);
704 for (i = cFnsAliasesAndThisModule; i < pFnFindBuf->cFns; i++)
705 {
706 sprintf(&szQuery[strlen(&szQuery[0])],
707 i > cFnsAliasesAndThisModule ? ", %ld" : "%ld", pFnFindBuf->alRefCode[i]);
708 }
709 strcat(&szQuery[0], ")");
710 rc = mysql_query6(pmysql, &szQuery[0]);
711 } /* query 5 */
712 }
713 } /* query 4 */
714 }
715 } /* query 3 */
716 }
717 } /* query 2 */
718 }
719 } /* query 1 */
720 else
721 rc = -1;
722 }
723
724 return rc >= 0;
725}
726
727
728/**
729 * Finds the refcode for a file (if it exists).
730 * @returns File 'refcode'.
731 * -1 on error or not found.
732 * @param lModule Refcode of the module which this file belongs to.
733 * @param pszFilename The filename to search for.
734 */
735signed long _System dbFindFile(signed long lModule, const char *pszFilename)
736{
737 char szQuery[256];
738 MYSQL_RES * pres;
739 signed long lRefCode = -1;
740
741 assert(lModule >= 0);
742 assert(pszFilename != NULL);
743 assert(*pszFilename != '\0');
744
745 sprintf(&szQuery[0], "SELECT refcode FROM file WHERE module = %ld AND name = '%s'",
746 lModule, pszFilename);
747 if (mysql_query(pmysql, &szQuery[0]) >= 0)
748 {
749 pres = mysql_store_result(pmysql);
750 if (pres != NULL)
751 {
752 MYSQL_ROW parow = mysql_fetch_row(pres);
753 if (parow != NULL)
754 lRefCode = getvalue(0, parow);
755 mysql_free_result(pres);
756 }
757 }
758
759 return lRefCode;
760}
761
762
763/**
764 * Finds the refcode for an author, if the author exists.
765 * @returns Author 'refcode'.
766 * @param pszAuthor String which holds the identifier of an author.
767 * This doesn't have to be the name. Initials, alias and email
768 * is also searched.
769 * @param pszEmail Email address. Might be NULL!
770 */
771signed long _System dbFindAuthor(const char *pszAuthor, const char *pszEmail)
772{
773 signed long refcode = -1;
774 MYSQL_RES *pres;
775 char szQuery[512];
776
777 /*
778 * parameter validations
779 */
780 if (pszAuthor == NULL || strlen(pszAuthor) > 64)
781 return -1;
782 if (pszEmail != NULL && strlen(pszEmail) > 64)
783 {
784 fprintf(stderr, "email too long!");
785 return -1;
786 }
787
788 /*
789 * Query
790 */
791 sprintf(&szQuery[0],
792 "SELECT refcode FROM author "
793 "WHERE name = '%s' OR "
794 " initials = '%s' OR "
795 " alias = '%s' OR "
796 " email = '%s'",
797 pszAuthor, pszAuthor, pszAuthor, pszAuthor);
798
799 if (pszEmail != NULL)
800 sprintf(&szQuery[strlen(&szQuery[0])], " OR email = '%s'", pszEmail);
801
802 if (mysql_query(pmysql, &szQuery[0]) >= 0)
803 {
804 pres = mysql_store_result(pmysql);
805 if (pres != NULL)
806 {
807 MYSQL_ROW parow;
808
809 /* integrety check */
810 if (mysql_num_rows(pres) > 1)
811 fprintf(stderr, "Integrety: author '%s' is not unique!\n", pszAuthor);
812 parow = mysql_fetch_row(pres);
813 if (parow != NULL)
814 refcode = getvalue(0, parow);
815
816 mysql_free_result(pres);
817 }
818 }
819
820 return refcode;
821}
822
823
824/**
825 * Gets the state of a function.
826 * @returns state code. On error -1.
827 * @param lRefCode Function refcode.
828 */
829signed long _System dbGetFunctionState(signed long lRefCode)
830{
831 signed long lState = -1;
832 MYSQL_RES *pres;
833 char szQuery[128];
834
835 sprintf(&szQuery[0], "SELECT state FROM function WHERE refcode = %ld", lRefCode);
836 if (mysql_query(pmysql, &szQuery[0]) >= 0)
837 {
838 pres = mysql_store_result(pmysql);
839 if (pres != NULL)
840 {
841 MYSQL_ROW parow = mysql_fetch_row(pres);
842 if (parow != NULL)
843 lState = getvalue(0, parow);
844 mysql_free_result(pres);
845 }
846 }
847
848 return lState;
849}
850
851#if 1
852/*
853 * Stubs used while optimizing sqls.
854 */
855int mysql_queryu1(MYSQL *mysql, const char *q)
856{ return mysql_query(mysql, q); }
857int mysql_queryu2(MYSQL *mysql, const char *q)
858{ return mysql_query(mysql, q); }
859int mysql_queryu3(MYSQL *mysql, const char *q)
860{ return mysql_query(mysql, q); }
861int mysql_queryu4(MYSQL *mysql, const char *q)
862{ return mysql_query(mysql, q); }
863int mysql_queryu5(MYSQL *mysql, const char *q)
864{ return mysql_query(mysql, q); }
865int mysql_queryu6(MYSQL *mysql, const char *q)
866{ return mysql_query(mysql, q); }
867int mysql_queryu7(MYSQL *mysql, const char *q)
868{ return mysql_query(mysql, q); }
869int mysql_queryu8(MYSQL *mysql, const char *q)
870{ return mysql_query(mysql, q); }
871#else
872#define mysql_queryu1 mysql_query
873#define mysql_queryu2 mysql_query
874#define mysql_queryu3 mysql_query
875#define mysql_queryu4 mysql_query
876#define mysql_queryu5 mysql_query
877#define mysql_queryu6 mysql_query
878#define mysql_queryu7 mysql_query
879#define mysql_queryu8 mysql_query
880#endif
881
882/**
883 * Updates function information.
884 * @returns number of errors.
885 * @param pFnDesc Function description struct.
886 * @param lModule Module which we are working at.
887 * @param pszError Buffer for error messages
888 * @result on error(s) pszError will hold information about the error(s).
889 */
890unsigned long _System dbUpdateFunction(PFNDESC pFnDesc, signed long lModule, char *pszError)
891{
892 MYSQL_RES * pres;
893 MYSQL_ROW row;
894 char * pszQuery2 = (char*)malloc(65500);
895 char * pszQuery = pszQuery2;
896 long lCurrentState;
897 int i,k,rc;
898 unsigned long ulRc = 0;
899
900 /* check if malloc have failed allocating memory for us. */
901 if (pszQuery2 == NULL)
902 {
903 strcpy(pszError, "internal dbUpdateFunction error - malloc failed!\n");
904 return 1;
905 }
906
907
908 /*
909 * Loop thru all functions in the array of refocodes.
910 */
911 for (k = 0; k < pFnDesc->cRefCodes; k++)
912 {
913 /*
914 * Get current status
915 */
916 lCurrentState = dbGetFunctionState(pFnDesc->alRefCode[k]);
917 if (lCurrentState == -1 && dbGetLastErrorDesc() != NULL && strlen(dbGetLastErrorDesc()) != 0)
918 {
919 strcpy(pszError, dbGetLastErrorDesc());
920 /*
921 * Set updated flag
922 */
923 sprintf(pszQuery, "UPDATE function SET updated = updated + 1 WHERE refcode = %ld",
924 pFnDesc->alRefCode[k]);
925 rc = mysql_queryu1(pmysql, pszQuery2);
926 free(pszQuery2);
927 return 1;
928 }
929
930
931 /*
932 * Update function table first
933 */
934 strcpy(pszQuery, "UPDATE function SET updated = updated + 1");
935 pszQuery += strlen(pszQuery);
936
937 /* Status */
938 if (lCurrentState != pFnDesc->lStatus
939 && pFnDesc->lStatus != 0
940 && (lCurrentState == 0 || pFnDesc->lStatus != 99)
941 )
942 pszQuery += sprintf(pszQuery, ", state = %ld", pFnDesc->lStatus);
943
944 /* File */
945 if (pFnDesc->lFile >= 0)
946 pszQuery += sprintf(pszQuery, ", file = %ld", pFnDesc->lFile);
947 else
948 pszQuery += sprintf(pszQuery, ", file = -1");
949
950 /* Line */
951 if (pFnDesc->lLine >= 0)
952 pszQuery += sprintf(pszQuery, ", line = %ld", pFnDesc->lLine);
953 else
954 pszQuery += sprintf(pszQuery, ", line = -1");
955
956 /* return type */
957 if (pFnDesc->pszReturnType != NULL)
958 pszQuery = sqlstrcat(pszQuery, ", return = ", pFnDesc->pszReturnType);
959 else
960 pszQuery += sprintf(pszQuery, ", return = NULL");
961
962 /* Description */
963 if (pFnDesc->pszDescription != NULL)
964 pszQuery = sqlstrcat(pszQuery, ", description = ", pFnDesc->pszDescription);
965 else
966 pszQuery += sprintf(pszQuery, ", description = NULL");
967
968 /* Remark */
969 if (pFnDesc->pszRemark != NULL)
970 pszQuery = sqlstrcat(pszQuery, ", remark = ", pFnDesc->pszRemark);
971 else
972 pszQuery += sprintf(pszQuery, ", remark = NULL");
973
974 /* Description */
975 if (pFnDesc->pszReturnDesc != NULL)
976 pszQuery = sqlstrcat(pszQuery, ", returndesc = ", pFnDesc->pszReturnDesc);
977 else
978 pszQuery += sprintf(pszQuery, ", returndesc = NULL");
979
980 /* Sketch */
981 if (pFnDesc->pszSketch != NULL)
982 pszQuery = sqlstrcat(pszQuery, ", sketch = ", pFnDesc->pszSketch);
983 else
984 pszQuery += sprintf(pszQuery, ", sketch = NULL");
985
986 /* Equiv */
987 if (pFnDesc->pszEquiv != NULL)
988 pszQuery = sqlstrcat(pszQuery, ", equiv = ", pFnDesc->pszEquiv);
989 else
990 pszQuery += sprintf(pszQuery, ", equiv = NULL");
991
992 /* Time */
993 if (pFnDesc->pszTime != NULL)
994 pszQuery = sqlstrcat(pszQuery, ", time = ", pFnDesc->pszTime);
995 else
996 pszQuery += sprintf(pszQuery, ", time = NULL");
997
998 /* Execute update query? */
999 sprintf(pszQuery + strlen(pszQuery), " WHERE refcode = %ld", pFnDesc->alRefCode[k]);
1000 rc = mysql_queryu2(pmysql, pszQuery2);
1001 if (rc < 0)
1002 {
1003 sprintf(pszError, "Updating functiontable failed with error: %s - (sql=%s) ",
1004 dbGetLastErrorDesc(), pszQuery2);
1005 pszError += strlen(pszError) - 1;
1006 ulRc++;
1007 }
1008
1009
1010 /*
1011 * Parameters
1012 */
1013 pszQuery = pszQuery2;
1014 sprintf(pszQuery, "SELECT count(*) FROM parameter WHERE function = %ld", pFnDesc->alRefCode[k]);
1015 rc = mysql_queryu3(pmysql, pszQuery);
1016 if (rc >= 0)
1017 {
1018 pres = mysql_store_result(pmysql);
1019 if (pres != NULL)
1020 row = mysql_fetch_row(pres);
1021 if (pres != NULL && row != NULL && mysql_num_rows(pres) == 1)
1022 {
1023 #if 0 /* keep getting duplicate keys when parameter order/names are changed. */
1024 if (atol(row[0]) == pFnDesc->cParams)
1025 { /* update parameters */
1026 for (i = 0; i < pFnDesc->cParams; i++)
1027 {
1028 sprintf(pszQuery, "UPDATE parameter SET type = '%s', name = '%s'",
1029 pFnDesc->apszParamType[i] != NULL ? pFnDesc->apszParamType[i] : "",
1030 pFnDesc->apszParamName[i] != NULL ? pFnDesc->apszParamName[i] : "");
1031 if (pFnDesc->apszParamDesc[i] != NULL)
1032 sqlstrcat(pszQuery, ", description = ", pFnDesc->apszParamDesc[i]);
1033 sprintf(pszQuery + strlen(pszQuery), " WHERE function = (%ld) AND sequencenbr = (%ld)",
1034 pFnDesc->alRefCode[k], i);
1035 rc = mysql_queryu4(pmysql, pszQuery);
1036 if (rc < 0)
1037 {
1038 if (*pszError == ' ')
1039 strcpy(pszError++, "\n\t");
1040 sprintf(pszError, "Updating parameter %i failed with error: %s - (sql=%s) ",
1041 i, dbGetLastErrorDesc(), pszQuery);
1042 pszError += strlen(pszError) - 1;
1043 ulRc++;
1044 }
1045 }
1046 }
1047 else
1048 #endif
1049 {
1050 if (atol(row[0]) != 0)
1051 { /* delete old parameters */
1052 sprintf(pszQuery, "DELETE FROM parameter WHERE function = %ld", pFnDesc->alRefCode[k]);
1053 rc = mysql_queryu5(pmysql, pszQuery);
1054 if (rc < 0)
1055 {
1056 if (*pszError == ' ')
1057 strcpy(pszError++, "\n\t");
1058 sprintf(pszError, "Deleting old parameters failed with error: %s - (sql=%s) ",
1059 dbGetLastErrorDesc(), pszQuery);
1060 pszError += strlen(pszError) - 1;
1061 ulRc++;
1062 }
1063 }
1064
1065 /* insert parameters */
1066 for (i = 0; i < pFnDesc->cParams; i++)
1067 {
1068 sprintf(pszQuery, "INSERT INTO parameter(function, sequencenbr, type, name, description) "
1069 "VALUES (%ld, %d, '%s', '%s'",
1070 pFnDesc->alRefCode[k], i,
1071 pFnDesc->apszParamType[i] != NULL ? pFnDesc->apszParamType[i] : "",
1072 pFnDesc->apszParamName[i] != NULL ? pFnDesc->apszParamName[i] : ""
1073 );
1074 if (pFnDesc->apszParamDesc[i] != NULL)
1075 sqlstrcat(pszQuery, ", ", pFnDesc->apszParamDesc[i], ")");
1076 else
1077 strcat(pszQuery, ", NULL)");
1078
1079 rc = mysql_queryu6(pmysql, pszQuery2);
1080 if (rc < 0)
1081 {
1082 if (*pszError == ' ')
1083 strcpy(pszError++, "\n\t");
1084 sprintf(pszError, "Inserting parameter %i failed with error: %s - (sql=%s) ",
1085 i, dbGetLastErrorDesc(), pszQuery);
1086 pszError += strlen(pszError) - 1;
1087 ulRc++;
1088 }
1089 }
1090 }
1091 }
1092 else
1093 {
1094 if (*pszError == ' ')
1095 strcpy(pszError++, "\n\t");
1096 sprintf(pszError, "failed to store result or to fetch a row , error: %s - (sql=%s) ",
1097 dbGetLastErrorDesc(), pszQuery);
1098 pszError += strlen(pszError) - 1;
1099 ulRc++;
1100 }
1101 }
1102 else
1103 {
1104 if (*pszError == ' ')
1105 strcpy(pszError++, "\n\t");
1106 sprintf(pszError, "Failed querying number of parameters, error: %s - (sql=%s) ",
1107 dbGetLastErrorDesc(), pszQuery);
1108 pszError += strlen(pszError) - 1;
1109 ulRc++;
1110 }
1111
1112
1113 /*
1114 * Authors
1115 */
1116 sprintf(pszQuery, "DELETE FROM fnauthor WHERE function = %ld", pFnDesc->alRefCode[k]);
1117 rc = mysql_queryu7(pmysql, pszQuery);
1118 if (rc < 0)
1119 {
1120 if (*pszError == ' ')
1121 strcpy(pszError++, "\n\t");
1122 sprintf(pszError, "Deleting old authors failed with error: %s - (sql=%s) ",
1123 dbGetLastErrorDesc(), pszQuery);
1124 pszError += strlen(pszError) - 1;
1125 ulRc++;
1126 }
1127
1128 for (i = 0; i < pFnDesc->cAuthors; i++)
1129 {
1130 if (pFnDesc->alAuthorRefCode[i] == -1)
1131 continue;
1132 sprintf(pszQuery, "INSERT INTO fnauthor(author, function) "
1133 "VALUES (%ld, %ld)",
1134 pFnDesc->alAuthorRefCode[i], pFnDesc->alRefCode[k]);
1135 rc = mysql_queryu8(pmysql, pszQuery);
1136 if (rc < 0)
1137 {
1138 if (*pszError == ' ')
1139 strcpy(pszError++, "\n\t");
1140 sprintf(pszError, "Inserting parameter %i failed with error: %s - (sql=%s) ",
1141 i, dbGetLastErrorDesc(), pszQuery);
1142 pszError += strlen(pszError) - 1;
1143 ulRc++;
1144 }
1145 }
1146 } /* for */
1147
1148 lModule = lModule;
1149 free(pszQuery2);
1150 return ulRc;
1151}
1152
1153
1154/**
1155 * Removes all the existing design notes in the specified file.
1156 * @returns Success indicator.
1157 * @param lFile File refcode of the file to remove all design notes for.
1158 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
1159 */
1160BOOL _System dbRemoveDesignNotes(signed long lFile)
1161{
1162 char szQuery[80];
1163
1164 assert(lFile >= 0);
1165 sprintf(&szQuery[0], "DELETE FROM designnote WHERE file = %ld", lFile);
1166 return mysql_query(pmysql, &szQuery[0]) >= 0;
1167}
1168
1169
1170/**
1171 * Adds a design note.
1172 * @returns Success indicator.
1173 * @param lModule Module refcode.
1174 * @param lFile File refcode.
1175 * @param pszTitle Design note title.
1176 * @param pszText Design note text.
1177 * @param lLevel Level of the note section. 0 is the design note it self.
1178 * @param lSeqNbr Sequence number (in module). If 0 the use next available number.
1179 * @param lSeqNbrNote Sequence number in note.
1180 * @param lLine Line number (1 - based!).
1181 * @param fSubSection TRUE if subsection FALSE if design note.
1182 * if TRUE *plRefCode will hold the reference id of the note.
1183 * if FALSE *plRefCode will receive the reference id of the note being created.
1184 * @param plRefCode Pointer to reference id of the design note. see fSubSection for more info.
1185 */
1186BOOL _System dbAddDesignNote(signed long lModule,
1187 signed long lFile,
1188 const char *pszTitle,
1189 const char *pszText,
1190 signed long lLevel,
1191 signed long lSeqNbr,
1192 signed long lSeqNbrNote,
1193 signed long lLine,
1194 BOOL fSubSection,
1195 signed long *plRefCode)
1196{
1197 int rc;
1198 char szQuery[0x10200];
1199 MYSQL_RES * pres;
1200
1201
1202 assert(lModule >= 0 && lFile >= 0);
1203 assert(lSeqNbrNote >= 0);
1204
1205 /*
1206 * If no lSqlNbr the make one.
1207 */
1208 if (lSeqNbr == 0 && !fSubSection)
1209 {
1210 sprintf(&szQuery[0], "SELECT MAX(seqnbr) + 1 FROM designnote WHERE module = %ld AND level = 0", lModule);
1211 if (mysql_query(pmysql, &szQuery[0]) >= 0)
1212 {
1213 pres = mysql_store_result(pmysql);
1214 if (pres != NULL)
1215 {
1216 MYSQL_ROW parow = mysql_fetch_row(pres);
1217 if (parow != NULL && parow[0])
1218 lSeqNbr = getvalue(0, parow);
1219 else
1220 lSeqNbr = 1;
1221 mysql_free_result(pres);
1222 }
1223 else
1224 return FALSE;
1225 }
1226 else
1227 return FALSE;
1228 }
1229
1230 /*
1231 * Create insert query.
1232 */
1233 if (!fSubSection)
1234 sprintf(&szQuery[0], "INSERT INTO designnote(module, file, level, seqnbrnote, seqnbr, line, name, note) "
1235 "VALUES (%ld, %ld, %ld, %ld, %ld, %ld, ",
1236 lModule, lFile, lLevel, lSeqNbrNote, lSeqNbr, lLine);
1237 else
1238 sprintf(&szQuery[0], "INSERT INTO designnote(refcode, module, file, level, seqnbrnote, seqnbr, line, name, note) "
1239 "VALUES (%ld, %ld, %ld, %ld, %ld, %ld, %ld, ",
1240 *plRefCode, lModule, lFile, lLevel, lSeqNbrNote, lSeqNbr, lLine);
1241
1242 if (pszTitle != NULL && *pszTitle != '\0')
1243 sqlstrcat(&szQuery[0], NULL, pszTitle);
1244 else
1245 strcat(&szQuery[0], "NULL");
1246 sqlstrcat(&szQuery[0], ", ", pszText == NULL ? "" : pszText, ")");
1247
1248 if (mysql_query(pmysql, &szQuery[0]) >= 0)
1249 {
1250 if (!fSubSection)
1251 *plRefCode = mysql_insert_id(pmysql);
1252 return TRUE;
1253 }
1254 return FALSE;
1255}
1256
1257
1258
1259/**
1260 * Updates the history tables.
1261 * @returns Number of signals/errors.
1262 * @param pszError Pointer to buffer which will hold the error messages.
1263 * @remark This should be called whenever updates have been completed.
1264 */
1265unsigned long _System dbCreateHistory(char *pszError)
1266{
1267 unsigned long ulRc = 0;
1268 MYSQL_RES *pres;
1269 MYSQL_ROW row;
1270 char szQuery[256];
1271 char *pszQuery = &szQuery[0];
1272 int rc;
1273 char szCurDt[20] = {0}; /*yyyy-mm-dd\0*/
1274
1275 mysql_refresh(pmysql, REFRESH_TABLES);
1276
1277 /* get currentdate - just in case the date changes between the delete and the update is completed. */
1278 strcpy(pszQuery, "SELECT CURDATE()");
1279 rc = mysql_query(pmysql, pszQuery);
1280 pres = mysql_use_result(pmysql);
1281 if (rc >= 0 && pres != NULL)
1282 {
1283 row = mysql_fetch_row(pres);
1284 if (row != NULL && mysql_num_rows(pres) == 1)
1285 {
1286 strcpy(&szCurDt[0], row[0]);
1287 while (mysql_fetch_row(pres) != NULL)
1288 pres=pres;
1289
1290 /* delete - all rows on this date in the history tables */
1291 sprintf(pszQuery, "DELETE FROM historymodule WHERE date = '%s'", &szCurDt[0]);
1292 rc = mysql_query(pmysql, pszQuery);
1293 CheckLogContinue((pszError, "error removing old history rows: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1294
1295 sprintf(pszQuery, "DELETE FROM historyapigroup WHERE date = '%s'", &szCurDt[0]);
1296 rc = mysql_query(pmysql, pszQuery);
1297 CheckLogContinue((pszError, "error removing old history rows: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1298
1299 sprintf(pszQuery, "DELETE FROM historymoduletotal WHERE date = '%s'", &szCurDt[0]);
1300 rc = mysql_query(pmysql, pszQuery);
1301 CheckLogContinue((pszError, "error removing old history rows: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1302
1303 sprintf(pszQuery, "DELETE FROM historyapigrouptotal WHERE date = '%s'", &szCurDt[0]);
1304 CheckLogContinue((pszError, "error removing old history rows: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1305
1306 /* insert new stats */
1307 sprintf(pszQuery, "INSERT INTO historymodule(module, state, date, count, type) "
1308 "SELECT module, state, '%s', count(*), type FROM function GROUP BY module, state, type",
1309 &szCurDt[0]);
1310 rc = mysql_query(pmysql, pszQuery);
1311 CheckLogContinue((pszError, "error inserting: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1312
1313 sprintf(pszQuery, "INSERT INTO historyapigroup(apigroup, state, date, count) "
1314 "SELECT apigroup, state, '%s', count(*) FROM function WHERE apigroup IS NOT NULL "
1315 "GROUP BY apigroup, state",
1316 &szCurDt[0]);
1317 rc = mysql_query(pmysql, pszQuery);
1318 CheckLogContinue((pszError, "error inserting: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1319
1320 /* inserting new totals */
1321 sprintf(pszQuery, "INSERT INTO historymoduletotal(module, date, totalcount, type) "
1322 "SELECT module, '%s', count(*), type FROM function GROUP BY module, type",
1323 &szCurDt[0]);
1324 rc = mysql_query(pmysql, pszQuery);
1325 CheckLogContinue((pszError, "error inserting: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1326
1327 sprintf(pszQuery, "INSERT INTO historyapigrouptotal(apigroup, date, totalcount) "
1328 "SELECT apigroup, '%s', count(*) FROM function WHERE apigroup IS NOT NULL AND type = 'A' "
1329 "GROUP BY apigroup",
1330 &szCurDt[0]);
1331 rc = mysql_query(pmysql, pszQuery);
1332 CheckLogContinue((pszError, "error inserting: %s - (sql=%s) ", dbGetLastErrorDesc(), pszQuery));
1333 }
1334 else
1335 {
1336 sprintf(pszError, "error getting current date (row == NULL): %s - (sql=%s) ",
1337 dbGetLastErrorDesc(), pszQuery);
1338 ulRc++;
1339 }
1340 }
1341 else
1342 {
1343 sprintf(pszError, "error getting current date: %s - (sql=%s) ",
1344 dbGetLastErrorDesc(), pszQuery);
1345 ulRc++;
1346 }
1347
1348 mysql_refresh(pmysql, REFRESH_TABLES);
1349
1350 return ulRc;
1351}
1352
1353
1354/**
1355 * Check that database integrety is ok. Verfies foreign keys.
1356 * @returns numbers of errors.
1357 * @param pszError Very large buffer which will hold error messges (if any).
1358 * @sketch
1359 * @remark current versions of mysql don't support 'SELECT ... WHERE id NOT IN(SELECT id FROM table)'
1360 */
1361unsigned long _System dbCheckIntegrity(char *pszError)
1362{
1363 char szQuery[384];
1364 char *pszQuery = &szQuery[0];
1365 MYSQL_RES *pres1;
1366 MYSQL_RES *pres2;
1367 MYSQL_ROW row1;
1368 int rc;
1369 unsigned long ulRc = 0;
1370
1371 mysql_refresh(pmysql, REFRESH_TABLES);
1372
1373 /* foreign keys in function table */
1374 strcpy(pszQuery, "SELECT refcode, module, state, apigroup, file FROM function");
1375 rc = mysql_query(pmysql, pszQuery);
1376 if (rc >= 0)
1377 {
1378 pres1 = mysql_store_result(pmysql);
1379 if (pres1 != NULL)
1380 {
1381 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1382 {
1383 /* check module */
1384 sprintf(pszQuery, "SELECT refcode FROM module WHERE refcode = %s", row1[1]);
1385 rc = mysql_query(pmysql, pszQuery);
1386 CheckFKError("function/module", "Foreign key 'module' not found in the module table");
1387
1388 /* check state */
1389 sprintf(pszQuery, "SELECT refcode FROM state WHERE refcode = %s", row1[2]);
1390 rc = mysql_query(pmysql, pszQuery);
1391 CheckFKError("function/state", "Foreign key 'state' not found in the state table");
1392
1393 /* check apigroup */
1394 if (row1[3] != NULL)
1395 {
1396 sprintf(pszQuery, "SELECT refcode FROM apigroup WHERE refcode = %s", row1[3]);
1397 rc = mysql_query(pmysql, pszQuery);
1398 CheckFKError("function/state", "Foreign key 'state' not found in the state table");
1399 }
1400
1401 /* check file */
1402 if (atoi(row1[4]) >= 0)
1403 {
1404 sprintf(pszQuery, "SELECT refcode FROM file WHERE refcode = %s", row1[4]);
1405 rc = mysql_query(pmysql, pszQuery);
1406 CheckFKError("function/file", "Foreign key 'file' not found in the file table");
1407 }
1408 }
1409 mysql_free_result(pres1);
1410 }
1411 }
1412 else
1413 ulRc += logDbError(pszError, pszQuery);
1414
1415 /* foreign keys in file */
1416 strcpy(pszQuery, "SELECT refcode, module FROM file");
1417 rc = mysql_query(pmysql, pszQuery);
1418 if (rc >= 0)
1419 {
1420 pres1 = mysql_store_result(pmysql);
1421 if (pres1 != NULL)
1422 {
1423 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1424 {
1425 /* check module */
1426 sprintf(pszQuery, "SELECT refcode FROM module WHERE refcode = %s", row1[1]);
1427 rc = mysql_query(pmysql, pszQuery);
1428 CheckFKError("apigroup/module", "Foreign key 'module' not found in the module table");
1429 }
1430 mysql_free_result(pres1);
1431 }
1432 }
1433 else
1434 ulRc += logDbError(pszError, pszQuery);
1435
1436 /* foreign keys in apigroup */
1437 strcpy(pszQuery, "SELECT refcode, module FROM apigroup");
1438 rc = mysql_query(pmysql, pszQuery);
1439 if (rc >= 0)
1440 {
1441 pres1 = mysql_store_result(pmysql);
1442 if (pres1 != NULL)
1443 {
1444 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1445 {
1446 /* check module */
1447 sprintf(pszQuery, "SELECT refcode FROM module WHERE refcode = %s", row1[1]);
1448 rc = mysql_query(pmysql, pszQuery);
1449 CheckFKError("file/module", "Foreign key 'module' not found in the module table");
1450 }
1451 mysql_free_result(pres1);
1452 }
1453 }
1454 else
1455 ulRc += logDbError(pszError, pszQuery);
1456
1457 /* foreign keys in fnauthor */
1458 strcpy(pszQuery, "SELECT function, author FROM fnauthor");
1459 rc = mysql_query(pmysql, pszQuery);
1460 if (rc >= 0)
1461 {
1462 pres1 = mysql_store_result(pmysql);
1463 if (pres1 != NULL)
1464 {
1465 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1466 {
1467 /* check function */
1468 sprintf(pszQuery, "SELECT refcode FROM function WHERE refcode = %s", row1[1]);
1469 rc = mysql_query(pmysql, pszQuery);
1470 CheckFKError("fnauthor/function", "Foreign key 'function' not found in the function table");
1471
1472 /* check author */
1473 sprintf(pszQuery, "SELECT refcode FROM author WHERE refcode = %s", row1[1]);
1474 rc = mysql_query(pmysql, pszQuery);
1475 CheckFKError("fnauthor/author", "Foreign key 'author' not found in the author table");
1476 }
1477 mysql_free_result(pres1);
1478 }
1479 }
1480 else
1481 ulRc += logDbError(pszError, pszQuery);
1482
1483 /* foreign keys in historymodule table */
1484 strcpy(pszQuery, "SELECT date, module, state FROM historymodule");
1485 rc = mysql_query(pmysql, pszQuery);
1486 if (rc >= 0)
1487 {
1488 pres1 = mysql_store_result(pmysql);
1489 if (pres1 != NULL)
1490 {
1491 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1492 {
1493 /* check module */
1494 sprintf(pszQuery, "SELECT refcode FROM module WHERE refcode = %s", row1[1]);
1495 rc = mysql_query(pmysql, pszQuery);
1496 CheckFKError("historymodule/module", "Foreign key 'module' not found in the module table");
1497
1498 /* check state */
1499 sprintf(pszQuery, "SELECT refcode FROM state WHERE refcode = %s", row1[2]);
1500 rc = mysql_query(pmysql, pszQuery);
1501 CheckFKError("historymodule/state", "Foreign key 'state' not found in the state table");
1502 }
1503 mysql_free_result(pres1);
1504 }
1505 }
1506 else
1507 ulRc += logDbError(pszError, pszQuery);
1508
1509 /* foreign keys in historyapigroup table */
1510 strcpy(pszQuery, "SELECT date, apigroup, state FROM historyapigroup");
1511 rc = mysql_query(pmysql, pszQuery);
1512 if (rc >= 0)
1513 {
1514 pres1 = mysql_store_result(pmysql);
1515 if (pres1 != NULL)
1516 {
1517 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1518 {
1519 /* check module */
1520 sprintf(pszQuery, "SELECT refcode FROM apigroup WHERE refcode = %s", row1[1]);
1521 rc = mysql_query(pmysql, pszQuery);
1522 CheckFKError("historyapigroup/apigroup", "Foreign key 'apigroup' not found in the apigroup table");
1523
1524 /* check state */
1525 sprintf(pszQuery, "SELECT refcode FROM state WHERE refcode = %s", row1[2]);
1526 rc = mysql_query(pmysql, pszQuery);
1527 CheckFKError("historyapigroup/state", "Foreign key 'state' not found in the state table");
1528 }
1529 mysql_free_result(pres1);
1530 }
1531 }
1532 else
1533 ulRc += logDbError(pszError, pszQuery);
1534
1535 /* foreign keys in historymoduletotal table */
1536 strcpy(pszQuery, "SELECT date, module FROM historymoduletotal");
1537 rc = mysql_query(pmysql, pszQuery);
1538 if (rc >= 0)
1539 {
1540 pres1 = mysql_store_result(pmysql);
1541 if (pres1 != NULL)
1542 {
1543 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1544 {
1545 /* check module */
1546 sprintf(pszQuery, "SELECT refcode FROM module WHERE refcode = %s", row1[1]);
1547 rc = mysql_query(pmysql, pszQuery);
1548 CheckFKError("historymoduletotal/module", "Foreign key 'module' not found in the module table");
1549 }
1550 mysql_free_result(pres1);
1551 }
1552 }
1553 else
1554 ulRc += logDbError(pszError, pszQuery);
1555
1556 /* foreign keys in historyapigroup table */
1557 strcpy(pszQuery, "SELECT date, apigroup FROM historyapigrouptotal");
1558 rc = mysql_query(pmysql, pszQuery);
1559 if (rc >= 0)
1560 {
1561 pres1 = mysql_store_result(pmysql);
1562 if (pres1 != NULL)
1563 {
1564 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1565 {
1566 /* check module */
1567 sprintf(pszQuery, "SELECT refcode FROM apigroup WHERE refcode = %s", row1[1]);
1568 rc = mysql_query(pmysql, pszQuery);
1569 CheckFKError("historyapigrouptotal/apigroup", "Foreign key 'apigroup' not found in the apigroup table");
1570 }
1571 mysql_free_result(pres1);
1572 }
1573 }
1574 else
1575 ulRc += logDbError(pszError, pszQuery);
1576
1577 /* foreign keys in parameter table */
1578 strcpy(pszQuery, "SELECT sequencenbr, function FROM parameter");
1579 rc = mysql_query(pmysql, pszQuery);
1580 if (rc >= 0)
1581 {
1582 pres1 = mysql_store_result(pmysql);
1583 if (pres1 != NULL)
1584 {
1585 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1586 {
1587 /* check function */
1588 sprintf(pszQuery, "SELECT refcode FROM function WHERE refcode = %s", row1[1]);
1589 rc = mysql_query(pmysql, pszQuery);
1590 CheckFKError("parameter/function", "Foreign key 'function' not found in the function table");
1591 }
1592 mysql_free_result(pres1);
1593 }
1594 }
1595 else
1596 ulRc += logDbError(pszError, pszQuery);
1597
1598 /* Author table is special, since you should be able to interchangably reference an
1599 * author by any of the following tables:
1600 * name
1601 * initials
1602 * alias
1603 * email
1604 */
1605 strcpy(pszQuery, "SELECT name, initials, alias, email FROM author");
1606 rc = mysql_query(pmysql, pszQuery);
1607 if (rc >= 0)
1608 {
1609 pres1 = mysql_store_result(pmysql);
1610 if (pres1 != NULL)
1611 {
1612 while ((row1 = mysql_fetch_row(pres1)) != NULL)
1613 {
1614 /* check name */
1615 sprintf(pszQuery, "SELECT name FROM author WHERE "
1616 "initials = '%s' OR alias = '%s' OR email = '%s'",
1617 row1[0], row1[0], row1[0]);
1618 ulRc += CheckAuthorError(pszError, "name", row1[0], pszQuery);
1619
1620 /* check initials */
1621 sprintf(pszQuery, "SELECT name FROM author WHERE "
1622 "alias = '%s' OR email = '%s'",
1623 row1[1], row1[1]);
1624 ulRc += CheckAuthorError(pszError, "initials", row1[1], pszQuery);
1625
1626 /* alias */
1627 if (row1[2] != NULL)
1628 {
1629 sprintf(pszQuery, "SELECT name FROM author WHERE "
1630 "email = '%s'",
1631 row1[2]);
1632 ulRc += CheckAuthorError(pszError, "alias", row1[2], pszQuery);
1633 }
1634 }
1635 mysql_free_result(pres1);
1636 }
1637 }
1638 else
1639 ulRc += logDbError(pszError, pszQuery);
1640
1641 return ulRc;
1642}
1643
1644
1645/**
1646 * Checks for duplicate key and sql error for a given author key in the author table... (arg!)
1647 * @returns Number of errors.
1648 * @param pszError Reference to error buffer pointer.
1649 * @param pszFieldName Key field name; used for logging.
1650 * @param pszFieldValue Key value; used for logging
1651 * @param pszQuery Query which is to be exectued to test for duplicate key.
1652 * @remark Uses pszError[1] == '\xFE' to detect when to insert '\n\t'.
1653 */
1654static unsigned long CheckAuthorError(char * &pszError, const char *pszFieldName, const char *pszFieldValue, const char *pszQuery)
1655{
1656 MYSQL_ROW row;
1657 MYSQL_RES *pres;
1658 unsigned long ulRc = 0;
1659 int rc;
1660
1661 rc = mysql_query(pmysql, pszQuery);
1662 pres = mysql_store_result(pmysql);
1663 if (rc < 0 || (pres != NULL && mysql_num_rows(pres) != 0))
1664 { /* some kind of error has occurred */
1665 if (pszError[1] == '\xFE')
1666 {
1667 strcat(pszError, "\n\t");
1668 pszError += 2;
1669 }
1670
1671 if (rc < 0) /* sql error or 'duplicate key' */
1672 {
1673 sprintf(pszError, "author/%s: select failed - %s (sql=%s)",
1674 pszFieldName, dbGetLastErrorDesc(), pszQuery);
1675 }
1676 else
1677 { /* 'duplicate key' - print duplicates */
1678 sprintf(pszError, "author/%s: 'duplicate key', %s='%s': ",
1679 pszFieldName, pszFieldValue, pszFieldName);
1680
1681 while ((row = mysql_fetch_row(pres)) != NULL)
1682 {
1683 pszError += strlen(pszError);
1684 sprintf(pszError, "'%s' ", row[0]);
1685 }
1686 }
1687
1688 pszError += strlen(pszError);
1689 pszError[1] = '\xFE';
1690 ulRc = 1;
1691 }
1692 if (pres != NULL)
1693 mysql_free_result(pres);
1694
1695 return ulRc;
1696}
1697
1698
1699/**
1700 * Writes db error (rc<0) to the log buffer.
1701 * @returns Number of signals.
1702 * @param pszError Reference to the error buffer pointer.
1703 * @param pszQuery Pointer to query which was executed.
1704 * @remark Uses pszError[1] == '\xFE' to detect when to insert '\n\t'.
1705 */
1706static unsigned long logDbError(char * &pszError, const char *pszQuery)
1707{
1708 if (pszError[1] == '\xFE')
1709 {
1710 strcat(pszError, "\n\t");
1711 pszError += 2;
1712 }
1713 sprintf(pszError, "select failed: %s - (sql=%s)", dbGetLastErrorDesc(), pszQuery);
1714
1715 pszError += strlen(pszError);
1716 pszError[1] = '\xFE';
1717
1718 return 1;
1719}
1720
1721
1722/**
1723 * Executes a give query and returns a result identifier/pointer.
1724 * @returns Query result identifier/pointer. NULL on error.
1725 * @param pszQuery Pointer to query.
1726 * @remark Used by and designed for kHtmlPC.
1727 */
1728void * _System dbExecuteQuery(const char *pszQuery)
1729{
1730 assert(pmysql != NULL);
1731 if (mysql_query(pmysql, pszQuery) >= 0)
1732 return mysql_store_result(pmysql);
1733
1734 return NULL;
1735}
1736
1737
1738/**
1739 * Asks for the number of rows in the result.
1740 * @returns Number of rows in the result. -1 on error.
1741 * @param pres Query result identifier/pointer.
1742 * @remark Used by and designed for kHtmlPC.
1743 */
1744signed long _System dbQueryResultRows(void *pres)
1745{
1746 if (pres == NULL)
1747 return -1;
1748 return mysql_num_rows((MYSQL_RES*)pres);
1749}
1750
1751
1752/**
1753 * Frees the storage allocated by the given result.
1754 * @returns Success indicator, TRUE/FALSE.
1755 * @param pres Query result identifier/pointer.
1756 * @remark Used by and designed for kHtmlPC.
1757 */
1758BOOL _System dbFreeResult(void *pres)
1759{
1760 if (pres != NULL)
1761 mysql_free_result((MYSQL_RES*)pres);
1762 else
1763 return FALSE;
1764 return TRUE;
1765}
1766
1767
1768/**
1769 * Fetch data from a result. Returns the data by calling the given callback function.
1770 * @returns Success indicator, TRUE/FALSE.
1771 * @param pres Query result identifier/pointer.
1772 * @param dbFetchCallBack Callback-function.
1773 * @param pvUser User parameter which is passed onto dbFetchCallBack.
1774 * @remark Used by and designed for kHtmlPC.
1775 */
1776BOOL _System dbFetch(void *pres, DBCALLBACKFETCH dbFetchCallBack, void *pvUser)
1777{
1778 BOOL fRc = FALSE;
1779 MYSQL_ROW row = mysql_fetch_row((MYSQL_RES*)pres);
1780
1781 if (row)
1782 {
1783 MYSQL_FIELD *pField;
1784 int i = 0;
1785 mysql_field_seek((MYSQL_RES*)pres, 0);
1786
1787 while ((pField = mysql_fetch_field((MYSQL_RES*)pres)) != NULL)
1788 if (dbFetchCallBack(row[i++], pField->name, pvUser) != 0)
1789 return FALSE;
1790
1791 fRc = TRUE;
1792 }
1793
1794 return fRc;
1795}
1796
1797
1798/**
1799 * Converts an ISO date to days after Christ, year 0.
1800 * @returns days. -1 on error;
1801 * @param pszDate ISO Date.
1802 */
1803signed long _System dbDateToDaysAfterChrist(const char *pszDate)
1804{
1805 signed long lRet = -1;
1806 char szQuery[128];
1807
1808 sprintf(&szQuery[0], "SELECT to_days('%s')", pszDate);
1809 if (mysql_query(pmysql, &szQuery[0]) >= 0)
1810 {
1811 MYSQL_ROW row;
1812 MYSQL_RES *pres = mysql_use_result(pmysql);
1813 row = mysql_fetch_row(pres);
1814 if (row != NULL)
1815 {
1816 lRet = atol(row[0]);
1817 do { row = mysql_fetch_row(pres); } while (row != NULL);
1818 }
1819 }
1820
1821 return lRet;
1822}
1823
1824
1825/**
1826 * Converts days after Christ (year 0) to ISO date.
1827 * @returns Success indicator. TRUE/FALSE;
1828 * @param lDays Days after Christ (year 0).
1829 * @param pszDate ISO Date. Result.
1830 */
1831BOOL _System dbDaysAfterChristToDate(signed long lDays, char *pszDate)
1832{
1833 BOOL fRet = FALSE;
1834 char szQuery[128];
1835
1836 if (lDays < 0)
1837 return FALSE;
1838
1839 sprintf(&szQuery[0], "SELECT from_days(%ld)", lDays);
1840 if (mysql_query(pmysql, &szQuery[0]) >= 0)
1841 {
1842 MYSQL_ROW row;
1843 MYSQL_RES *pres = mysql_use_result(pmysql);
1844 row = mysql_fetch_row(pres);
1845 if (row != NULL)
1846 {
1847 fRet = strlen(row[0]) == (4+1+2+1+2) && row[0][4] == '-' && row[0][7] == '-'
1848 && strcmp(row[0], "0000-00-00") != 0;
1849 if (fRet)
1850 strcpy(pszDate, row[0]);
1851 do { row = mysql_fetch_row(pres); } while (row != NULL);
1852 }
1853 }
1854
1855 return fRet;
1856}
1857
1858
1859/**
1860 * Display all functions for, the given module, that is not updated.
1861 * @returns TRUE / FALSE.
1862 * @param lModule Module reference number.
1863 * @param dbFetchCall Callback function which will be called once for each
1864 * field for all the functions not updated.
1865 * pvUser is NULL, pszValue field value, pszFieldName the field name.
1866 */
1867BOOL _System dbGetNotUpdatedFunction(signed long lModule, DBCALLBACKFETCH dbFetchCallBack)
1868{
1869 BOOL fRet = FALSE;
1870 void *pres;
1871 char szQuery[256];
1872
1873 /* not updated names */
1874 sprintf(&szQuery[0], "SELECT f1.name, f1.intname, f1.updated, f1.aliasfn, d.name, f2.name, f2.intname AS last "
1875 "FROM function f1 LEFT OUTER JOIN function f2 ON f1.aliasfn = f2.refcode "
1876 " LEFT JOIN module d ON f2.module = d.refcode "
1877 "WHERE f1.module = %ld AND f1.updated = 0",
1878 lModule);
1879 pres = dbExecuteQuery(szQuery);
1880 if (pres != NULL)
1881 {
1882 BOOL f;
1883 do
1884 {
1885 f = dbFetch(pres, dbFetchCallBack, NULL);
1886 } while (f);
1887 dbFreeResult(pres);
1888 fRet = TRUE;
1889 }
1890
1891 /* warn about updated > 1 too */
1892 sprintf(&szQuery[0], "SELECT f1.name, f1.intname, f1.updated, f1.aliasfn, d.name, f2.name, f2.intname AS last "
1893 "FROM function f1 LEFT OUTER JOIN function f2 ON f1.aliasfn = f2.refcode "
1894 " LEFT JOIN module d ON f2.module = d.refcode "
1895 "WHERE f1.module = %ld AND f1.updated > 1",
1896 lModule);
1897 pres = dbExecuteQuery(szQuery);
1898 if (pres != NULL)
1899 {
1900 BOOL f;
1901 do
1902 {
1903 f = dbFetch(pres, dbFetchCallBack, NULL);
1904 } while (f);
1905 dbFreeResult(pres);
1906 fRet = TRUE;
1907 }
1908
1909 strcpy(&szQuery[0], "UPDATE function SET updated = 0");
1910 mysql_query(pmysql, &szQuery[0]);
1911
1912 return fRet;
1913}
1914
1915
1916/**
1917 * Counts the function for the given MODULE which has been updated.
1918 * @returns -1 on error, number of updated function on success.
1919 * @param lModule Module reference number.
1920 */
1921signed long _System dbGetNumberOfUpdatedFunction(signed long lModule)
1922{
1923 int rc;
1924 char szQuery[128];
1925 MYSQL_RES * pres;
1926
1927 sprintf(&szQuery[0], "SELECT count(*) FROM function WHERE module = (%ld) AND updated > 0\n", lModule);
1928 rc = mysql_query(pmysql, &szQuery[0]);
1929 pres = mysql_store_result(pmysql);
1930 if (rc >= 0 && pres != NULL && mysql_num_rows(pres) == 1)
1931 rc = (int)getvalue(0, mysql_fetch_row(pres));
1932 else
1933 rc = -1;
1934 mysql_free_result(pres);
1935 return (signed long)rc;
1936}
1937
1938
1939
1940/**
1941 * Clear the update flags for all file in a module/module.
1942 * @returns Success indicator. (TRUE / FALSE)
1943 * @param lModule Module refcode.
1944 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1945 * @remark Intended for use by APIImport.
1946 */
1947BOOL _System dbClearUpdateFlagFile(signed long lModule)
1948{
1949 int rc;
1950 char szQuery[128];
1951
1952 sprintf(&szQuery[0],
1953 "UPDATE file SET updated = 0 WHERE module = (%ld)",
1954 lModule);
1955 rc = mysql_query(pmysql, &szQuery[0]);
1956 return rc == 0;
1957}
1958
1959
1960/**
1961 * Clear update flag
1962 * @returns Success indicator.
1963 * @param lModule Module refcode.
1964 * @param fAll All module. If false only APIs and Internal APIs are cleared
1965 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1966 * @remark Intended for use by APIImport.
1967 */
1968BOOL _System dbClearUpdateFlagFunction(signed long lModule, BOOL fAll)
1969{
1970 int rc;
1971 char szQuery[128];
1972
1973 sprintf(&szQuery[0],
1974 "UPDATE function SET updated = 0 WHERE module = (%ld)",
1975 lModule);
1976 if (!fAll)
1977 strcat(&szQuery[0], " AND type IN ('A', 'I')");
1978 rc = mysql_query(pmysql, &szQuery[0]);
1979 return rc == 0;
1980}
1981
1982
1983
1984/**
1985 * Deletes all the files in a module/module which was not found/updated.
1986 * @returns Success indicator.
1987 * @param lModule Module refcode.
1988 * @sketch Select all files which is to be deleted.
1989 * Set all references to each file in function to -1.
1990 * Delete all files which is to be deleted.
1991 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no)
1992 * @remark Use with GRATE CARE!
1993 */
1994BOOL _System dbDeleteNotUpdatedFiles(signed long lModule)
1995{
1996 MYSQL_RES * pres;
1997 int rc;
1998 BOOL fRc = TRUE;
1999 char szQuery[128];
2000
2001 sprintf(&szQuery[0],
2002 "SELECT refcode FROM file WHERE module = (%ld) AND updated = 0",
2003 lModule);
2004 rc = mysql_query(pmysql, &szQuery[0]);
2005 pres = mysql_store_result(pmysql);
2006 if (pres != NULL && mysql_num_rows(pres))
2007 {
2008 MYSQL_ROW row;
2009 while ((row = mysql_fetch_row(pres)) != NULL)
2010 {
2011 sprintf(&szQuery[0],
2012 "UPDATE function SET file = -1 WHERE file = %s",
2013 row[0]);
2014 rc = mysql_query(pmysql, &szQuery[0]);
2015 if (rc) fRc = FALSE;
2016 }
2017 }
2018
2019 sprintf(&szQuery[0],
2020 "DELETE FROM file WHERE module = %ld AND updated = 0",
2021 lModule);
2022 rc = mysql_query(pmysql, &szQuery[0]);
2023 if (rc) fRc = FALSE;
2024
2025 return fRc;
2026}
2027
2028
2029/**
2030 * Deletes all the functions which haven't been updated.
2031 * All rows in other tables which references the functions are
2032 * also delete.
2033 *
2034 * @returns Success indicator. (TRUE / FALSE)
2035 * @param lModule The refcode of the module owning the functions.
2036 * @param fAll All function. If FALSE then only APIs and Internal APIs.
2037 * @sketch Select all functions which wan't updated (ie. updated = 0 and module = lModule).
2038 * If anyone Then
2039 * Delete the referenced to the functions in:
2040 * parameters
2041 * fnauthor
2042 * Delete all function which wasn't updated.
2043 * EndIf
2044 * @remark Use with GREATE CARE!
2045 */
2046BOOL _System dbDeleteNotUpdatedFunctions(signed long lModule, BOOL fAll)
2047{
2048 MYSQL_RES * pres;
2049 int rc;
2050 BOOL fRc = TRUE;
2051 char szQuery[128];
2052
2053 sprintf(&szQuery[0],
2054 "SELECT refcode FROM function WHERE module = %ld AND updated = 0",
2055 lModule);
2056 if (!fAll)
2057 strcat(&szQuery[0], " AND type IN ('A', 'I')");
2058 rc = mysql_query(pmysql, &szQuery[0]);
2059 pres = mysql_store_result(pmysql);
2060
2061 if (pres != NULL && mysql_num_rows(pres))
2062 {
2063 MYSQL_ROW row;
2064 while ((row = mysql_fetch_row(pres)) != NULL)
2065 {
2066 /* delete parameters */
2067 sprintf(&szQuery[0], "DELETE FROM parameter WHERE function = %s", row[0]);
2068 rc = mysql_query(pmysql, &szQuery[0]);
2069 if (rc) fRc = FALSE;
2070
2071 /* author relations */
2072 sprintf(&szQuery[0], "DELETE FROM fnauthor WHERE function = %s", row[0]);
2073 rc = mysql_query(pmysql, &szQuery[0]);
2074 if (rc) fRc = FALSE;
2075 }
2076
2077 /*
2078 * Delete the functions only if above completed without errors.
2079 *
2080 * Deleting the functions before all the references has successfully be
2081 * deleted causes database corruption!
2082 */
2083 if (fRc)
2084 {
2085 sprintf(&szQuery[0],
2086 "DELETE FROM function WHERE module = %ld AND updated = 0",
2087 lModule);
2088 if (!fAll)
2089 strcat(&szQuery[0], " AND type IN ('A', 'I')");
2090 rc = mysql_query(pmysql, &szQuery[0]);
2091 if (rc) fRc = FALSE;
2092 }
2093 }
2094
2095 return fRc;
2096}
2097
2098
2099
2100/**
2101 * Appends a set of strings to a query. The main string (pszStr) is enclosed in "'"s.
2102 * @returns Pointer to end of the string.
2103 * @param pszQuery Outputbuffer
2104 * @param pszBefore Text before string, might be NULL.
2105 * @param pszStr String (NOT NULL)
2106 * @param pszAfter Text after, might be NULL.
2107 * @status completely implemented
2108 * @author knut st. osmundsen (knut.stange.osmundsen@pmsc.no)
2109 */
2110static char *sqlstrcat(char *pszQuery, const char *pszBefore, const char *pszStr, const char *pszAfter)
2111{
2112 char * pszLineStart = pszQuery;
2113 register char ch;
2114
2115 pszQuery += strlen(pszQuery);
2116
2117 /*
2118 * String before
2119 */
2120 if (pszBefore != NULL)
2121 {
2122 strcpy(pszQuery, pszBefore);
2123 pszQuery += strlen(pszQuery);
2124 }
2125
2126 /*
2127 * THE String
2128 */
2129 *pszQuery++ = '\'';
2130 while ((ch = *pszStr++) != '\0')
2131 {
2132 switch (ch)
2133 {
2134 case '\'':
2135 *pszQuery++ = '\\';
2136 *pszQuery++ = '\'';
2137 break;
2138
2139 case '"':
2140 *pszQuery++ = '\\';
2141 *pszQuery++ = '"';
2142 break;
2143
2144 case '\\':
2145 *pszQuery++ = '\\';
2146 *pszQuery++ = '\\';
2147 break;
2148
2149 case '%':
2150 *pszQuery++ = '\\';
2151 *pszQuery++ = '%';
2152 break;
2153
2154 case '_':
2155 *pszQuery++ = '\\';
2156 *pszQuery++ = '_';
2157 break;
2158
2159 case '\n':
2160 *pszQuery++ = '\\';
2161 *pszQuery++ = 'r';
2162 *pszQuery++ = '\\';
2163 *pszQuery++ = 'n';
2164 break;
2165
2166 case '\t':
2167 *pszQuery++ = '\\';
2168 *pszQuery++ = 't';
2169 break;
2170
2171 case '\r':
2172 break;
2173
2174 default:
2175 *pszQuery++ = ch;
2176 }
2177
2178 /* Add new lines every 80 chars MySql don't like long lines. */
2179 if (pszLineStart - pszQuery > 80)
2180 {
2181 *pszQuery = '\n';
2182 pszLineStart = pszQuery;
2183 }
2184 }
2185 *pszQuery++ = '\'';
2186
2187 /*
2188 * String after
2189 */
2190 if (pszAfter != NULL)
2191 {
2192 strcpy(pszQuery, pszAfter);
2193 pszQuery += strlen(pszQuery);
2194 }
2195 else
2196 *pszQuery = '\0';
2197
2198
2199 return pszQuery;
2200}
2201
2202
2203#ifndef DLL
2204/**
2205 * Signal handler.
2206 * Ensures that the database connection is closed at termination.
2207 * @param sig Signal number.
2208 */
2209void dbHandler(int sig)
2210{
2211 if (pmysql != NULL)
2212 {
2213 fprintf(stderr, "\n\t!disconnecting from database!\n");
2214 dbDisconnect();
2215 }
2216
2217 flushall();
2218 switch (sig)
2219 {
2220 case SIGBREAK:
2221 printf("\nSIGBREAK\n");
2222 exit(-1);
2223 break;
2224 case SIGINT:
2225 printf("\nSIGINT\n");
2226 exit(-1);
2227 break;
2228 case SIGTERM:
2229 printf("\nSIGTERM\n");
2230 exit(-1);
2231 break;
2232 case SIGSEGV:
2233 raise(sig);
2234 break;
2235 case SIGILL:
2236 printf("\nSIGILL\n");
2237 exit(-1);
2238 break;
2239 }
2240}
2241
2242
2243#else
2244/*******/
2245/* DLL */
2246/*******/
2247/* prototypes used in the _DLL_InitTerm function */
2248extern "C"
2249{
2250 int _CRT_init(void);
2251 void _CRT_term(void);
2252 void __ctordtorInit( void );
2253 void __ctordtorTerm( void );
2254 unsigned long _System _DLL_InitTerm(unsigned long hModule, unsigned long ulFlag);
2255}
2256
2257
2258/**
2259 * Dll InitTerm function.
2260 * @returns 0 on success.
2261 * 1 on error.
2262 * @param hModule
2263 * @param ulFlags
2264 * @remark We'll ensure that the database connection is terminated as we terminate.
2265 */
2266unsigned long _System _DLL_InitTerm(unsigned long hModule, unsigned long ulFlag)
2267{
2268 /*-------------------------------------------------------------------------*/
2269 /* If ulFlag is zero then the DLL is being loaded so initialization should */
2270 /* be performed. If ulFlag is 1 then the DLL is being freed so */
2271 /* termination should be performed. */
2272 /*-------------------------------------------------------------------------*/
2273
2274 switch (ulFlag)
2275 {
2276 case 0:
2277 if (_CRT_init() == -1)
2278 return 0;
2279 __ctordtorInit();
2280 break;
2281
2282 case 1:
2283 /* ensure that db connection is terminated */
2284 if (pmysql != NULL)
2285 {
2286 fprintf(stderr, "\n\t!disconnecting from database!\n");
2287 dbDisconnect();
2288 }
2289 __ctordtorTerm();
2290 break;
2291
2292 default:
2293 return 0;
2294 }
2295 hModule = hModule;
2296 return 1;
2297}
2298
2299/*****************************************************************/
2300/* -why is this terminate function referenced but not defined??? */
2301/* and where is it referenced??? */
2302/* -Probably an export missing from the libraries. */
2303/*****************************************************************/
2304void terminate(void)
2305{
2306 DosPutMessage(0, sizeof("terminate")-1, "terminate");
2307 exit(-1);
2308}
2309
2310/****************************************/
2311/* EMX run-time trouble */
2312/* _environ is missing when using -Zomf */
2313/****************************************/
2314char **_environ = environ;
2315
2316#endif
Note: See TracBrowser for help on using the repository browser.