]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/cats/sql_create.c
7ad6497cef0a68bc73a5190415f950e7f61bba13
[bacula/bacula] / bacula / src / cats / sql_create.c
1 /*
2  * Bacula Catalog Database Create record interface routines
3  * 
4  *    Kern Sibbald, March 2000
5  */
6
7 /*
8    Copyright (C) 2000, 2001, 2002 Kern Sibbald and John Walker
9
10    This program is free software; you can redistribute it and/or
11    modify it under the terms of the GNU General Public License as
12    published by the Free Software Foundation; either version 2 of
13    the License, or (at your option) any later version.
14
15    This program is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18    General Public License for more details.
19
20    You should have received a copy of the GNU General Public
21    License along with this program; if not, write to the Free
22    Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
23    MA 02111-1307, USA.
24
25  */
26
27 /* *****FIXME**** fix fixed length of select_cmd[] and insert_cmd[] */
28
29 /* The following is necessary so that we do not include
30  * the dummy external definition of DB.
31  */
32 #define __SQL_C                       /* indicate that this is sql.c */
33
34 #include "bacula.h"
35 #include "cats.h"
36
37 #if    HAVE_MYSQL || HAVE_SQLITE
38
39 /* -----------------------------------------------------------------------
40  *
41  *   Generic Routines (or almost generic)
42  *
43  * -----------------------------------------------------------------------
44  */
45
46 /* Forward referenced subroutines */
47 static int db_create_file_record(B_DB *mdb, ATTR_DBR *ar);
48 static int db_create_filename_record(B_DB *mdb, ATTR_DBR *ar, char *fname);
49 static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path);
50
51
52 /* Imported subroutines */
53 extern void print_dashes(B_DB *mdb);
54 extern void print_result(B_DB *mdb);
55 extern int QueryDB(char *file, int line, B_DB *db, char *select_cmd);
56 extern int InsertDB(char *file, int line, B_DB *db, char *select_cmd);
57
58
59 /* Create a new record for the Job
60  * Returns: 0 on failure
61  *          1 on success
62  */
63 int
64 db_create_job_record(B_DB *mdb, JOB_DBR *jr)
65 {
66    char dt[MAX_TIME_LENGTH];
67    time_t stime;
68    struct tm tm;
69    int stat;
70    char *JobId;
71    int32_t StartDay;
72
73    stime = jr->SchedTime;
74
75    localtime_r(&stime, &tm); 
76    strftime(dt, sizeof(dt), "%Y-%m-%d %T", &tm);
77    StartDay = (int32_t)(date_encode(tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday) -
78        date_encode(2000, 1, 1));
79
80    P(mdb->mutex);
81    JobId = db_next_index(mdb, "Job");
82    if (!JobId) {
83       jr->JobId = 0;
84       V(mdb->mutex);
85       return 0;
86    }
87    /* Must create it */
88    Mmsg(&mdb->cmd,
89 "INSERT INTO Job (JobId, Job, Name, Type, Level, SchedTime, StartDay) VALUES \
90 (%s, \"%s\", \"%s\", \"%c\", \"%c\", \"%s\", %d)", 
91            JobId, jr->Job, jr->Name, (char)(jr->Type), (char)(jr->Level), dt,
92            StartDay);
93
94    if (!INSERT_DB(mdb, mdb->cmd)) {
95       Mmsg2(&mdb->errmsg, _("Create DB Job record %s failed. ERR=%s\n"), 
96             mdb->cmd, sql_strerror(mdb));
97       jr->JobId = 0;
98       stat = 0;
99    } else {
100       jr->JobId = sql_insert_id(mdb);
101       stat = 1;
102    }
103    V(mdb->mutex);
104    return stat;
105 }
106
107 /* Create a JobMedia record for medium used this job   
108  * Returns: 0 on failure
109  *          1 on success
110  */
111 int
112 db_create_jobmedia_record(B_DB *mdb, JOBMEDIA_DBR *jm)
113 {
114    int stat;
115
116    P(mdb->mutex);
117    Mmsg(&mdb->cmd, "SELECT JobId, MediaId FROM JobMedia WHERE \
118 JobId=%d AND MediaId=%d", jm->JobId, jm->MediaId);
119
120    Dmsg0(30, mdb->cmd);
121    if (QUERY_DB(mdb, mdb->cmd)) {
122       mdb->num_rows = sql_num_rows(mdb);
123       if (mdb->num_rows > 0) {
124          Mmsg0(&mdb->errmsg, _("Create JobMedia failed. Record already exists.\n"));
125          sql_free_result(mdb);
126          V(mdb->mutex);
127          Dmsg0(0, "Already have JobMedia record\n");
128          return 0;
129       }
130       sql_free_result(mdb);
131    }
132
133    /* Must create it */
134    Mmsg(&mdb->cmd, 
135 "INSERT INTO JobMedia (JobId, MediaId, FirstIndex, LastIndex) \
136 VALUES (%d, %d, %u, %u)", 
137        jm->JobId, jm->MediaId, jm->FirstIndex, jm->LastIndex);
138
139    Dmsg0(30, mdb->cmd);
140    if (!INSERT_DB(mdb, mdb->cmd)) {
141       Mmsg2(&mdb->errmsg, _("Create db JobMedia record %s failed. ERR=%s\n"), mdb->cmd, 
142          sql_strerror(mdb));
143       stat = 0;
144    } else {
145       stat = 1;
146    }
147    V(mdb->mutex);
148    Dmsg0(30, "Return from JobMedia\n");
149    return stat;
150 }
151
152
153
154 /* Create Unique Pool record
155  * Returns: 0 on failure
156  *          1 on success
157  */
158 int
159 db_create_pool_record(B_DB *mdb, POOL_DBR *pool_dbr)
160 {
161    int stat;
162
163    P(mdb->mutex);
164    Mmsg(&mdb->cmd, "SELECT PoolId,Name FROM Pool WHERE Name=\"%s\"", pool_dbr->Name);
165    Dmsg1(20, "selectpool: %s\n", mdb->cmd);
166
167    if (QUERY_DB(mdb, mdb->cmd)) {
168
169       mdb->num_rows = sql_num_rows(mdb);
170    
171       if (mdb->num_rows > 0) {
172          Mmsg1(&mdb->errmsg, _("pool record %s already exists\n"), pool_dbr->Name);
173          sql_free_result(mdb);
174          V(mdb->mutex);
175          return 0;
176       }
177       sql_free_result(mdb);
178    }
179
180    /* Must create it */
181    Mmsg(&mdb->cmd, 
182 "INSERT INTO Pool (Name, NumVols, MaxVols, UseOnce, UseCatalog, \
183 AcceptAnyVolume, PoolType, LabelFormat) \
184 VALUES (\"%s\", %d, %d, %d, %d, %d, \"%s\", \"%s\")", 
185                   pool_dbr->Name,
186                   pool_dbr->NumVols, pool_dbr->MaxVols,
187                   pool_dbr->UseOnce, pool_dbr->UseCatalog,
188                   pool_dbr->AcceptAnyVolume,
189                   pool_dbr->PoolType, pool_dbr->LabelFormat);
190
191    if (!INSERT_DB(mdb, mdb->cmd)) {
192       Mmsg2(&mdb->errmsg, _("Create db Pool record %s failed: ERR=%s\n"), 
193             mdb->cmd, sql_strerror(mdb));
194       pool_dbr->PoolId = 0;
195       stat = 0;
196    } else {
197       pool_dbr->PoolId = sql_insert_id(mdb);
198       stat = 1;
199    }
200    V(mdb->mutex);
201    
202    return stat;
203 }
204
205
206 /* 
207  * Create Unique Media record   
208  * Returns: 0 on failure
209  *          1 on success
210  */ 
211 int
212 db_create_media_record(B_DB *mdb, MEDIA_DBR *mr)
213 {
214    int stat;
215
216    P(mdb->mutex);
217    Mmsg(&mdb->cmd, "SELECT MediaId FROM Media WHERE VolumeName=\"%s\"", 
218            mr->VolumeName);
219    Dmsg1(110, "selectpool: %s\n", mdb->cmd);
220
221    if (QUERY_DB(mdb, mdb->cmd)) {
222       mdb->num_rows = sql_num_rows(mdb);
223       if (mdb->num_rows > 0) {
224          Mmsg1(&mdb->errmsg, _("Media record %s already exists\n"), mr->VolumeName);
225          sql_free_result(mdb);
226          V(mdb->mutex);
227          return 0;
228       }
229       sql_free_result(mdb);
230    }
231
232    /* Must create it */
233    Mmsg(&mdb->cmd, 
234 "INSERT INTO Media (VolumeName, MediaType, PoolId, VolMaxBytes, VolCapacityBytes, \
235 VolStatus, Recycle) VALUES (\"%s\", \"%s\", %d, %" lld ", %" lld ", \"%s\", \"%s\")", 
236                   mr->VolumeName,
237                   mr->MediaType, mr->PoolId, 
238                   mr->VolMaxBytes, mr->VolCapacityBytes, 
239                   mr->VolStatus, mr->Recycle);
240
241    if (!INSERT_DB(mdb, mdb->cmd)) {
242       Mmsg2(&mdb->errmsg, _("Create DB Media record %s failed. ERR=%s\n"),
243             mdb->cmd, sql_strerror(mdb));
244       stat = 0;
245    } else {
246       mr->MediaId = sql_insert_id(mdb);
247       stat = 1;
248    }
249    V(mdb->mutex);
250    return stat;
251 }
252
253
254
255 /* 
256  * Create a Unique record for the client -- no duplicates 
257  * Returns: 0 on failure
258  *          1 on success with id in cr->ClientId
259  */
260 int db_create_client_record(B_DB *mdb, CLIENT_DBR *cr)
261 {
262    SQL_ROW row;
263    int stat;
264
265    P(mdb->mutex);
266    Mmsg(&mdb->cmd, "SELECT ClientId FROM Client WHERE Name=\"%s\"", cr->Name);
267
268    cr->ClientId = 0;
269    if (QUERY_DB(mdb, mdb->cmd)) {
270
271       mdb->num_rows = sql_num_rows(mdb);
272       
273       /* If more than one, report error, but return first row */
274       if (mdb->num_rows > 1) {
275          Mmsg1(&mdb->errmsg, _("More than one Client!: %d\n"), (int)(mdb->num_rows));
276          Emsg0(M_ERROR, 0, mdb->errmsg);
277       }
278       if (mdb->num_rows >= 1) {
279          if ((row = sql_fetch_row(mdb)) == NULL) {
280             Mmsg1(&mdb->errmsg, _("error fetching Client row: %s\n"), sql_strerror(mdb));
281             Emsg0(M_ERROR, 0, mdb->errmsg);
282             sql_free_result(mdb);
283             V(mdb->mutex);
284             return 0;
285          }
286          sql_free_result(mdb);
287          cr->ClientId = atoi(row[0]);
288          V(mdb->mutex);
289          return 1;
290       }
291       sql_free_result(mdb);
292    }
293
294    /* Must create it */
295    Mmsg(&mdb->cmd, "INSERT INTO Client (Name, Uname) VALUES \
296 (\"%s\", \"%s\")", cr->Name, cr->Uname);
297
298    if (!INSERT_DB(mdb, mdb->cmd)) {
299       Mmsg2(&mdb->errmsg, _("Create DB Client record %s failed. ERR=%s\n"),
300             mdb->cmd, sql_strerror(mdb));
301       cr->ClientId = 0;
302       stat = 0;
303    } else {
304       cr->ClientId = sql_insert_id(mdb);
305       stat = 1;
306    }
307    V(mdb->mutex);
308    return stat;
309 }
310
311
312 /* 
313  * Create a FileSet record. This record is unique in the
314  *  name and the MD5 signature of the include/exclude sets.
315  *  Returns: 0 on failure
316  *           1 on success with FileSetId in record
317  */
318 int db_create_fileset_record(B_DB *mdb, FILESET_DBR *fsr)
319 {
320    SQL_ROW row;
321    int stat;
322
323    P(mdb->mutex);
324    Mmsg(&mdb->cmd, "SELECT FileSetId FROM FileSet WHERE \
325 FileSet=\"%s\" and MD5=\"%s\"", fsr->FileSet, fsr->MD5);
326
327    fsr->FileSetId = 0;
328    if (QUERY_DB(mdb, mdb->cmd)) {
329
330       mdb->num_rows = sql_num_rows(mdb);
331       
332       if (mdb->num_rows > 1) {
333          Mmsg1(&mdb->errmsg, _("More than one FileSet!: %d\n"), (int)(mdb->num_rows));
334          Emsg0(M_ERROR, 0, mdb->errmsg);
335       }
336       if (mdb->num_rows >= 1) {
337          if ((row = sql_fetch_row(mdb)) == NULL) {
338             Mmsg1(&mdb->errmsg, _("error fetching FileSet row: ERR=%s\n"), sql_strerror(mdb));
339             Emsg0(M_ERROR, 0, mdb->errmsg);
340             sql_free_result(mdb);
341             V(mdb->mutex);
342             return 0;
343          }
344          sql_free_result(mdb);
345          fsr->FileSetId = atoi(row[0]);
346          V(mdb->mutex);
347          return 1;
348       }
349       sql_free_result(mdb);
350    }
351
352    /* Must create it */
353    Mmsg(&mdb->cmd, "INSERT INTO FileSet (FileSet, MD5) VALUES \
354 (\"%s\", \"%s\")", fsr->FileSet, fsr->MD5);
355
356    if (!INSERT_DB(mdb, mdb->cmd)) {
357       Mmsg2(&mdb->errmsg, _("Create DB FileSet record %s failed. ERR=%s\n"),
358             mdb->cmd, sql_strerror(mdb));
359       fsr->FileSetId = 0;
360       stat = 0;
361    } else {
362       fsr->FileSetId = sql_insert_id(mdb);
363       stat = 1;
364    }
365
366    V(mdb->mutex);
367    return stat;
368 }
369
370
371 /*
372  *  struct stat
373  *  {
374  *      dev_t         st_dev;       * device *
375  *      ino_t         st_ino;       * inode *
376  *      mode_t        st_mode;      * protection *
377  *      nlink_t       st_nlink;     * number of hard links *
378  *      uid_t         st_uid;       * user ID of owner *
379  *      gid_t         st_gid;       * group ID of owner *
380  *      dev_t         st_rdev;      * device type (if inode device) *
381  *      off_t         st_size;      * total size, in bytes *
382  *      unsigned long st_blksize;   * blocksize for filesystem I/O *
383  *      unsigned long st_blocks;    * number of blocks allocated *
384  *      time_t        st_atime;     * time of last access *
385  *      time_t        st_mtime;     * time of last modification *
386  *      time_t        st_ctime;     * time of last inode change *            
387  *  };
388  */
389
390
391
392 /* 
393  * Create File record in B_DB   
394  *
395  *  In order to reduce database size, we store the File attributes,
396  *  the FileName, and the Path separately.  In principle, there   
397  *  is a single FileName record and a single Path record, no matter
398  *  how many times it occurs.  This is this subroutine, we separate
399  *  the file and the path and create three database records.
400  */
401 int db_create_file_attributes_record(B_DB *mdb, ATTR_DBR *ar)
402 {
403    int fnl, pnl;
404    char *l, *p;
405    /* ****FIXME***** malloc these */
406    char file[MAXSTRING];
407    char spath[MAXSTRING];
408    char buf[MAXSTRING];
409
410    Dmsg1(100, "Fname=%s\n", ar->fname);
411    Dmsg0(50, "put_file_into_catalog\n");
412    /* For the moment, we only handle Unix attributes.  Note, we are
413     * also getting any MD5 signature that was computed.
414     */
415    if (ar->Stream != STREAM_UNIX_ATTRIBUTES) {
416       Mmsg0(&mdb->errmsg, _("Attempt to put non-attributes into catalog\n"));
417       return 0;
418    }
419
420    /* Find path without the filename.  
421     * I.e. everything after the last / is a "filename".
422     * OK, maybe it is a directory name, but we treat it like
423     * a filename. If we don't find a / then the whole name
424     * must be a path name (e.g. c:).
425     */
426    for (p=l=ar->fname; *p; p++) {
427       if (*p == '/') {
428          l = p;                       /* set pos of last slash */
429       }
430    }
431    if (*l == '/') {                   /* did we find a slash? */
432       l++;                            /* yes, point to filename */
433    } else {                           /* no, whole thing must be path name */
434       l = p;
435    }
436
437    /* If filename doesn't exist (i.e. root directory), we
438     * simply create a blank name consisting of a single 
439     * space. This makes handling zero length filenames
440     * easier.
441     */
442    fnl = p - l;
443    if (fnl > 255) {
444       Emsg1(M_WARNING, 0, _("Filename truncated to 255 chars: %s\n"), l);
445       fnl = 255;
446    }
447    if (fnl > 0) {
448       strncpy(file, l, fnl);          /* copy filename */
449       file[fnl] = 0;
450    } else {
451       file[0] = ' ';                  /* blank filename */
452       file[1] = 0;
453    }
454
455    pnl = l - ar->fname;    
456    if (pnl > 255) {
457       Emsg1(M_WARNING, 0, _("Path name truncated to 255 chars: %s\n"), ar->fname);
458       pnl = 255;
459    }
460    strncpy(spath, ar->fname, pnl);
461    spath[pnl] = 0;
462
463    if (pnl == 0) {
464       Mmsg1(&mdb->errmsg, _("Path length is zero. File=%s\n"), ar->fname);
465       Emsg0(M_ERROR, 0, mdb->errmsg);
466       spath[0] = ' ';
467       spath[1] = 0;
468    }
469
470    Dmsg1(100, "spath=%s\n", spath);
471    Dmsg1(100, "file=%s\n", file);
472
473    db_escape_string(buf, file, fnl);
474
475    if (!db_create_filename_record(mdb, ar, buf)) {
476       return 0;
477    }
478    Dmsg1(100, "db_create_filename_record: %s\n", buf);
479
480    db_escape_string(buf, spath, pnl);
481
482    if (!db_create_path_record(mdb, ar, buf)) {
483       return 0;
484    }
485    Dmsg1(100, "db_create_path_record\n", buf);
486
487    if (!db_create_file_record(mdb, ar)) {
488       return 0;
489    }
490    Dmsg0(50, "db_create_file_record\n");
491
492    Dmsg3(100, "Path=%s File=%s FilenameId=%d\n", spath, file, ar->FilenameId);
493
494    return 1;
495 }
496
497 static int db_create_file_record(B_DB *mdb, ATTR_DBR *ar)
498 {
499    int stat;
500
501    P(mdb->mutex);
502    /* Must create it */
503    Mmsg(&mdb->cmd,
504 "INSERT INTO File (FileIndex, JobId, PathId, FilenameId, \
505 LStat, MD5) VALUES (%d, %d, %d, %d, \"%s\", \" \")", 
506      (int)ar->FileIndex, ar->JobId, ar->PathId, ar->FilenameId, 
507       ar->attr);
508
509    if (!INSERT_DB(mdb, mdb->cmd)) {
510       Mmsg2(&mdb->errmsg, _("Create db File record %s failed. ERR=%s"),       
511          mdb->cmd, sql_strerror(mdb));
512       Emsg1(M_ERROR, 0, "%s", mdb->errmsg);
513       ar->FileId = 0;
514       stat = 0;
515    } else {
516       ar->FileId = sql_insert_id(mdb);
517       stat = 1;
518    }
519    V(mdb->mutex);
520    return stat;
521 }
522
523 /* Create a Unique record for the Path -- no duplicates */
524 static int db_create_path_record(B_DB *mdb, ATTR_DBR *ar, char *path)
525 {
526    SQL_ROW row;
527    static uint32_t cached_id = 0;
528    static char cached_path[MAXSTRING];
529    int stat;
530
531    if (*path == 0) {
532       Mmsg0(&mdb->errmsg, _("Null path given to db_create_path_record\n"));
533       Emsg0(M_ERROR, 0, mdb->errmsg);
534       ar->PathId = 0;
535       return 0;
536    }
537
538    P(mdb->mutex);
539
540    if (cached_id != 0 && strcmp(cached_path, path) == 0) {
541       ar->PathId = cached_id;
542       V(mdb->mutex);
543       return 1;
544    }
545
546    Mmsg(&mdb->cmd, "SELECT PathId FROM Path WHERE Path=\"%s\"", path);
547
548    if (QUERY_DB(mdb, mdb->cmd)) {
549
550       mdb->num_rows = sql_num_rows(mdb);
551
552       if (mdb->num_rows > 1) {
553          Mmsg2(&mdb->errmsg, _("More than one Path!: %" lld " for Path=%s\n"), 
554             mdb->num_rows, path);
555          Emsg1(M_ERROR, 0, "%s", mdb->errmsg);
556          Emsg1(M_ERROR, 0, "%s\n", mdb->cmd);
557       }
558       if (mdb->num_rows >= 1) {
559          if ((row = sql_fetch_row(mdb)) == NULL) {
560             V(mdb->mutex);
561             Mmsg1(&mdb->errmsg, _("error fetching row: %s\n"), sql_strerror(mdb));
562             Emsg0(M_ERROR, 0, mdb->errmsg);
563             sql_free_result(mdb);
564             ar->PathId = 0;
565             return 0;
566          }
567          sql_free_result(mdb);
568          ar->PathId = atoi(row[0]);
569          if (ar->PathId != cached_id) {
570             cached_id = ar->PathId;
571             strncpy(cached_path, path, sizeof(cached_path));
572             cached_path[sizeof(cached_path)-1] = 0;
573          }
574          V(mdb->mutex);
575          return 1;
576       }
577
578       sql_free_result(mdb);
579    }
580
581    Mmsg(&mdb->cmd, "INSERT INTO Path (Path)  VALUES (\"%s\")", path);
582
583    if (!INSERT_DB(mdb, mdb->cmd)) {
584       Mmsg2(&mdb->errmsg, _("Create db Path record %s failed. ERR=%s\n"), 
585          mdb->cmd, sql_strerror(mdb));
586       Emsg1(M_ERROR, 0, "%s", mdb->errmsg);
587       ar->PathId = 0;
588       stat = 0;
589    } else {
590       ar->PathId = sql_insert_id(mdb);
591       stat = 1;
592    }
593
594    if (ar->PathId != cached_id) {
595       cached_id = ar->PathId;
596       strncpy(cached_path, path, sizeof(cached_path));
597       cached_path[sizeof(cached_path)-1] = 0;
598    }
599    V(mdb->mutex);
600    return stat;
601 }
602
603 /* Create a Unique record for the filename -- no duplicates */
604 static int db_create_filename_record(B_DB *mdb, ATTR_DBR *ar, char *fname) 
605 {
606    SQL_ROW row;
607    int stat;
608
609    P(mdb->mutex);
610    Mmsg(&mdb->cmd, "SELECT FilenameId FROM Filename WHERE Name=\"%s\"", fname);
611
612    if (QUERY_DB(mdb, mdb->cmd)) {
613       mdb->num_rows = sql_num_rows(mdb);
614       if (mdb->num_rows > 1) {
615          Mmsg2(&mdb->errmsg, _("More than one Filename!: %d File=%s\n"), 
616             (int)(mdb->num_rows), fname);
617          Emsg1(M_ERROR, 0, "%s", mdb->errmsg);
618          Emsg1(M_ERROR, 0, "%s\n", mdb->cmd);
619       }
620       if (mdb->num_rows >= 1) {
621          if ((row = sql_fetch_row(mdb)) == NULL) {
622             Mmsg2(&mdb->errmsg, _("error fetching row for file=%s: ERR=%s\n"), 
623                 fname, sql_strerror(mdb));
624             sql_free_result(mdb);
625             V(mdb->mutex);
626             Emsg0(M_ERROR, 0, mdb->errmsg);
627             ar->FilenameId = 0;
628             return 0;
629          }
630          sql_free_result(mdb);
631          ar->FilenameId = atoi(row[0]);
632          V(mdb->mutex);
633          return 1;
634       }
635       sql_free_result(mdb);
636    }
637
638    Mmsg(&mdb->cmd, "INSERT INTO Filename (Name) \
639 VALUES (\"%s\")", fname);
640
641    if (!INSERT_DB(mdb, mdb->cmd)) {
642       Mmsg2(&mdb->errmsg, _("Create db Filename record %s failed. ERR=%s\n"), 
643             mdb->cmd, sql_strerror(mdb));
644       Emsg1(M_ERROR, 0, "%s", mdb->errmsg);
645       ar->FilenameId = 0;
646       stat = 0;
647    } else {
648       ar->FilenameId = sql_insert_id(mdb);
649       stat = 1;
650    }
651
652    V(mdb->mutex);
653    return stat;
654 }
655
656 #endif /* HAVE_MYSQL || HAVE_SQLITE */