@capacitor-community/sqlite 3.5.2-dev2 → 3.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -26,6 +26,8 @@ import com.getcapacitor.community.database.sqlite.SQLite.UtilsSQLite;
26
26
  import java.io.File;
27
27
  import java.text.SimpleDateFormat;
28
28
  import java.util.ArrayList;
29
+ import java.util.Arrays;
30
+ import java.util.Collections;
29
31
  import java.util.Date;
30
32
  import java.util.Dictionary;
31
33
  import java.util.Hashtable;
@@ -545,27 +547,59 @@ public class Database {
545
547
  */
546
548
  public void findReferencesAndUpdate(Database mDB, String tableName, String whereStmt, ArrayList<Object> values) throws Exception {
547
549
  try {
548
- JSArray references = getReferences(mDB, tableName);
549
- for (int j = 0; j < references.length(); j++) {
550
+ ArrayList<String> references = getReferences(mDB, tableName);
551
+ if (references.size() == 0) {
552
+ return;
553
+ }
554
+ String tableNameWithRefs = references.get(references.size() - 1);
555
+ references.remove(references.size() - 1);
556
+ for (String refe : references) {
550
557
  // get the tableName of the reference
551
- String refTable = getReferenceTableName(references.getJSONObject(j).getString("sql"));
558
+ String refTable = getReferenceTableName(refe);
552
559
  if (refTable.length() <= 0) {
553
560
  continue;
554
561
  }
555
- // get the columnName
556
- String colName = getReferenceColumnName(references.getJSONObject(j).getString("sql"));
557
- if (refTable.length() <= 0) {
562
+ // get the withRefsNames
563
+ String[] withRefsNames = getWithRefsColumnName(refe);
564
+ if (withRefsNames.length <= 0) {
565
+ continue;
566
+ }
567
+ // get the columnNames
568
+ String[] colNames = getReferencedColumnName(refe);
569
+ if (colNames.length <= 0) {
558
570
  continue;
559
571
  }
560
572
  // update the where clause
561
- String uWhereStmt = updateWhere(whereStmt, colName);
573
+ String uWhereStmt = updateWhere(whereStmt, withRefsNames, colNames);
562
574
 
563
575
  if (uWhereStmt.length() <= 0) {
564
576
  continue;
565
577
  }
578
+ String updTableName = tableNameWithRefs;
579
+ String[] updColNames = colNames;
580
+ if (tableNameWithRefs.equals(tableName)) {
581
+ updTableName = refTable;
582
+ updColNames = withRefsNames;
583
+ }
566
584
  //update sql_deleted for this reference
567
- String stmt = "UPDATE " + refTable + " SET sql_deleted = 1 " + uWhereStmt;
568
- long lastId = prepareSQL(stmt, values, false);
585
+ String stmt = "UPDATE " + updTableName + " SET sql_deleted = 1 " + uWhereStmt;
586
+ ArrayList<Object> selValues = new ArrayList<Object>();
587
+ if (values != null && values.size() > 0) {
588
+ String[] arrVal = whereStmt.split("\\?");
589
+ if (arrVal[arrVal.length - 1].equals(";")) {
590
+ Arrays.copyOf(arrVal, arrVal.length - 1);
591
+ }
592
+ for (int j = 0; j < arrVal.length; j++) {
593
+ for (String updVal : updColNames) {
594
+ int idxVal = arrVal[j].indexOf(updVal);
595
+ if (idxVal > -1) {
596
+ selValues.add(values.get(j));
597
+ }
598
+ }
599
+ }
600
+ }
601
+
602
+ long lastId = prepareSQL(stmt, selValues, false);
569
603
  if (lastId == -1) {
570
604
  String msg = "UPDATE sql_deleted failed for references " + "table: " + refTable + ";";
571
605
  throw new Exception(msg);
@@ -587,47 +621,104 @@ public class Database {
587
621
  */
588
622
  public String getReferenceTableName(String refValue) {
589
623
  String tableName = "";
590
- if (refValue.length() > 0 && refValue.substring(0, 12).equalsIgnoreCase("CREATE TABLE")) {
591
- Integer oPar = refValue.indexOf("(");
592
- tableName = refValue.substring(13, oPar).trim();
593
- }
624
+ if (refValue.length() > 0) {
625
+ String[] arr = refValue.split("(?i)REFERENCES", -1);
626
+ if (arr.length == 2) {
627
+ int oPar = arr[1].indexOf("(");
594
628
 
629
+ tableName = arr[1].substring(0, oPar).trim();
630
+ }
631
+ }
595
632
  return tableName;
596
633
  }
597
634
 
598
635
  /**
599
- * GetReferenceColumnName method
636
+ * GetWithRefsColumnName
637
+ *
638
+ * @param refValue
639
+ * @return
640
+ */
641
+ public String[] getWithRefsColumnName(String refValue) {
642
+ String[] colNames = new String[0];
643
+ if (refValue.length() > 0) {
644
+ String[] arr = refValue.split("(?i)REFERENCES", -1);
645
+ if (arr.length == 2) {
646
+ int oPar = arr[0].indexOf("(");
647
+ int cPar = arr[0].indexOf(")");
648
+ String colStr = arr[0].substring(oPar + 1, cPar).trim();
649
+ colNames = colStr.split(",");
650
+ }
651
+ }
652
+ return colNames;
653
+ }
654
+
655
+ /**
656
+ * GetReferencedColumnName method
600
657
  *
601
658
  * @param refValue
602
659
  * @return
603
660
  */
604
- public String getReferenceColumnName(String refValue) {
605
- String colName = "";
661
+ public String[] getReferencedColumnName(String refValue) {
662
+ String[] colNames = new String[0];
606
663
  if (refValue.length() > 0) {
607
- Integer index = refValue.toLowerCase().indexOf("FOREIGN KEY".toLowerCase());
608
- String stmt = refValue.substring(index + 12);
609
- Integer oPar = stmt.indexOf("(");
610
- Integer cPar = stmt.indexOf(")");
611
- colName = stmt.substring(oPar + 1, cPar).trim();
664
+ String[] arr = refValue.split("(?i)REFERENCES", -1);
665
+ if (arr.length == 2) {
666
+ int oPar = arr[1].indexOf("(");
667
+ int cPar = arr[1].indexOf(")");
668
+ String colStr = arr[1].substring(oPar + 1, cPar).trim();
669
+ colNames = colStr.split(",");
670
+ }
612
671
  }
613
- return colName;
672
+ return colNames;
614
673
  }
615
674
 
616
675
  /**
617
676
  * UpdateWhere method
618
677
  *
619
678
  * @param whStmt
620
- * @param colName
679
+ * @param withRefsNames
680
+ * @param colNames
621
681
  * @return
622
682
  */
623
- public String updateWhere(String whStmt, String colName) {
683
+ public String updateWhere(String whStmt, String[] withRefsNames, String[] colNames) {
624
684
  String whereStmt = "";
625
685
  if (whStmt.length() > 0) {
626
686
  Integer index = whStmt.toLowerCase().indexOf("WHERE".toLowerCase());
627
687
  String stmt = whStmt.substring(index + 6);
628
- Integer fEqual = stmt.indexOf("=");
629
- String whereColName = stmt.substring(0, fEqual).trim();
630
- whereStmt = whStmt.replaceFirst(whereColName, colName);
688
+ if (withRefsNames.length == colNames.length) {
689
+ for (int i = 0; i < withRefsNames.length; i++) {
690
+ String colType = "withRefsNames";
691
+ int idx = stmt.indexOf(withRefsNames[i]);
692
+ if (idx == -1) {
693
+ idx = stmt.indexOf(colNames[i]);
694
+ colType = "colNames";
695
+ }
696
+ if (idx > -1) {
697
+ String valStr = "";
698
+ int fEqual = stmt.indexOf("=", idx);
699
+ if (fEqual > -1) {
700
+ int iAnd = stmt.indexOf("AND", fEqual);
701
+ int ilAnd = stmt.indexOf("and", fEqual);
702
+ if (iAnd > -1) {
703
+ valStr = (stmt.substring(fEqual + 1, iAnd - 1)).trim();
704
+ } else if (ilAnd > -1) {
705
+ valStr = (stmt.substring(fEqual + 1, ilAnd - 1)).trim();
706
+ } else {
707
+ valStr = (stmt.substring(fEqual + 1)).trim();
708
+ }
709
+ if (i > 0) {
710
+ whereStmt += " AND ";
711
+ }
712
+ if (colType.equals("withRefsNames")) {
713
+ whereStmt += colNames[i] + " = " + valStr;
714
+ } else {
715
+ whereStmt += withRefsNames[i] + " = " + valStr;
716
+ }
717
+ }
718
+ }
719
+ }
720
+ whereStmt = "WHERE " + whereStmt;
721
+ }
631
722
  }
632
723
  return whereStmt;
633
724
  }
@@ -640,21 +731,49 @@ public class Database {
640
731
  * @return
641
732
  * @throws Exception
642
733
  */
643
- public JSArray getReferences(Database mDB, String tableName) throws Exception {
734
+ public ArrayList<String> getReferences(Database mDB, String tableName) throws Exception {
644
735
  String sqlStmt =
645
736
  "SELECT sql FROM sqlite_master " +
646
- "WHERE sql LIKE('%REFERENCES%') AND " +
737
+ "WHERE sql LIKE('%FOREIGN KEY%') AND sql LIKE('%REFERENCES%') AND " +
647
738
  "sql LIKE('%" +
648
739
  tableName +
649
740
  "%') AND sql LIKE('%ON DELETE%');";
650
741
  try {
651
742
  JSArray references = mDB.selectSQL(sqlStmt, new ArrayList<Object>());
652
- return references;
743
+ ArrayList<String> retRefs = new ArrayList<String>();
744
+ if (references.length() > 0) {
745
+ retRefs = getRefs(references.getJSONObject(0).getString("sql"));
746
+ }
747
+ return retRefs;
653
748
  } catch (Exception e) {
654
749
  throw new Exception(e.getMessage());
655
750
  }
656
751
  }
657
752
 
753
+ /**
754
+ * GetRefs
755
+ *
756
+ * @param str
757
+ * @return
758
+ * @throws Exception
759
+ */
760
+ private ArrayList<String> getRefs(String str) throws Exception {
761
+ ArrayList<String> retRefs = new ArrayList<String>();
762
+ String[] arrFor = str.split("(?i)FOREIGN KEY", -1);
763
+ // Loop through Foreign Keys
764
+ for (int i = 1; i < arrFor.length; i++) {
765
+ retRefs.add((arrFor[i].split("(?i)ON DELETE", -1))[0].trim());
766
+ }
767
+ // find table name with references
768
+ if (str.substring(0, 12).toLowerCase().equals("CREATE TABLE".toLowerCase())) {
769
+ int oPar = str.indexOf("(");
770
+ String tableName = str.substring(13, oPar).trim();
771
+ retRefs.add(tableName);
772
+ }
773
+
774
+ return retRefs;
775
+ }
776
+
658
777
  /**
659
778
  * SelectSQL Method
660
779
  * Query a raw sql statement with or without binding values
@@ -342,7 +342,9 @@ class UtilsSQLite {
342
342
  if (trimStmt === 'DELETE FROM' &&
343
343
  stmt.toLowerCase().includes('WHERE'.toLowerCase())) {
344
344
  const whereStmt = `${stmt.trim()};`;
345
+ console.log(`in utilsSQLite execute whereStmt ${whereStmt}`);
345
346
  const rStmt = await this.deleteSQL(mDB, whereStmt, []);
347
+ console.log(`in utilsSQLite execute rStmt ${rStmt}`);
346
348
  resArr.push(rStmt);
347
349
  }
348
350
  else {
@@ -351,12 +353,14 @@ class UtilsSQLite {
351
353
  }
352
354
  sqlStmt = resArr.join(';');
353
355
  }
356
+ console.log(`in utilsSQLite execute sqlStmt ${sqlStmt}`);
354
357
  await this.execDB(mDB, sqlStmt);
355
358
  changes = (await this.dbChanges(mDB)) - initChanges;
356
359
  return Promise.resolve(changes);
357
360
  }
358
361
  catch (err) {
359
- return Promise.reject(`Execute: ${err.message}`);
362
+ const msg = err.message ? err.message : err;
363
+ return Promise.reject(`Execute: ${msg}`);
360
364
  }
361
365
  }
362
366
  /**
@@ -368,7 +372,8 @@ class UtilsSQLite {
368
372
  return new Promise((resolve, reject) => {
369
373
  mDB.exec(sql, async (err) => {
370
374
  if (err) {
371
- reject(`Execute: ${err.message}: `);
375
+ console.log(`in execDB err: ${JSON.stringify(err)}`);
376
+ reject(`Execute: ${err}: `);
372
377
  }
373
378
  resolve();
374
379
  });
@@ -440,9 +445,12 @@ class UtilsSQLite {
440
445
  async runExec(db, stmt, values = []) {
441
446
  return new Promise((resolve, reject) => {
442
447
  if (values != null && values.length > 0) {
448
+ console.log(`in runExec stmt: ${stmt} values: ${values}`);
443
449
  db.run(stmt, values, (err) => {
444
450
  if (err) {
445
- reject(err.message);
451
+ console.log(`in runExec err1: ${JSON.stringify(err)}`);
452
+ const msg = err.message ? err.message : err;
453
+ reject(msg);
446
454
  }
447
455
  else {
448
456
  resolve();
@@ -452,7 +460,9 @@ class UtilsSQLite {
452
460
  else {
453
461
  db.exec(stmt, (err) => {
454
462
  if (err) {
455
- reject(err.message);
463
+ console.log(`in runExec err2: ${JSON.stringify(err)}`);
464
+ const msg = err.message ? err.message : err;
465
+ reject(msg);
456
466
  }
457
467
  else {
458
468
  resolve();
@@ -499,13 +509,14 @@ class UtilsSQLite {
499
509
  .substring('DELETE FROM'.length)
500
510
  .trim();
501
511
  sqlStmt = `UPDATE ${tableName} SET sql_deleted = 1 ${clauseStmt}`;
512
+ console.log(`in deleteSQL sqlStmt: ${sqlStmt}`);
502
513
  // Find REFERENCES if any and update the sql_deleted column
503
514
  await this.findReferencesAndUpdate(db, tableName, clauseStmt, values);
504
515
  }
505
516
  return sqlStmt;
506
517
  }
507
518
  catch (err) {
508
- return Promise.reject(`DeleteSL: ${err}`);
519
+ return Promise.reject(`DeleteSQL: ${err}`);
509
520
  }
510
521
  }
511
522
  /**
@@ -519,27 +530,70 @@ class UtilsSQLite {
519
530
  async findReferencesAndUpdate(db, tableName, whereStmt, values) {
520
531
  try {
521
532
  const references = await this.getReferences(db, tableName);
533
+ if (references.length <= 0) {
534
+ return;
535
+ }
536
+ const tableNameWithRefs = references.pop();
537
+ console.log(`references: ${references}`);
538
+ console.log(`tableNameWithRefs: ${tableNameWithRefs}`);
522
539
  for (const refe of references) {
523
540
  // get the tableName of the reference
524
- const refTable = await this.getReferenceTableName(refe.sql);
541
+ const refTable = await this.getReferenceTableName(refe);
525
542
  if (refTable.length <= 0) {
526
543
  continue;
527
544
  }
528
- // get the columnName
529
- const colName = await this.getReferenceColumnName(refe.sql);
530
- if (colName.length <= 0) {
545
+ console.log(`refTable: ${refTable}`);
546
+ // get the with references columnName
547
+ const withRefsNames = await this.getWithRefsColumnName(refe);
548
+ console.log(`withRefsNames: ${withRefsNames}`);
549
+ if (withRefsNames.length <= 0) {
550
+ continue;
551
+ }
552
+ // get the referenced columnName
553
+ const colNames = await this.getReferencedColumnName(refe);
554
+ console.log(`colNames: ${colNames}`);
555
+ if (colNames.length <= 0) {
531
556
  continue;
532
557
  }
533
558
  // update the where clause
534
- const uWhereStmt = await this.updateWhere(whereStmt, colName);
559
+ const uWhereStmt = await this.updateWhere(whereStmt, withRefsNames, colNames);
560
+ console.log(`whereStmt: ${whereStmt}`);
561
+ console.log(`uWhereStmt: ${uWhereStmt}`);
535
562
  if (uWhereStmt.length <= 0) {
536
563
  continue;
537
564
  }
565
+ let updTableName = tableNameWithRefs;
566
+ let updColNames = colNames;
567
+ if (tableNameWithRefs === tableName) {
568
+ updTableName = refTable;
569
+ updColNames = withRefsNames;
570
+ }
571
+ console.log(`updTableName: ${updTableName}`);
572
+ console.log(`updColNames: ${updColNames}`);
538
573
  //update sql_deleted for this reference
539
- const stmt = `UPDATE ${refTable} SET sql_deleted = 1 ${uWhereStmt}`;
574
+ const stmt = 'UPDATE ' + updTableName + ' SET sql_deleted = 1 ' + uWhereStmt;
575
+ console.log(`stmt: ${stmt}`);
576
+ console.log(`values: ${values}`);
540
577
  if (values != null && values.length > 0) {
541
578
  const mVal = await this.replaceUndefinedByNull(values);
542
- await db.run(stmt, mVal);
579
+ let arrVal = whereStmt.split('?');
580
+ if (arrVal[arrVal.length - 1] === ';')
581
+ arrVal = arrVal.slice(0, -1);
582
+ console.log(`arrVal: ${arrVal}`);
583
+ const selValues = [];
584
+ for (const [j, val] of arrVal.entries()) {
585
+ console.log(`j: ${j} val: ${val}`);
586
+ for (const updVal of updColNames) {
587
+ const idxVal = val.indexOf(updVal);
588
+ console.log(`updVal: ${updVal} idxVal ${idxVal}`);
589
+ if (idxVal > -1) {
590
+ selValues.push(mVal[j]);
591
+ }
592
+ }
593
+ }
594
+ console.log(`*** stmt: ${selValues}`);
595
+ console.log(`*** selValues: ${selValues}`);
596
+ await db.run(stmt, selValues);
543
597
  }
544
598
  else {
545
599
  await db.exec(stmt);
@@ -558,51 +612,120 @@ class UtilsSQLite {
558
612
  }
559
613
  async getReferenceTableName(refValue) {
560
614
  let tableName = '';
561
- if (refValue.length > 0 &&
562
- refValue.substring(0, 12).toLowerCase() === 'CREATE TABLE'.toLowerCase()) {
563
- const oPar = refValue.indexOf('(');
564
- tableName = refValue.substring(13, oPar).trim();
615
+ if (refValue.length > 0) {
616
+ const arr = refValue.split(new RegExp('REFERENCES', 'i'));
617
+ if (arr.length === 2) {
618
+ const oPar = arr[1].indexOf('(');
619
+ tableName = arr[1].substring(0, oPar).trim();
620
+ }
565
621
  }
566
622
  return tableName;
567
623
  }
568
- async getReferenceColumnName(refValue) {
569
- let colName = '';
624
+ async getReferencedColumnName(refValue) {
625
+ let colNames = [];
626
+ if (refValue.length > 0) {
627
+ const arr = refValue.split(new RegExp('REFERENCES', 'i'));
628
+ if (arr.length === 2) {
629
+ const oPar = arr[1].indexOf('(');
630
+ const cPar = arr[1].indexOf(')');
631
+ const colStr = arr[1].substring(oPar + 1, cPar).trim();
632
+ colNames = colStr.split(',');
633
+ }
634
+ }
635
+ return colNames;
636
+ }
637
+ async getWithRefsColumnName(refValue) {
638
+ let colNames = [];
570
639
  if (refValue.length > 0) {
571
- const index = refValue
572
- .toLowerCase()
573
- .indexOf('FOREIGN KEY'.toLowerCase());
574
- const stmt = refValue.substring(index + 12);
575
- const oPar = stmt.indexOf('(');
576
- const cPar = stmt.indexOf(')');
577
- colName = stmt.substring(oPar + 1, cPar).trim();
640
+ const arr = refValue.split(new RegExp('REFERENCES', 'i'));
641
+ if (arr.length === 2) {
642
+ const oPar = arr[0].indexOf('(');
643
+ const cPar = arr[0].indexOf(')');
644
+ const colStr = arr[0].substring(oPar + 1, cPar).trim();
645
+ colNames = colStr.split(',');
646
+ }
578
647
  }
579
- return colName;
648
+ return colNames;
580
649
  }
581
- async updateWhere(whStmt, colName) {
650
+ async updateWhere(whStmt, withRefsNames, colNames) {
582
651
  let whereStmt = '';
583
652
  if (whStmt.length > 0) {
584
653
  const index = whStmt.toLowerCase().indexOf('WHERE'.toLowerCase());
585
654
  const stmt = whStmt.substring(index + 6);
586
- const fEqual = stmt.indexOf('=');
587
- const whereColName = stmt.substring(0, fEqual).trim();
588
- whereStmt = whStmt.replace(whereColName, colName);
655
+ if (withRefsNames.length === colNames.length) {
656
+ for (let i = 0; i < withRefsNames.length; i++) {
657
+ let colType = 'withRefsNames';
658
+ let idx = stmt.indexOf(withRefsNames[i]);
659
+ if (idx === -1) {
660
+ idx = stmt.indexOf(colNames[i]);
661
+ colType = 'colNames';
662
+ }
663
+ if (idx > -1) {
664
+ let valStr = '';
665
+ const fEqual = stmt.indexOf('=', idx);
666
+ if (fEqual > -1) {
667
+ const iAnd = stmt.indexOf('AND', fEqual);
668
+ const ilAnd = stmt.indexOf('and', fEqual);
669
+ if (iAnd > -1) {
670
+ valStr = stmt.substring(fEqual + 1, iAnd - 1).trim();
671
+ }
672
+ else if (ilAnd > -1) {
673
+ valStr = stmt.substring(fEqual + 1, ilAnd - 1).trim();
674
+ }
675
+ else {
676
+ valStr = stmt.substring(fEqual + 1, stmt.length).trim();
677
+ }
678
+ if (i > 0) {
679
+ whereStmt += ' AND ';
680
+ }
681
+ if (colType === 'withRefsNames') {
682
+ whereStmt += `${colNames[i]} = ${valStr}`;
683
+ }
684
+ else {
685
+ whereStmt += `${withRefsNames[i]} = ${valStr}`;
686
+ }
687
+ }
688
+ }
689
+ }
690
+ whereStmt = 'WHERE ' + whereStmt;
691
+ }
589
692
  }
590
693
  return whereStmt;
591
694
  }
592
695
  async getReferences(db, tableName) {
593
696
  const sqlStmt = 'SELECT sql FROM sqlite_master ' +
594
- "WHERE sql LIKE('%REFERENCES%') AND " +
697
+ "WHERE sql LIKE('%FOREIGN KEY%') AND sql LIKE('%REFERENCES%') AND " +
595
698
  "sql LIKE('%" +
596
699
  tableName +
597
700
  "%') AND sql LIKE('%ON DELETE%');";
598
701
  try {
599
702
  const res = await this.queryAll(db, sqlStmt, []);
600
- return Promise.resolve(res);
703
+ // get the reference's string(s)
704
+ let retRefs = [];
705
+ if (res.length > 0) {
706
+ retRefs = await this.getRefs(res[0].sql);
707
+ }
708
+ return Promise.resolve(retRefs);
601
709
  }
602
710
  catch (err) {
603
711
  return Promise.reject(new Error(`getReferences: ${err.message}`));
604
712
  }
605
713
  }
714
+ async getRefs(str) {
715
+ const retRefs = [];
716
+ const arrFor = str.split(new RegExp('FOREIGN KEY', 'i'));
717
+ // Loop through Foreign Keys
718
+ for (let i = 1; i < arrFor.length; i++) {
719
+ retRefs.push(arrFor[i].split(new RegExp('ON DELETE', 'i'))[0].trim());
720
+ }
721
+ // find table name with references
722
+ if (str.substring(0, 12).toLowerCase() === 'CREATE TABLE'.toLowerCase()) {
723
+ const oPar = str.indexOf('(');
724
+ const tableName = str.substring(13, oPar).trim();
725
+ retRefs.push(tableName);
726
+ }
727
+ return retRefs;
728
+ }
606
729
  /**
607
730
  * QueryAll
608
731
  * @param mDB