From 1e9a45db89212714162ad7aca93bbfa0daee7fbd Mon Sep 17 00:00:00 2001 From: Alain Spineux Date: Fri, 12 Aug 2022 11:45:13 +0200 Subject: [PATCH] Fix sqlite query error in VF - this fix don't modify the pgsql nor the mysql query, ONLY the sqlite query, is modified. The code is duplicated and modified ONLY for sqlite, - fix the "UNION": syntax error that come when running a VF - the fix just remove the () and a useless "order by" - I think this query could be used for pgsql & mysql too. - tests/virtual-backup-test 12-Aug 11:38 127.0.0.1-dir JobId 8: Error: Query failed: SELECT Path, Filename, FileIndex, JobId, LStat, DeltaSeq , JobTDate FROM ((SELECT Path.Path, T1.Filename, T1.FileIndex, T1.JobId, LStat, DeltaSeq , JobTDate FROM ( SELECT FileId, Job.JobId AS JobId, FileIndex, File.PathId AS PathId,File.Filename AS Filename, LStat , File.DeltaSeq AS DeltaSeq,Job.JobTDate AS JobTDate FROM Job, File, (SELECT MAX(JobTDate) AS JobTDate, PathId, Filename, DeltaSeq FROM (SELECT JobTDate, PathId, Filename, DeltaSeq FROM File JOIN Job USING (JobId) WHERE File.JobId IN (1,2,3,4,5,6) UNION ALL SELECT JobTDate, PathId, Filename, DeltaSeq FROM BaseFiles JOIN File USING (FileId) JOIN Job ON (BaseJobId = Job.JobId) WHERE BaseFiles.JobId IN (1,2,3,4,5,6) ) AS tmp GROUP BY PathId, Filename, DeltaSeq ) AS T1 WHERE (Job.JobId IN ( SELECT DISTINCT BaseJobId FROM BaseFiles WHERE JobId IN (1,2,3,4,5,6)) OR Job.JobId IN (1,2,3,4,5,6)) AND T1.JobTDate = Job.JobTDate AND Job.JobId = File.JobId AND T1.PathId = File.PathId AND T1.Filename = File.Filename ) AS T1 JOIN Path ON (Path.PathId = T1.PathId) WHERE FileIndex > 0 ) UNION (SELECT ObjectName AS Path, PluginName AS Filename, FileIndex, JobId, '' AS LStat, 0 AS DeltaSeq , JobTDate FROM Job JOIN RestoreObject USING (JobId) WHERE JobId IN (1,2,3,4,5,6) ORDER BY JobTDate ASC, FileIndex ASC) ) AS U1 ORDER BY JobTDate, FileIndex ASC: ERR=near "UNION": syntax error --- bacula/src/cats/sql_get.c | 81 +++++++++++++++++++++++++++++---------- 1 file changed, 61 insertions(+), 20 deletions(-) diff --git a/bacula/src/cats/sql_get.c b/bacula/src/cats/sql_get.c index 3aaec9e20..998452d7c 100644 --- a/bacula/src/cats/sql_get.c +++ b/bacula/src/cats/sql_get.c @@ -1534,27 +1534,68 @@ bool BDB::bdb_get_file_list(JCR *jcr, char *jobids, int opts, Mmsg(buf2, select_recent_version_with_basejob[bdb_get_type_index()], jobids, jobids, jobids, jobids); } - /* During virtual full, we want to include Objects in the BSR */ - if (opts & DBL_USE_OBJ) { - Mmsg(buf3, - "UNION (SELECT ObjectName AS Path, PluginName AS Filename, FileIndex, JobId, '' AS LStat, 0 AS DeltaSeq, '' AS MD5, JobTDate " - "FROM Job JOIN RestoreObject USING (JobId) " - "WHERE JobId IN (%s) ORDER BY JobTDate ASC, FileIndex ASC) ", jobids); - } - /* bsr code is optimized for JobId sorted, with Delta, we need to get - * them ordered by date. JobTDate and JobId can be mixed if using Copy - * or Migration - */ - Mmsg(buf, -"SELECT Path, Filename, FileIndex, JobId, LStat, DeltaSeq, MD5, JobTDate " -"FROM ((" - "SELECT Path.Path, T1.Filename, T1.FileIndex, T1.JobId, LStat, DeltaSeq, MD5, JobTDate " - "FROM ( %s ) AS T1 " - "JOIN Path ON (Path.PathId = T1.PathId) %s " - ") %s ) AS U1 ORDER BY JobTDate, FileIndex ASC",/* Return sorted by JobTDate */ - /* FileIndex for restore code */ - buf2.c_str(), type, buf3.c_str()); + if (bdb_get_type_index() == SQL_TYPE_SQLITE3) { + /* This is a SQLite version of the query that could replace the + * pgsql/mysql that is left untouched below. + * The problem is that sqlite don't like parenthesis to manage UNION like + * in (select * from table1) UNION (select * from table2) + * the parenthesis were required because of two "order by" like this: + * select * from ( + * (select * from tableXX) + * UNION + * (select * from tableYY order by WW)) + * order by WW + * but the "before last order by" is not required because it is identical to + * the last one and then the parenthesis can be removed to get something like : + * select * from + * ( + * select * from tableXX + * UNION + * select * from tableYY + * ) + * order by WW + */ + if (opts & DBL_USE_OBJ) { + Mmsg(buf3, + "UNION SELECT ObjectName AS Path, PluginName AS Filename, FileIndex, JobId, '' AS LStat, 0 AS DeltaSeq, '' AS MD5, JobTDate " + "FROM Job JOIN RestoreObject USING (JobId) " + "WHERE JobId IN (%s) ", jobids); + } + /* bsr code is optimized for JobId sorted, with Delta, we need to get + * them ordered by date. JobTDate and JobId can be mixed if using Copy + * or Migration + */ + Mmsg(buf, + "SELECT Path, Filename, FileIndex, JobId, LStat, DeltaSeq, MD5, JobTDate " + "FROM (" + "SELECT Path.Path, T1.Filename, T1.FileIndex, T1.JobId, LStat, DeltaSeq, MD5, JobTDate " + "FROM ( %s ) AS T1 " + "JOIN Path ON (Path.PathId = T1.PathId) %s " + " %s ) AS U1 ORDER BY JobTDate, FileIndex ASC",/* Return sorted by JobTDate */ + /* FileIndex for restore code */ + buf2.c_str(), type, buf3.c_str()); + } else { + if (opts & DBL_USE_OBJ) { + Mmsg(buf3, + "UNION (SELECT ObjectName AS Path, PluginName AS Filename, FileIndex, JobId, '' AS LStat, 0 AS DeltaSeq, '' AS MD5, JobTDate " + "FROM Job JOIN RestoreObject USING (JobId) " + "WHERE JobId IN (%s) ORDER BY JobTDate ASC, FileIndex ASC) ", jobids); + } + /* bsr code is optimized for JobId sorted, with Delta, we need to get + * them ordered by date. JobTDate and JobId can be mixed if using Copy + * or Migration + */ + Mmsg(buf, + "SELECT Path, Filename, FileIndex, JobId, LStat, DeltaSeq, MD5, JobTDate " + "FROM ((" + "SELECT Path.Path, T1.Filename, T1.FileIndex, T1.JobId, LStat, DeltaSeq, MD5, JobTDate " + "FROM ( %s ) AS T1 " + "JOIN Path ON (Path.PathId = T1.PathId) %s " + ") %s ) AS U1 ORDER BY JobTDate, FileIndex ASC",/* Return sorted by JobTDate */ + /* FileIndex for restore code */ + buf2.c_str(), type, buf3.c_str()); + } if (!(opts & DBL_USE_MD5)) { strip_md5(buf.c_str()); -- 2.47.3