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