FOSSology  4.4.0
Open Source License Compliance by Open Source Software
database.cc
1 /*
2  SPDX-FileCopyrightText: © 2014-2017,2022, Siemens AG
3  Author: Daniele Fognini, Johannes Najjar
4 
5  SPDX-License-Identifier: GPL-2.0-only
6 */
7 
8 #include "database.hpp"
9 #include "identity.hpp"
10 
11 #include <iostream>
12 #include <libfossUtils.hpp>
13 
14 using namespace fo;
15 
16 #define RETURN_IF_FALSE(query) \
17  do {\
18  if (!(query)) {\
19  return false;\
20  }\
21  } while(0)
22 
27  agent_fk(0),
28  pfile_fk(0),
29  content(""),
30  hash(""),
31  type(""),
32  copy_startbyte(0),
33  copy_endbyte(0)
34 {
35 };
36 
42 {
43  DbManager spawnedDbMan(dbManager.spawn());
44  return CopyrightDatabaseHandler(spawnedDbMan);
45 }
46 
55 {
56  std::string result;
57  for (size_t i = 0; i < size; ++i)
58  {
59  if (i != 0)
60  result += ", ";
61  result += in[i].name;
62  }
63  return result;
64 }
65 
75 {
76  std::string result;
77  for (size_t i = 0; i < size; ++i)
78  {
79  if (i != 0)
80  result += ", ";
81  result += in[i].name;
82  result += " ";
83  result += in[i].type;
84  result += " ";
85  result += in[i].creationFlags;
86  }
87  return result;
88 }
89 
101 {
102  int failedCounter = 0;
103  bool tablesChecked = false;
104 
106  while (!tablesChecked && failedCounter < MAX_TABLE_CREATION_RETRIES)
107  {
108  dbManager.begin();
109 
110  tablesChecked = createTableAgentFindings() && createTableClearing();
111 
112  if (tablesChecked)
113  dbManager.commit();
114  else
115  {
117  ++failedCounter;
118  if (failedCounter < MAX_TABLE_CREATION_RETRIES)
119  std::cout << "WARNING: table creation failed: trying again"
120  " (" << failedCounter << "/" << MAX_TABLE_CREATION_RETRIES << ")"
121  << std::endl;
122  }
123  }
124  if (tablesChecked && (failedCounter > 0))
125  std::cout << "NOTICE: table creation succeded on try "
126  << failedCounter << "/" << MAX_TABLE_CREATION_RETRIES
127  << std::endl;
128 
129  dbManager.ignoreWarnings(false);
130  return tablesChecked;
131 }
132 
138  {
139 #define SEQUENCE_NAME IDENTITY"_pk_seq"
140 #define COLUMN_NAME_PK IDENTITY"_pk"
141  { COLUMN_NAME_PK, "bigint", "PRIMARY KEY DEFAULT nextval('" SEQUENCE_NAME "'::regclass)"},
142  {"agent_fk", "bigint", "NOT NULL"},
143  {"pfile_fk", "bigint", "NOT NULL"},
144  {"content", "text", ""},
145  {"hash", "text", ""},
146  {"type", "text", ""}, //TODO removed constrain: "CHECK (type in ('statement', 'email', 'url'))"},
147  {"copy_startbyte", "integer", ""},
148  {"copy_endbyte", "integer", ""},
149  {"is_enabled", "boolean", "NOT NULL DEFAULT TRUE"},
150  };
151 
158 {
159  if (!dbManager.sequenceExists(SEQUENCE_NAME))
160  {
161  RETURN_IF_FALSE(dbManager.queryPrintf("CREATE SEQUENCE "
162  SEQUENCE_NAME
163  " START WITH 1"
164  " INCREMENT BY 1"
165  " NO MAXVALUE"
166  " NO MINVALUE"
167  " CACHE 1"));
168  }
169 
170  if (!dbManager.tableExists(IDENTITY))
171  {
172  size_t ncolumns = (sizeof(CopyrightDatabaseHandler::columns) / sizeof(CopyrightDatabaseHandler::ColumnDef));
173  RETURN_IF_FALSE(dbManager.queryPrintf("CREATE table %s(%s)", IDENTITY,
175  )
176  );
177  RETURN_IF_FALSE(dbManager.queryPrintf(
178  "CREATE INDEX %s_agent_fk_index"
179  " ON %s"
180  " USING BTREE (agent_fk)",
181  IDENTITY, IDENTITY
182  ));
183 
184  RETURN_IF_FALSE(dbManager.queryPrintf(
185  "CREATE INDEX %s_hash_index"
186  " ON %s"
187  " USING BTREE (hash)",
188  IDENTITY, IDENTITY
189  ));
190 
191  RETURN_IF_FALSE(dbManager.queryPrintf(
192  "CREATE INDEX %s_pfile_fk_index"
193  " ON %s"
194  " USING BTREE (pfile_fk)",
195  IDENTITY, IDENTITY
196  ));
197 
198  RETURN_IF_FALSE(dbManager.queryPrintf(
199  "ALTER TABLE ONLY %s"
200  " ADD CONSTRAINT agent_fk"
201  " FOREIGN KEY (agent_fk)"
202  " REFERENCES agent(agent_pk) ON DELETE CASCADE",
203  IDENTITY
204  ));
205 
206  RETURN_IF_FALSE(dbManager.queryPrintf(
207  "ALTER TABLE ONLY %s"
208  " ADD CONSTRAINT pfile_fk"
209  " FOREIGN KEY (pfile_fk)"
210  " REFERENCES pfile(pfile_pk) ON DELETE CASCADE",
211  IDENTITY
212  ));
213  }
214  return true;
215 }
216 
221 #define SEQUENCE_NAMEClearing IDENTITY"_decision_pk_seq"
222  {IDENTITY"_decision_pk", "bigint", "PRIMARY KEY DEFAULT nextval('" SEQUENCE_NAMEClearing "'::regclass)"},
223  {"user_fk", "bigint", "NOT NULL"},
224  {"pfile_fk", "bigint", "NOT NULL"},
225  {"clearing_decision_type_fk", "bigint", "NOT NULL"},
226  {"description", "text", ""},
227  {"textFinding", "text", ""},
228  {"comment", "text", ""},
229  {"is_enabled", "boolean", "NOT NULL DEFAULT TRUE"}
230 };
231 
238 {
239  #define CLEARING_TABLE IDENTITY "_decision"
240 
241  if (!dbManager.sequenceExists(SEQUENCE_NAMEClearing))
242  {
243  RETURN_IF_FALSE(dbManager.queryPrintf("CREATE SEQUENCE "
244  SEQUENCE_NAMEClearing
245  " START WITH 1"
246  " INCREMENT BY 1"
247  " NO MAXVALUE"
248  " NO MINVALUE"
249  " CACHE 1"));
250  }
251 
252  if (!dbManager.tableExists(CLEARING_TABLE))
253  {
255  RETURN_IF_FALSE(dbManager.queryPrintf("CREATE table %s(%s)", CLEARING_TABLE,
257 
258  RETURN_IF_FALSE(dbManager.queryPrintf(
259  "CREATE INDEX %s_pfile_fk_index"
260  " ON %s"
261  " USING BTREE (pfile_fk)",
262  CLEARING_TABLE, CLEARING_TABLE
263  ));
264 
265  RETURN_IF_FALSE(dbManager.queryPrintf(
266  "CREATE INDEX %s_user_fk_index"
267  " ON %s"
268  " USING BTREE (user_fk)",
269  CLEARING_TABLE, CLEARING_TABLE
270  ));
271 
272  RETURN_IF_FALSE(dbManager.queryPrintf(
273  "CREATE INDEX %s_clearing_decision_type_fk_index"
274  " ON %s"
275  " USING BTREE (clearing_decision_type_fk)",
276  CLEARING_TABLE, CLEARING_TABLE
277  ));
278 
279  RETURN_IF_FALSE(dbManager.queryPrintf(
280  "ALTER TABLE ONLY %s"
281  " ADD CONSTRAINT user_fk"
282  " FOREIGN KEY (user_fk)"
283  " REFERENCES users(user_pk) ON DELETE CASCADE",
284  CLEARING_TABLE
285  ));
286 
287  RETURN_IF_FALSE(dbManager.queryPrintf(
288  "ALTER TABLE ONLY %s"
289  " ADD CONSTRAINT pfile_fk"
290  " FOREIGN KEY (pfile_fk)"
291  " REFERENCES pfile(pfile_pk) ON DELETE CASCADE",
292  CLEARING_TABLE
293  ));
294  }
295 
296  return true;
297 }
298 
306 std::vector<unsigned long> CopyrightDatabaseHandler::queryFileIdsForUpload(int agentId, int uploadId, bool ignoreFilesWithMimeType)
307 {
308  std::string uploadTreeTableName = queryUploadTreeTableName(uploadId);
309  fo_dbManager_PreparedStatement* preparedStatement;
310  std::string sql = "SELECT pfile_pk"
311  " FROM ("
312  " SELECT distinct(pfile_fk) AS PF"
313  " FROM " + uploadTreeTableName +
314  " WHERE upload_fk = $1 and (ufile_mode&x'3C000000'::int)=0"
315  " ) AS SS "
316  "LEFT OUTER JOIN " IDENTITY " ON (PF = pfile_fk AND agent_fk = $2) "
317 #ifdef IDENTITY_COPYRIGHT
318  "LEFT OUTER JOIN author AS au ON (PF = au.pfile_fk AND au.agent_fk = $2) "
319 #endif
320  "INNER JOIN pfile ON (PF = pfile_pk) "
321 #ifdef IDENTITY_COPYRIGHT
322  "WHERE copyright.copyright_pk IS NULL AND au.author_pk IS NULL"
323 #else
324  "WHERE (" IDENTITY "_pk IS NULL OR agent_fk <> $2)"
325 #endif
326  ;
327  std::string statementName = "queryFileIdsForUpload:" IDENTITY "Agent" + uploadTreeTableName;
328  if (ignoreFilesWithMimeType)
329  {
330  sql = sql + " AND (pfile_mimetypefk NOT IN ( "
331  "SELECT mimetype_pk FROM mimetype WHERE mimetype_name=ANY(string_to_array(( "
332  "SELECT conf_value FROM sysconfig WHERE variablename='SkipFiles'),','))));";
333  statementName = statementName + "withMimetype";
334  }
335  preparedStatement =
336  fo_dbManager_PrepareStamement(dbManager.getStruct_dbManager(),
337  statementName.c_str(),
338  sql.c_str(),
339  int, int);
340  QueryResult queryResult = dbManager.execPrepared(preparedStatement,
341  uploadId, agentId);
342 
343  return queryResult.getSimpleResults<unsigned long>(0, fo::stringToUnsignedLong);
344 
345 }
346 
354 {
355  std::string tableName = IDENTITY;
356 
357  if("author" == entry.type ||
358  "email" == entry.type ||
359  "url" == entry.type){
360  tableName = "author";
361  }
362 
363  return dbManager.execPrepared(
364  fo_dbManager_PrepareStamement(
366  ("insertInDatabaseFor" + tableName).c_str(),
367  ("INSERT INTO "+ tableName +
368  "(agent_fk, pfile_fk, content, hash, type, copy_startbyte, copy_endbyte)" +
369  " VALUES($1,$2,$3,md5($3),$4,$5,$6)").c_str(),
370  long, long, char*, char*, int, int
371  ),
372  entry.agent_fk, entry.pfile_fk,
373  entry.content.c_str(),
374  entry.type.c_str(),
375  entry.copy_startbyte, entry.copy_endbyte
376  );
377 }
378 
383  AgentDatabaseHandler(manager)
384 {
385 
386 }
Manages database related requests for agent.
Definition: database.hpp:53
std::vector< unsigned long > queryFileIdsForUpload(int agentId, int uploadId, bool ignoreFilesWithMimeType)
Get the list of pfile ids on which the given agent has no findings for a given upload.
Definition: database.cc:306
static const ColumnDef columns[]
Columns required by agent in database.
Definition: database.hpp:77
bool createTableAgentFindings() const
Create table to store agent find data.
Definition: database.cc:157
bool insertInDatabase(DatabaseEntry &entry) const
Insert a finding in database.
Definition: database.cc:353
static const ColumnDef columnsDecision[]
Columns required to store user decisions in database.
Definition: database.hpp:78
std::string getColumnListString(const ColumnDef in[], size_t size) const
Given a list of ColumnDef, return a comma separated list of column names.
Definition: database.cc:54
CopyrightDatabaseHandler(fo::DbManager manager)
Constructor to initialize database handler.
Definition: database.cc:382
CopyrightDatabaseHandler spawn() const
Spawn/fork a new database handler and return it.
Definition: database.cc:41
bool createTables() const
Create tables required by agent.
Definition: database.cc:100
std::string getColumnCreationString(const ColumnDef in[], size_t size) const
Return a comma delimited string with column elements separated by space. The string is used for datab...
Definition: database.cc:74
bool createTableClearing() const
Create table to store user decisions.
Definition: database.cc:237
Maps agent data to database schema.
Definition: database.hpp:25
int copy_startbyte
Definition: database.hpp:44
std::string content
Definition: database.hpp:31
std::string type
Type of statement found.
Definition: database.hpp:43
int copy_endbyte
Definition: database.hpp:45
DatabaseEntry()
Default constructor for DatabaseEntry.
Definition: database.cc:26
Database handler for agents.
std::string queryUploadTreeTableName(int uploadId)
Get the upload tree table name 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.
bool tableExists(const char *tableName) const
void ignoreWarnings(bool) const
QueryResult queryPrintf(const char *queryFormat,...) const
Execute a query in printf format.
bool sequenceExists(const char *name) const
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.
General utility functions for CPP.
fo namespace holds the FOSSology library functions.
unsigned long stringToUnsignedLong(const char *string)
Definition: libfossUtils.cc:20
Holds the column related data for table creation.
Definition: database.hpp:71