@@ -3,7 +3,7 @@ import { open, Database } from "sqlite";
33import { DataTable } from "./interfaces/database-interface" ;
44import { resolve } from "path" ;
55import { rejects } from "assert" ;
6- import { GetQuery , TableData , RadData } from "./types" ;
6+ import { GetQuery , TableData , InsertData , UpdateData } from "./types" ;
77import { error } from "console" ;
88
99export class DatabaseController {
@@ -68,6 +68,29 @@ export class DatabaseController {
6868 ` ) ;
6969 }
7070
71+ // Will probably remove, decided to change id to ROWID to add efficiency
72+ private async initializeViews ( ) : Promise < void > {
73+ const paperView = `CREATE VIEW paper_view AS
74+ SELECT
75+ ROWID AS id,
76+ year,
77+ paper_name,
78+ part_no,
79+ type,
80+ manufacturer,
81+ data_type,
82+ testing_location,
83+ testing_type
84+ FROM paper` ;
85+ await this . db . run ( paperView , ( err : any ) => {
86+ if ( err ) {
87+ console . error ( `Error creating paper view: ${ err } ` ) ;
88+ } else {
89+ console . log ( "View created successfully." ) ;
90+ }
91+ } ) ;
92+ }
93+
7194 /*
7295 * Parameters:
7396 * - tableName (string): the name of the table to check
@@ -99,15 +122,15 @@ export class DatabaseController {
99122 * created in the 'author_paper_join' table for each author.
100123 * Returns: None
101124 */
102- async insertPaper ( paperData : TableData ) : Promise < void > {
125+ async insertPaper ( paperData : InsertData ) : Promise < void > {
103126 if ( ! this . db ) {
104127 throw new Error ( `Database not initialized` ) ;
105128 }
106129 try {
107130 const paperId = await this . createPaper ( paperData ) ;
108131 console . log ( paperData . author ) ;
109132 for ( const author in paperData . author ) {
110- const authorRowId = await this . getOrCreateAuthor (
133+ const authorRowId = await this . getOrCreateAuthorByName (
111134 paperData . author [ author ] ,
112135 ) ;
113136 await this . linkPaperToAuthor ( authorRowId , paperId ) ;
@@ -120,14 +143,36 @@ export class DatabaseController {
120143 }
121144 }
122145
146+ /*
147+ * !!! NOTE !!!!
148+ * paperData MUST contain the ROWID of the paper for proper update purposes.
149+ *
150+ * Parameters:
151+ * - paperData: Data to be updated coresponding to a sepcific paper
152+ * Function: Updates an entry for the given paper in the 'paper' table and
153+ * entries in the 'author' and 'author_paper_join' are updated.
154+ * Returns: None
155+ */
156+ async updatePaper ( paperData : UpdateData ) : Promise < void > {
157+ if ( ! this . db ) {
158+ throw new Error ( `Database not initialized` ) ;
159+ }
160+ try {
161+ await this . updatePaperTable ( paperData ) ;
162+ if ( paperData . author ) {
163+ await this . syncPaperAuthors ( paperData . ROWID , paperData . author ) ;
164+ }
165+ } catch ( error ) { }
166+ }
167+
123168 /*
124169 * Parameters:
125170 * - paperData: An insertData instance
126171 * Function: Uses the given data to create an entry in the table cotaining the papers
127172 * Returns:
128173 * - number: The ROWID of the paper.
129174 */
130- private async createPaper ( paperData : TableData ) : Promise < number > {
175+ private async createPaper ( paperData : InsertData ) : Promise < number > {
131176 if ( ! this . db ) {
132177 throw new Error ( `Database not initialized` ) ;
133178 }
@@ -165,6 +210,34 @@ export class DatabaseController {
165210 }
166211 }
167212
213+ private async updatePaperTable ( paperData : UpdateData ) : Promise < void > {
214+ let query = `UPDATE paper SET ` ;
215+ let conditions : string [ ] = [ ] ;
216+ const params : string [ ] = [ ] ;
217+ if ( ! this . db ) {
218+ throw new Error ( `Database not initialized` ) ;
219+ }
220+ try {
221+ for ( const [ key , value ] of Object . entries ( paperData ) ) {
222+ if (
223+ value !== undefined &&
224+ value !== null &&
225+ key !== "author" &&
226+ key !== "ROWID"
227+ ) {
228+ conditions . push ( `${ key } = ?` ) ;
229+ params . push ( `${ value } ` ) ;
230+ }
231+ }
232+ params . push ( `${ paperData . ROWID } ` ) ;
233+ query += `${ conditions . join ( "," ) } WHERE ROWID = ?` ;
234+ await this . db . run ( query , params ) ;
235+ } catch ( error ) {
236+ console . error ( error ) ;
237+ throw error ;
238+ }
239+ }
240+
168241 /*
169242 * Parameters:
170243 * - author: the name of the author to be added/retrieved
@@ -173,7 +246,7 @@ export class DatabaseController {
173246 * Returns:
174247 * - number: The ROWID of the author.
175248 */
176- private async getOrCreateAuthor ( author : string ) : Promise < number > {
249+ private async getOrCreateAuthorByName ( author : string ) : Promise < number > {
177250 if ( ! this . db ) {
178251 throw new Error ( `Database not initialized` ) ;
179252 }
@@ -197,6 +270,100 @@ export class DatabaseController {
197270 }
198271 }
199272
273+ /*
274+ * Parameters:
275+ * - authors: List of authors given when update is passed
276+ * - paperId: Id of the paper to update
277+ * Function: Compares the new list of authors to the current links, if it is
278+ * found that a preexisting link should no longer exist, it is removed.
279+ * If a new link is needed, it is created.
280+ * Returns: None
281+ */
282+ private async syncPaperAuthors (
283+ paperId : number ,
284+ authors : string [ ] ,
285+ ) : Promise < void > {
286+ if ( ! this . db ) {
287+ throw new Error ( `Database not initialized` ) ;
288+ }
289+
290+ try {
291+ // Begin transaction for consistency
292+ await this . db . exec ( "BEGIN TRANSACTION" ) ;
293+
294+ // Retrieve the current authors linked to the paper
295+ const currentAuthors = await this . db . all <
296+ { author_id : number ; name : string } [ ]
297+ > (
298+ `
299+ SELECT a.name
300+ FROM paper_author_join paj
301+ INNER JOIN author a ON paj.author_id = a.ROWID
302+ WHERE paj.paper_id = ?
303+ ` ,
304+ [ paperId ] ,
305+ ) ;
306+
307+ // Extract names of current authors
308+ const currentAuthorNames = currentAuthors . map ( ( author ) => author . name ) ;
309+
310+ // Identify authors to add
311+ const authorsToAdd = authors . filter (
312+ ( author ) => ! currentAuthorNames . includes ( author ) ,
313+ ) ;
314+
315+ // Identify authors to remove
316+ const authorsToRemove = currentAuthorNames . filter (
317+ ( author ) => ! authors . includes ( author ) ,
318+ ) ;
319+
320+ // Add new author links
321+ for ( const authorName of authorsToAdd ) {
322+ // Ensure the author exists in the `author` table
323+ const row = await this . db . get < { ROWID : number } > (
324+ `
325+ INSERT OR IGNORE INTO author (name) VALUES (?);
326+ SELECT ROWID FROM author WHERE name = ?;
327+ ` ,
328+ [ authorName , authorName ] ,
329+ ) ;
330+
331+ if ( ! row || typeof row . ROWID !== "number" ) {
332+ throw new Error ( `Failed to retrieve ROWID for author: ${ authorName } ` ) ;
333+ }
334+ // Link the author to the paper using the retrieved ROWID
335+ await this . db . run (
336+ `
337+ INSERT INTO paper_author_join (paper_id, author_id) VALUES (?, ?)
338+ ` ,
339+ [ paperId , row . ROWID ] ,
340+ ) ;
341+ }
342+
343+ // Remove unwanted author links
344+ for ( const authorName of authorsToRemove ) {
345+ await this . db . run (
346+ `
347+ DELETE FROM paper_author_join
348+ WHERE paper_id = ?
349+ AND author_id = (SELECT ROWID FROM author WHERE name = ?)
350+ ` ,
351+ [ paperId , authorName ] ,
352+ ) ;
353+ }
354+
355+ // Commit the transaction
356+ await this . db . exec ( "COMMIT" ) ;
357+ } catch ( error ) {
358+ // Rollback the transaction on error
359+ await this . db . exec ( "ROLLBACK" ) ;
360+ console . error (
361+ `Failed to sync authors for paperID: ${ paperId } \nError: ${ error } ` ,
362+ ) ;
363+ throw error ;
364+ }
365+ }
366+
200367 /*
201368 * Parameters:
202369 * - authorId: The ROWID of the author to link
@@ -212,8 +379,12 @@ export class DatabaseController {
212379 ) : Promise < void > {
213380 try {
214381 await this . db . run (
215- "INSERT INTO paper_author_join (paper_id, author_id) VALUES (?, ?)" ,
216- [ paperId , authorId ] ,
382+ `INSERT INTO paper_author_join (paper_id, author_id)
383+ SELECT ?, ?
384+ WHERE NOT EXISTS (
385+ SELECT 1 FROM paper_author_join WHERE paper_id = ? AND author_id = ?
386+ )` ,
387+ [ paperId , authorId , paperId , authorId ] ,
217388 ) ;
218389 } catch ( error ) {
219390 console . error (
@@ -223,6 +394,35 @@ export class DatabaseController {
223394 }
224395 }
225396
397+ /*
398+ * Parameters:
399+ * - authorId: The ROWID of the author to check
400+ * - paperId: The ROWID of the paper to checl
401+ * Function: Checks for the existence of an entry in author_paper_join table.
402+ * This
403+ * Returns: None
404+ */
405+ private async checkPaperToAuthorLink (
406+ authorId : number ,
407+ paperId : number ,
408+ ) : Promise < boolean > {
409+ if ( ! this . db ) {
410+ throw new Error ( `Database not initialized` ) ;
411+ }
412+ try {
413+ const row = await this . db . get (
414+ "SELECT * FROM paper_author_join WHERE paper_id = ? AND author_id = ?" ,
415+ [ paperId , authorId ] ,
416+ ) ;
417+ return ! ! row ; // Return true if a row is found, otherwise false
418+ } catch ( error ) {
419+ console . error (
420+ `Problem retrieving paper-author link for authorID: ${ authorId } , paperID: ${ paperId } \n Error: ${ error } ` ,
421+ ) ;
422+ throw error ;
423+ }
424+ }
425+
226426 /*
227427 * Parameters: None
228428 * Function: Gets the total number of papers in the table 'paper'
@@ -262,7 +462,6 @@ export class DatabaseController {
262462 let query = `
263463 SELECT
264464 p.*,
265- p.ROWID AS id,
266465 GROUP_CONCAT(a.name, ', ') AS author
267466 FROM
268467 paper p
@@ -278,7 +477,6 @@ export class DatabaseController {
278477
279478 return new Promise < TableData [ ] > ( async ( resolve , reject ) => {
280479 try {
281-
282480 const result = await this . db . all ( query , `${ search } %` ) ;
283481 console . log ( "Query executed successfully:" ) ;
284482
@@ -296,22 +494,15 @@ export class DatabaseController {
296494 } ) ;
297495 }
298496
299- async getFilteredData ( queryData : GetQuery ) : Promise < RadData [ ] > {
497+ async getFilteredData ( queryData : GetQuery ) : Promise < TableData [ ] > {
300498 if ( ! this . db ) {
301499 throw new Error ( "Database not initialized" ) ;
302500 }
303501
304502 // Base SELECT query
305503 let query = `
306504 SELECT
307- p.year,
308- p.paper_name,
309- p.part_no,
310- p.type,
311- p.manufacturer,
312- p.data_type,
313- p.testing_location,
314- p.testing_type,
505+ p.*,
315506 GROUP_CONCAT(a.name, ', ') AS author
316507 FROM
317508 paper p
@@ -354,13 +545,13 @@ export class DatabaseController {
354545
355546 console . log ( query ) ;
356547
357- return new Promise < RadData [ ] > ( async ( resolve , reject ) => {
548+ return new Promise < TableData [ ] > ( async ( resolve , reject ) => {
358549 try {
359550 const result = await this . db . all ( query , params ) ;
360551 console . log ( "Query executed successfully:" ) ;
361552
362553 // Map rows to RadData format
363- const radData : RadData [ ] = result . map ( ( row ) => ( {
554+ const radData : TableData [ ] = result . map ( ( row ) => ( {
364555 ...row ,
365556 author : row . author ? row . author . split ( ", " ) : [ ] ,
366557 } ) ) ;
0 commit comments