FOSSology  4.4.0
Open Source License Compliance by Open Source Software
OjosDatabaseHandler.cc
Go to the documentation of this file.
1 /*
2  SPDX-FileCopyrightText: © 2019 Siemens AG
3 
4  SPDX-License-Identifier: GPL-2.0-only
5 */
11 #include "OjosDatabaseHandler.hpp"
12 
13 using namespace fo;
14 using namespace std;
15 
22 {
23 }
24 
33  int uploadId, int agentId, bool ignoreFilesWithMimeType)
34 {
35  return queryFileIdsVectorForUpload(uploadId, agentId, ignoreFilesWithMimeType);
36 }
37 
45 {
46  DbManager spawnedDbMan(dbManager.spawn());
47  return OjosDatabaseHandler(spawnedDbMan);
48 }
49 
56  OjoDatabaseEntry &entry) const
57 {
58  QueryResult queryResult = dbManager.execPrepared(
59  fo_dbManager_PrepareStamement(dbManager.getStruct_dbManager(),
60  "ojoInsertLicense",
61  "INSERT INTO license_file"
62  "(rf_fk, agent_fk, pfile_fk)"
63  " VALUES($1,$2,$3) RETURNING fl_pk",
64  long, long, long),
65  entry.license_fk, entry.agent_fk, entry.pfile_fk);
66  vector<unsigned long> res = queryResult.getSimpleResults<unsigned long>(0,
68  if (res.size() > 0)
69  {
70  return res.at(0);
71  }
72  else
73  {
74  return -1;
75  }
76 }
77 
85  const unsigned long fl_fk) const
86 {
87  if (fl_fk < 1)
88  {
89  return false;
90  }
91  return dbManager.execPrepared(
92  fo_dbManager_PrepareStamement(dbManager.getStruct_dbManager(),
93  "ojoInsertHighlight",
94  "INSERT INTO highlight"
95  "(fl_fk, start, len, type)"
96  " VALUES($1,$2,$3,'L')",
97  long, long, long
98  ),
99  fl_fk, match.start,
100  match.len);
101 }
102 
109  OjoDatabaseEntry &entry) const
110 {
111  return dbManager.execPrepared(
112  fo_dbManager_PrepareStamement(dbManager.getStruct_dbManager(),
113  "ojoInsertNoLicense",
114  "INSERT INTO license_file"
115  "(agent_fk, pfile_fk)"
116  " VALUES($1,$2)",
117  long, long
118  ),
119  entry.agent_fk, entry.pfile_fk);
120 }
121 
128 bool hasEnding(string const &firstString, string const &ending)
129 {
130  if (firstString.length() >= ending.length())
131  {
132  return (0
133  == firstString.compare(firstString.length() - ending.length(),
134  ending.length(), ending));
135  }
136  else
137  {
138  return false;
139  }
140 }
141 
161  string rfShortName, const int groupId, const int userId)
162 {
163  bool success = false;
164  unsigned long result = 0;
165 
166  icu::UnicodeString unicodeCleanShortname = fo::recodeToUnicode(rfShortName);
167 
168  // Clean shortname to get utf8 string
169  rfShortName = "";
170  unicodeCleanShortname.toUTF8String(rfShortName);
171 
172  fo_dbManager_PreparedStatement *searchWithOr = fo_dbManager_PrepareStamement(
174  "selectLicenseIdWithOrOJO",
175  "WITH mainLicense AS ("
176  " SELECT rf_pk, 1 AS prior FROM ONLY license_ref"
177  " WHERE LOWER(rf_shortname) = LOWER($1)"
178  " OR LOWER(rf_shortname) = LOWER($2)"
179  "), candidateLicense AS ("
180  " SELECT rf_pk, 2 AS prior FROM license_candidate"
181  " WHERE (LOWER(rf_shortname) = LOWER($1)"
182  " OR LOWER(rf_shortname) = LOWER($2))"
183  " AND group_fk = $3"
184  ")"
185  "SELECT rf_pk, prior FROM mainLicense "
186  "UNION "
187  "SELECT rf_pk, prior FROM candidateLicense "
188  "ORDER BY prior;",
189  char*, char*, int);
190 
191  /* First check similar matches */
192  /* Check if the name ends with +, -or-later, -only */
193  if (hasEnding(rfShortName, "+") || hasEnding(rfShortName, "-or-later"))
194  {
195  string tempShortName(rfShortName);
196  /* Convert shortname to lower-case */
197  std::transform(tempShortName.begin(), tempShortName.end(), tempShortName.begin(),
198  ::tolower);
199  string plus("+");
200  string orLater("-or-later");
201 
202  unsigned long int plusLast = tempShortName.rfind(plus);
203  unsigned long int orLaterLast = tempShortName.rfind(orLater);
204 
205  /* Remove last occurrence of + and -or-later (if found) */
206  if (plusLast != string::npos)
207  {
208  tempShortName.erase(plusLast, string::npos);
209  }
210  if (orLaterLast != string::npos)
211  {
212  tempShortName.erase(orLaterLast, string::npos);
213  }
214 
215  QueryResult queryResult = dbManager.execPrepared(searchWithOr,
216  (tempShortName + plus).c_str(), (tempShortName + orLater).c_str(),
217  groupId);
218 
219  success = queryResult && queryResult.getRowCount() > 0;
220  if (success)
221  {
222  result = queryResult.getSimpleResults<unsigned long>(0, fo::stringToUnsignedLong)[0];
223  }
224  }
225  else
226  {
227  string tempShortName(rfShortName);
228  /* Convert shortname to lower-case */
229  std::transform(tempShortName.begin(), tempShortName.end(), tempShortName.begin(),
230  ::tolower);
231  string only("-only");
232 
233  unsigned long int onlyLast = tempShortName.rfind(only);
234 
235  /* Remove last occurrence of -only (if found) */
236  if (onlyLast != string::npos)
237  {
238  tempShortName.erase(onlyLast, string::npos);
239  }
240 
241  QueryResult queryResult = dbManager.execPrepared(searchWithOr,
242  tempShortName.c_str(), (tempShortName + only).c_str(), groupId);
243 
244  success = queryResult && queryResult.getRowCount() > 0;
245  if (success)
246  {
247  result = queryResult.getSimpleResults<unsigned long>(0, fo::stringToUnsignedLong)[0];
248  }
249  }
250 
251  if (result > 0)
252  {
253  return result;
254  }
255 
256  if (groupId < 1)
257  {
258  return 0;
259  }
260 
261  if (userId < 1)
262  {
263  return 0;
264  }
265 
266  unsigned count = 0;
267  while ((!success) && count++ < 3)
268  {
269  if (!dbManager.begin())
270  continue;
271 
272  dbManager.queryPrintf("LOCK TABLE license_ref");
273 
274  QueryResult queryResult =
276  fo_dbManager_PrepareStamement(dbManager.getStruct_dbManager(),
277  "selectOrInsertLicenseIdForNameOjo",
278  "WITH "
279  "selectExisting AS ("
280  "SELECT rf_pk FROM ONLY license_ref"
281  " WHERE LOWER(rf_shortname) = LOWER($1)"
282  "),"
283  "insertNew AS ("
284  "INSERT INTO license_candidate"
285  "(rf_shortname, rf_text, rf_detector_type, group_fk, "
286  "rf_user_fk_created, rf_user_fk_modified)"
287  " SELECT $1, $2, $3, $4, $5, $5"
288  " WHERE NOT EXISTS(SELECT * FROM selectExisting)"
289  " RETURNING rf_pk"
290  ") "
291 
292  "SELECT rf_pk FROM insertNew "
293  "UNION "
294  "SELECT rf_pk FROM selectExisting",
295  char*, char*, int, int, int
296  ),
297  rfShortName.c_str(), "License by OJO.", 3, groupId, userId);
298 
299  success = queryResult && queryResult.getRowCount() > 0;
300 
301  if (success)
302  {
303  success &= dbManager.commit();
304 
305  if (success)
306  {
307  result = queryResult.getSimpleResults(0, fo::stringToUnsignedLong)[0];
308  }
309  }
310  else
311  {
313  }
314  }
315 
316  return result;
317 }
318 
331  string const &rfShortName, const int groupId, const int userId)
332 {
333  unsigned long licenseId = getCachedLicenseIdForName(rfShortName);
334  if (licenseId == 0)
335  {
336  licenseId = selectOrInsertLicenseIdForName(rfShortName, groupId, userId);
337  licenseRefCache.insert(std::make_pair(rfShortName, licenseId));
338  }
339  return licenseId;
340 }
341 
348  string const &rfShortName) const
349 {
350  std::unordered_map<string, long>::const_iterator findIterator =
351  licenseRefCache.find(rfShortName);
352  if (findIterator != licenseRefCache.end())
353  {
354  return findIterator->second;
355  }
356  else
357  {
358  return 0;
359  }
360 }
bool hasEnding(string const &firstString, string const &ending)
Database handler for OJO.
unsigned long getCachedLicenseIdForName(std::string const &rfShortName) const
OjosDatabaseHandler spawn() const
std::vector< unsigned long > queryFileIdsForUpload(int uploadId, int agentId, bool ignoreFilesWithMimeType)
bool insertNoResultInDatabase(OjoDatabaseEntry &entry) const
Save no result to the database.
bool saveHighlightToDatabase(const ojomatch &match, const unsigned long fl_fk) const
unsigned long saveLicenseToDatabase(OjoDatabaseEntry &entry) const
Save findings to the database if agent was called by scheduler.
std::unordered_map< std::string, long > licenseRefCache
OjosDatabaseHandler(fo::DbManager dbManager)
unsigned long selectOrInsertLicenseIdForName(std::string rfShortname, const int groupId, const int userId)
unsigned long getLicenseIdForName(std::string const &rfShortName, const int groupId, const int userId)
Get the license id for a given short name.
Database handler for agents.
std::vector< unsigned long > queryFileIdsVectorForUpload(int uploadId, bool ignoreFilesWithMimeType) const
Get pfile ids for a given upload id.
DbManager dbManager
DbManager to use.
DB wrapper for agents.
QueryResult execPrepared(fo_dbManager_PreparedStatement *stmt,...) const
Execute a prepared statement with new parameters.
QueryResult queryPrintf(const char *queryFormat,...) const
Execute a query in printf format.
fo_dbManager * getStruct_dbManager() const
DbManager spawn() const
Wrapper for DB result.
std::vector< T > getSimpleResults(int columnN, T(functionP)(const char *)) const
Get vector of a single column from query result.
fo_dbManager * dbManager
fo_dbManager object
Definition: process.c:16
fo namespace holds the FOSSology library functions.
unsigned long stringToUnsignedLong(const char *string)
Definition: libfossUtils.cc:20
icu::UnicodeString recodeToUnicode(const std::string &input)
Definition: libfossUtils.cc:46
const unsigned long int license_fk
const unsigned long int agent_fk
const unsigned long int pfile_fk
Store the results of a regex match.
Definition: scanners.hpp:28
const int start
Definition: scanners.hpp:35
Store the results of a regex match.
Definition: ojomatch.hpp:17