Skip to content

Commit

Permalink
fix issue #526
Browse files Browse the repository at this point in the history
  • Loading branch information
jepiqueau committed Mar 27, 2024
1 parent 37b07e9 commit 20970e3
Show file tree
Hide file tree
Showing 14 changed files with 204 additions and 156 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
# 5.6.4 (2024-03-27)

### Added Features

- Add SQLite Commands Within the Plugin chapter in API.md doc.
- Modify TypeORM-Usage-From-5.6.0.md
- Modify addUpgradeStatement parameters of the ISQLiteConnection

### Bug Fixes

- Fix Calling run method with BEGIN statement throws StringOutOfBoundIndexException #526 (iOS, Android, Electron)

# 5.6.3 (2024-03-12)

### Added Features
Expand Down
Binary file modified android/.gradle/buildOutputCleanup/buildOutputCleanup.lock
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -636,7 +636,7 @@ public JSObject runSQL(String statement, ArrayList<Object> values, Boolean trans
* @throws Exception message
*/
public JSObject prepareSQL(String statement, ArrayList<Object> values, Boolean fromJson, String returnMode) throws Exception {
String stmtType = statement.replaceAll("\n", "").trim().substring(0, 6).toUpperCase();
String stmtType = statement.trim().split("\\s+")[0].toUpperCase();
SupportSQLiteStatement stmt = null;
String sqlStmt = statement;
String retMode;
Expand Down Expand Up @@ -778,8 +778,9 @@ private JSObject isReturning(String sqlStmt) {
retObj.put("isReturning", false);
retObj.put("stmt", sqlStmt);
retObj.put("names", "");
String stmtType = sqlStmt.trim().split("\\s+")[0].toUpperCase();

switch (stmt.substring(0, Math.min(stmt.length(), 6)).toUpperCase()) {
switch (stmtType) {
case "INSERT":
int valuesIndex = stmt.toUpperCase().indexOf("VALUES");
if (valuesIndex != -1) {
Expand Down
28 changes: 13 additions & 15 deletions docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,18 @@ To easy the way to use the `@capacitor-community/sqlite` plugin and its ability

- [API_DB_Connection_Wrapper_Documentation](https://github.com/capacitor-community/sqlite/blob/master/docs/APIDBConnection.md)

## SQLite Commands Within the Plugin

- SQLite Data Definition Language commands (such as CREATE, ALTER, DROP) should be executed using the `execute` plugin method.

- SQLite Transaction Control commands (including BEGIN TRANSACTION, COMMIT, ROLLBACK) should also be executed using the `execute` plugin method.

- SQLite Data Manipulation Language commands (like INSERT, UPDATE, DELETE, REPLACE) should use the `run` plugin method if they involve bind values. They can utilize either the `execute` or `run` plugin methods if no bind values are involved.

- SQLite Data Query Language commands (SELECT) should be executed using the `query` plugin method.

- SQLite Special commands (PRAGMA) should be executed using the `execute` plugin method.

## Databases Location

The plugin add a suffix "SQLite" and an extension ".db" to the database name given as options in the `capConnectionOptions` or `capSQLiteOptions` ie (fooDB -> fooDBSQLite.db). If the name given contains the extension `.db` it will be removed ie (foo.db) will become internally (fooSQLite.db) after adding the suffix.
Expand Down Expand Up @@ -71,21 +83,7 @@ The plugin add a suffix "SQLite" and an extension ".db" to the database name giv
You can replace "Databases" by your "YOUR_DATABASES_LOCATION", but it MUST not have any "/" or "\\" characters.
For existing databases, YOU MUST COPY old databases to the new location
You MUST remove the Electron folder and add it again with:
```
npx cap add @capacitor-community/electron
npm run build
cd electron
npm i --save sqlite3
npm i --save @types:sqlite3
npm run rebuild
cd ..
npx cap sync @capacitor-community/electron
npm run build
npx cap copy @capacitor-community/electron
npx cap open @capacitor-community/electron
```
You MUST remove the Electron folder and add it again.
### Web
Expand Down
21 changes: 14 additions & 7 deletions docs/APIConnection.md
Original file line number Diff line number Diff line change
Expand Up @@ -224,18 +224,17 @@ Check the passphrase stored in a secure store
### addUpgradeStatement(...)

```typescript
addUpgradeStatement(database: string, toVersion: number, statements: string[]) => Promise<void>
addUpgradeStatement(database: string, upgrade: capSQLiteVersionUpgrade[]) => Promise<void>
```

Add the upgrade Statement for database version upgrading

| Param | Type |
| ---------------- | --------------------- |
| **`database`** | <code>string</code> |
| **`toVersion`** | <code>number</code> |
| **`statements`** | <code>string[]</code> |
| Param | Type |
| -------------- | -------------------------------------- |
| **`database`** | <code>string</code> |
| **`upgrade`** | <code>capSQLiteVersionUpgrade[]</code> |

**Since:** 2.9.0 refactor
**Since:** 5.6.4

--------------------

Expand Down Expand Up @@ -723,6 +722,14 @@ This resembles calling addSQLiteSuffix and deleteOldDatabases, but it is more pe
| **`result`** | <code>boolean</code> | result set to true when successful else false |


#### capSQLiteVersionUpgrade

| Prop | Type |
| ---------------- | --------------------- |
| **`toVersion`** | <code>number</code> |
| **`statements`** | <code>string[]</code> |


#### Map

| Prop | Type |
Expand Down
89 changes: 63 additions & 26 deletions docs/TypeORM-Usage-From-5.6.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,48 +200,85 @@ export const getCountOfElements = (async (connection: DataSource, entity:any):

## Correcting a Bug in the TypeOrm Capacitor Driver

- the bug is referenced "PRAGMA must run under query method in Capacitor sqlite #10687" in the typeorm/issues
- the bug is referenced "PRAGMA must run under query method in Capacitor sqlite #10687" in the typeorm/issues and it is for `typeorm release > 3.0.18`.

- create a `scripts` directory at the root of the App.

- create a `modify-typeorm.cjs` file under this directory with:

```js
const fs = require('fs');
const fs = require('fs');

const filePath = './node_modules/typeorm/driver/capacitor/CapacitorQueryRunner.js';
const lineToModify = 61;
const replacementText = ' else if (["INSERT", "UPDATE", "DELETE"].indexOf(command) !== -1) {';

fs.readFile(filePath, 'utf8', (err, data) => {
/* Moddify CapacitorQueryRunner.js */
const correctBugInCapacitorQueryRunner = (file) => {
if (fs.existsSync(file)) {
fs.readFile(file, 'utf8', function (err, data) {
if (err) {
console.error('Error reading file:', err);
return;
return console.error(err);
}

// Split data by line
const lines = data.split('\n');

// Modify the specific line
if (lines.length >= lineToModify) {
lines[lineToModify - 1] = replacementText; // Line numbers are 1-based
} else {
console.error('Line number to modify is out of range.');
const index = `"DROP",`
if (index === -1) {
console.warn('Line not found. Package probably fixed.');
return;
}

// Join lines back together
const modifiedData = lines.join('\n');
var result = data.replace(
` "DROP",`,
` "DROP",
"PRAGMA"`

// Write the modified data back to the file
fs.writeFile(filePath, modifiedData, 'utf8', (err) => {
if (err) {
console.error('Error writing file:', err);
return;
}
console.log('File modified successfully.');
);
result = result.replace(
'else if (["INSERT", "UPDATE", "DELETE", "PRAGMA"].indexOf(command) !== -1) {',
'else if (["INSERT", "UPDATE", "DELETE"].indexOf(command) !== -1) {'
);

fs.writeFile(file, result, 'utf8', function (err) {
if (err) return console.error(err);
});
});
} else {
utils.warn(`Couldn't find file ${file}`);
}

}
/* Moddify CapacitorDriver.js */
const correctBugInCapacitorDriver = (file) => {
if (fs.existsSync(file)) {
fs.readFile(file, 'utf8', function (err, data) {
if (err) {
return console.error(err);
}

const index = data.indexOf('await connection.run(`PRAGMA foreign_keys = ON`);');
if (index === -1) {
console.warn('Line not found. Package probably fixed.');
return;
}

var result = data.replace(
'await connection.run(`PRAGMA foreign_keys = ON`);',
'await connection.execute(`PRAGMA foreign_keys = ON`, false);'
);
result = result.replace(
'await connection.run(`PRAGMA journal_mode = ${this.options.journalMode}`);',
'await connection.execute(`PRAGMA journal_mode = ${this.options.journalMode}`, false);'
);

fs.writeFile(file, result, 'utf8', function (err) {
if (err) return console.error(err);
});
});
} else {
utils.warn(`Couldn't find file ${file}`);
}
}
correctBugInCapacitorQueryRunner('./node_modules/typeorm/driver/capacitor/CapacitorQueryRunner.js');
correctBugInCapacitorQueryRunner('./node_modules/typeorm/browser/driver/capacitor/CapacitorQueryRunner.js');
correctBugInCapacitorDriver('./node_modules/typeorm/driver/capacitor/CapacitorDriver.js');
correctBugInCapacitorDriver('./node_modules/typeorm/browser/driver/capacitor/CapacitorDriver.js');

```


Expand Down
2 changes: 1 addition & 1 deletion electron/src/electron-utils/UtilsSQL92Compatibility.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
export class UtilsSQL92Compatibility {
public compatibleSQL92(statement: string): string {
let newStatement = '';
const action = statement.trim().substring(0, 6).toUpperCase();
const action = statement.trim().split(' ')[0].toUpperCase();
switch (action) {
case 'INSERT':
newStatement = this.insertSQL92(statement);
Expand Down
18 changes: 9 additions & 9 deletions electron/src/electron-utils/utilsSQLite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -356,10 +356,11 @@ export class UtilsSQLite {
// loop through the statement
for (const stmt of sqlStmts) {
let rStmt = stmt.trim();
const method = rStmt
.substring(0, Math.min(stmt.trim().length, 6))
.toUpperCase();
switch (method) {
const stmtType: string = rStmt
.split(" ")[0]
.toUpperCase();

switch (stmtType) {
case 'CREATE':
if (rStmt.includes('&END')) {
rStmt = rStmt.replace(/&END/g, ';END');
Expand Down Expand Up @@ -510,9 +511,8 @@ export class UtilsSQLite {
const msg = 'PrepareRun';

const stmtType: string = statement
// .replace(/\n/g, '')
.trim()
.substring(0, 6)
.split(" ")[0]
.toUpperCase();
let sqlStmt: string = statement;
try {
Expand Down Expand Up @@ -1228,12 +1228,12 @@ export class UtilsSQLite {
suffix: string;
} {
let stmt = sqlStmt.trim();

const stmtType = stmt.split(' ')[0].toUpperCase();
if (stmt.endsWith(';')) {
stmt = stmt.slice(0, -1).trim();
}

switch (stmt.substring(0, 6).toUpperCase()) {
switch (stmtType) {
case 'INSERT': {
const valuesIndex = stmt.search(/\bVALUES\b/i);
let closingParenthesisIndex = -1;
Expand Down
18 changes: 14 additions & 4 deletions ios/Plugin/Utils/UtilsSQLCipher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -455,6 +455,11 @@ class UtilsSQLCipher {
var names: String = ""
var result: [[String: Any]] = []
var retMode: String
let stmtType = sqlStmt
.trimmingCharacters(in: .whitespacesAndNewlines)
.components(separatedBy: " ")
.first?.capitalized ?? ""

if #available(iOS 15, *) {
retMode = returnMode
} else {
Expand All @@ -471,7 +476,7 @@ class UtilsSQLCipher {
names = stmtNames["names"] ?? ""
}
// Check for DELETE statement
if !fromJson && sqlStmt.prefix(6).uppercased() == "DELETE" {
if !fromJson && stmtType == "DELETE" {
do {
sqlStmt = try deleteSQL(mDB: mDB, sql: sqlStmt,
values: values)
Expand Down Expand Up @@ -564,7 +569,12 @@ class UtilsSQLCipher {
throws -> [[String: Any]] {
var result: [[String: Any]] = []
let initLastId = Int64(sqlite3_last_insert_rowid(mDB.mDb))
if sqlStmt.prefix(6).uppercased() == "DELETE" &&
let stmtType = sqlStmt
.trimmingCharacters(in: .whitespacesAndNewlines)
.components(separatedBy: " ")
.first?.capitalized ?? ""

if stmtType == "DELETE" &&
names.count > 0 {
do {
result = try UtilsDelete
Expand All @@ -587,7 +597,7 @@ class UtilsSQLCipher {
.returningWorkAround(message: message)

}
if sqlStmt.prefix(6).uppercased() == "INSERT" {
if stmtType == "INSERT" {
let lastId = Int64(sqlite3_last_insert_rowid(mDB.mDb))
let tableName = UtilsSQLStatement
.extractTableName(from: sqlStmt)
Expand All @@ -609,7 +619,7 @@ class UtilsSQLCipher {

}

} else if sqlStmt.prefix(6).uppercased() == "UPDATE" {
} else if stmtType == "UPDATE" {
do {
result = try UtilsDelete
.getUpdDelReturnedValues(mDB: mDB,
Expand Down
10 changes: 8 additions & 2 deletions ios/Plugin/Utils/UtilsSQLStatement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -326,18 +326,24 @@ class UtilsSQLStatement {
// MARK: - isReturning

class func isReturning(sqlStmt: String) -> (Bool, String, String) {
let stmtType = sqlStmt
.trimmingCharacters(in: .whitespacesAndNewlines)
.components(separatedBy: " ")
.first?.capitalized ?? ""
var stmt = sqlStmt.trimmingCharacters(in: .whitespacesAndNewlines)
if stmt.hasSuffix(";") {
// Remove the suffix
stmt = String(stmt.dropLast())
.trimmingCharacters(in: .whitespacesAndNewlines)
}

switch stmt.prefix(6).uppercased() {
switch stmtType {

case "INSERT":
if let valuesIndex = stmt.range(of: "VALUES", options: .caseInsensitive)?.lowerBound,
let closingParenthesisIndex = stmt.range(of: ")", options: .backwards, range: valuesIndex..<stmt.endIndex)?.upperBound {
let closingParenthesisIndex = stmt
.range(of: ")", options: .backwards, range: valuesIndex..<stmt.endIndex)?
.upperBound {
guard closingParenthesisIndex < stmt.endIndex else {
stmt += ";"
return (false, stmt, "")
Expand Down
14 changes: 7 additions & 7 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 20970e3

Please sign in to comment.