Skip to content

Commit

Permalink
Fix issue#520 and issue#521
Browse files Browse the repository at this point in the history
  • Loading branch information
jepiqueau committed Mar 7, 2024
1 parent e0466f4 commit 7a80b50
Show file tree
Hide file tree
Showing 11 changed files with 181 additions and 76 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,14 @@
# 5.6.2 (2024-03-07)

### Added Features

- Include examples of SQLite comments in the API.md documentation

### Bug Fixes

- Fix Error in README.md with install instructions issue#520
- Fix Unable to run executeSet on SQL with -- comments issue#521

# 5.6.1 (2024-02-29)

### Bug Fixes
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pnpm install --save sql.js
npx cap sync
```

then add plugin to main `capacitor.config.json` file:
then add plugin to main `capacitor.config.ts` file:

```ts
import { CapacitorConfig } from '@capacitor/cli';
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 @@ -743,24 +743,40 @@ private JSObject getStmtAndRetColNames(String sqlStmt, String retMode) throws JS
if (returningIndex != -1) {
String substring = suffix.substring(returningIndex + "returning".length());
String names = substring.trim();
if (names.endsWith(";")) {
retObj.put("names", names.substring(0, names.length() - 1));
}
}
retObj.put("names", getNames(names));
}
}
return retObj;
}

private String getNames(String input) {
int indexSemicolon = input.indexOf(";");
int indexDoubleDash = input.indexOf("--");
int indexCommentStart = input.indexOf("/*");

// Find the minimum index among them
int minIndex = input.length();
if (indexSemicolon != -1) {
minIndex = Math.min(minIndex, indexSemicolon);
}
if (indexDoubleDash != -1) {
minIndex = Math.min(minIndex, indexDoubleDash);
}
if (indexCommentStart != -1) {
minIndex = Math.min(minIndex, indexCommentStart);
}
return input.substring(0, minIndex).trim();
}
private JSObject isReturning(String sqlStmt) {
JSObject retObj = new JSObject();

String stmt = sqlStmt.replace("\n", "").trim();
String stmt = sqlStmt.trim();
if (stmt.endsWith(";")) {
// Remove the suffix
stmt = stmt.substring(0, stmt.length() - 1).trim();
}
retObj.put("isReturning", false);
retObj.put("stmt", stmt);
retObj.put("stmt", sqlStmt);
retObj.put("names", "");

switch (stmt.substring(0, Math.min(stmt.length(), 6)).toUpperCase()) {
Expand Down
62 changes: 61 additions & 1 deletion docs/API.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ The plugin add a suffix "SQLite" and an extension ".db" to the database name giv

- for sharing databases between users:

```
```ts
plugins: {
CapacitorSQLite: {
electronMacLocation: "/YOUR_DATABASES_PATH",
Expand Down Expand Up @@ -95,6 +95,66 @@ The plugin add a suffix "SQLite" and an extension ".db" to the database name giv

- see [Comments within SQL](https://www.techonthenet.com/sqlite/comments.php)

- Some examples

```ts
const setContacts: Array<capSQLiteSet> = [
{ statement:"INSERT INTO contacts /* Contact Simpson */ (name,FirstName,email,company,age,MobileNumber) VALUES (?,?,?,?,?,?);",
values:["Simpson","Tom","Simpson@example.com",,69,"4405060708"]
},
{ statement:"INSERT INTO contacts /* three more contacts */ (name,FirstName,email,company,age,MobileNumber) VALUES (?,?,?,?,?,?) -- Add Jones, Whiteley and Brown;",
values:[
["Jones","David","Jones@example.com",,42.1,"4404030201"],
["Whiteley","Dave","Whiteley@example.com",,45.3,"4405162732"],
["Brown","John","Brown@example.com",,35,"4405243853"]
]
},
{ statement:"UPDATE contacts SET age = ? , MobileNumber = ? WHERE id = ? -- Update Jones Contact;",
values:[51.4,"4404030202",6]
}
];
const setMessages: Array<capSQLiteSet> = [
{ statement:`
/* Define the messages table */
CREATE TABLE IF NOT EXISTS messages (
id INTEGER PRIMARY KEY NOT NULL,
contactid INTEGER, -- key to contacts(id)
title TEXT NOT NULL,
body TEXT NOT NULL,
last_modified INTEGER DEFAULT (strftime('%s', 'now')),
FOREIGN KEY (contactid) REFERENCES contacts(id) ON DELETE SET DEFAULT
);`,
values:[]
},
];

let insertQuery = 'INSERT INTO contacts (name,FirstName,email,company,age,MobileNumber) VALUES (?, ?, ?, ?, ?, ?) -- Add Sue Hellen;';
let bindValues = ["Hellen","Sue","sue.hellen@example.com",,42,"4406050807"];
let ret = await db.run(insertQuery, bindValues);
console.log(`>>> run ret 1: ${JSON.stringify(ret)}`)
insertQuery = `INSERT INTO contacts /* some contacts */ (name,FirstName,email,company,age,MobileNumber) VALUES
('Doe','John','john.doe@example.com', 'IBM', 30, '4403050926'), -- add Doe
('Watson','Dave','dave.watson@example.com','Apple', 30, '4407050932') /* add Watson */,
('Smith', 'Jane', 'jane.smith@example.com', 'IBM', 27, '33607556142') /* Add Smith */-- End of add contact;`;
bindValues = [];
ret = await db.run(insertQuery, bindValues);
console.log(`>>> run ret 2: ${JSON.stringify(ret)}`)

let selectQuery = "SELECT * /* all columns */ FROM contacts WHERE company = 'IBM' -- for company IBM;";

ret = await db.query(selectQuery);
console.log(`>>> query "IBM" ret: ${JSON.stringify(ret)}`)

ret = await db.executeSet(setContacts);
console.log(`>>> executeSet 1 ret: ${JSON.stringify(ret)}`)

selectQuery = "SELECT email /* only email */ FROM contacts WHERE company ISNULL -- for company not given;";


ret = await db.executeSet(setMessages);
console.log(`>>> executeSet 2 ret: ${JSON.stringify(ret)}`)
```

## Unexpected behaviours

Unexpected or erroneous behaviour users of this library have encountered.
Expand Down
37 changes: 28 additions & 9 deletions electron/src/electron-utils/utilsSQLite.ts
Original file line number Diff line number Diff line change
Expand Up @@ -347,7 +347,7 @@ export class UtilsSQLite {
isSQL92: boolean,
): string {
// split the statements in an array of statement
let sqlStmt = sql.replace(/\n/g, '');
let sqlStmt = sql /*.replace(/\n/g, '')*/;
// deal with trigger
sqlStmt = sqlStmt.replace(/end;/g, 'END;');
sqlStmt = sqlStmt.replace(/;END;/g, '&END;');
Expand Down Expand Up @@ -398,7 +398,7 @@ export class UtilsSQLite {
}
resArr.push(rStmt);
}
sqlStmt = resArr.join(';');
sqlStmt = resArr.join(';\n');
return sqlStmt;
}
/**
Expand Down Expand Up @@ -510,7 +510,7 @@ export class UtilsSQLite {
const msg = 'PrepareRun';

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

if (stmt.endsWith(';')) {
stmt = stmt.slice(0, -1).trim();
Expand Down Expand Up @@ -1323,16 +1323,35 @@ export class UtilsSQLite {
const substring = suffix.slice(returningIndex + 9); // 9 is the length of "returning"

const names = substring.trim();
if (names.endsWith(';')) {
retObj.names = names.slice(0, -1);
} else {
retObj.names = names;
}
retObj.names = this.getNames(names);
}
}

return retObj;
}
private getNames(input: string): string {
// Find the index of the first occurrence of ";", "--", or "/*"
const indexSemicolon = input.indexOf(';');
const indexDoubleDash = input.indexOf('--');
const indexCommentStart = input.indexOf('/*');

// Find the minimum index among them
let minIndex = input.length;
if (indexSemicolon !== -1) {
minIndex = Math.min(minIndex, indexSemicolon);
}
if (indexDoubleDash !== -1) {
minIndex = Math.min(minIndex, indexDoubleDash);
}
if (indexCommentStart !== -1) {
minIndex = Math.min(minIndex, indexCommentStart);
}

// Extract substring up to the minimum index
const colnames = input.substring(0, minIndex).trim();
return colnames;
}

private getTableName(sqlStatement: string): string | null {
const patterns: { [key: string]: RegExp } = {
insert: /INSERT\s+INTO\s+(\w+)/i,
Expand Down
29 changes: 0 additions & 29 deletions electron/src/electron-utils/utilsSqlstatement.ts
Original file line number Diff line number Diff line change
Expand Up @@ -128,35 +128,6 @@ export class UtilsSQLStatement {
return lines.join(' ');
}

public getStmtAndRetColNames(
sqlStmt: string,
retMode: string,
): { stmt: string; names: string } {
const retWord = 'RETURNING';
const retStmtNames: { stmt: string; names: string } = {
stmt: sqlStmt,
names: '',
};

const retWordIndex = sqlStmt.toUpperCase().indexOf(retWord);
if (retWordIndex !== -1) {
const prefix = sqlStmt.substring(0, retWordIndex);
retStmtNames.stmt = `${prefix};`;

if (retMode.substring(0, 2) === 'wA') {
const suffix = sqlStmt.substring(retWordIndex + retWord.length);
const names = suffix.trim();
if (names.endsWith(';')) {
retStmtNames.names = names.substring(0, names.length - 1);
} else {
retStmtNames.names = names;
}
}
}

return retStmtNames;
}

public extractCombinedPrimaryKey(whereClause: string): string[][] | null {
const pattern = /WHERE\s*\((.+?)\)\s*(?:=|IN)\s*\((.+?)\)/g;
const regex = new RegExp(pattern);
Expand Down
30 changes: 18 additions & 12 deletions ios/Plugin/Utils/UtilsSQLCipher.swift
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ class UtilsSQLCipher {
retMode = "wA\(retMode)"
}
}
if (retMode == "no" || retMode.prefix(2) == "wA")/* && isReturning*/ {
if (retMode == "no" || retMode.prefix(2) == "wA") {
let stmtNames = UtilsSQLStatement
.getStmtAndRetColNames(sqlStmt: sqlStmt,
retMode: retMode)
Expand Down Expand Up @@ -834,6 +834,12 @@ class UtilsSQLCipher {
return Int(sqlite3_total_changes(mDB))
}

// MARK: - dbLastId

class func dbLastId(mDB: OpaquePointer?) -> Int64 {
return Int64(sqlite3_last_insert_rowid(mDB))
}

// MARK: - Execute

// swiftlint:disable function_body_length
Expand Down Expand Up @@ -970,17 +976,17 @@ class UtilsSQLCipher {
}
}
} else {
let resp = try UtilsSQLCipher
.prepareSQL(mDB: mDB, sql: sql, values: values,
fromJson: false, returnMode: returnMode)
lastId = resp.0
respSet = resp.1
if lastId == -1 {
let message: String = "lastId < 0"
throw UtilsSQLCipherError.executeSet(
message: message)
}
response = addToResponse(response: response, respSet: respSet)
let resp = try UtilsSQLCipher
.prepareSQL(mDB: mDB, sql: sql, values: values,
fromJson: false, returnMode: returnMode)
lastId = resp.0
respSet = resp.1
if lastId == -1 {
let message: String = "lastId < 0"
throw UtilsSQLCipherError.executeSet(
message: message)
}
response = addToResponse(response: response, respSet: respSet)
}
}

Expand Down
40 changes: 31 additions & 9 deletions ios/Plugin/Utils/UtilsSQLStatement.swift
Original file line number Diff line number Diff line change
Expand Up @@ -326,8 +326,7 @@ class UtilsSQLStatement {
// MARK: - isReturning

class func isReturning(sqlStmt: String) -> (Bool, String, String) {
var stmt = sqlStmt.replacingOccurrences(of: "\n", with: "")
.trimmingCharacters(in: .whitespacesAndNewlines)
var stmt = sqlStmt.trimmingCharacters(in: .whitespacesAndNewlines)
if stmt.hasSuffix(";") {
// Remove the suffix
stmt = String(stmt.dropLast())
Expand Down Expand Up @@ -360,10 +359,10 @@ class UtilsSQLStatement {
if substringAfterValues.lowercased().contains("returning") {
return (true, stmtString, resultString)
} else {
return (false, stmt, "")
return (false, sqlStmt, "")
}
}
return (false, stmt, "")
return (false, sqlStmt, "")

case "DELETE", "UPDATE":
let words = stmt.components(separatedBy: .whitespacesAndNewlines)
Expand Down Expand Up @@ -391,11 +390,11 @@ class UtilsSQLStatement {

return (true, joinedWords, joinedReturningString)
} else {
return (false, stmt, "")
return (false, sqlStmt, "")
}

default:
return (false, stmt, "")
return (false, sqlStmt, "")
}

}
Expand Down Expand Up @@ -425,14 +424,37 @@ class UtilsSQLStatement {

let names =
"\(substring)".trimmingLeadingAndTrailingSpaces()
if names.suffix(1) == ";" {
retStmtNames["names"] = String(names.dropLast())
}
retStmtNames["names"] = getNames(from: names)
}
}
return retStmtNames
}

// MARK: - getNames

class func getNames(from input: String) -> String {
// Find the index of the first occurrence of ";", "--", or "/*"
let indexSemicolon = input.firstIndex(of: ";")
let indexDoubleDash = input.range(of: "--")
let indexCommentStart = input.range(of: "/*")

// Find the minimum index among them
var minIndex = input.endIndex
if let index = indexSemicolon {
minIndex = min(minIndex, index)
}
if let index = indexDoubleDash?.lowerBound {
minIndex = min(minIndex, index)
}
if let index = indexCommentStart?.lowerBound {
minIndex = min(minIndex, index)
}

// Extract substring up to the minimum index
let colnames = String(input[..<minIndex]).trimmingCharacters(in: .whitespacesAndNewlines)
return colnames
}

// MARK: - extractCombinedPrimaryKey

class func extractCombinedPrimaryKey(from whereClause: String)
Expand Down
Loading

0 comments on commit 7a80b50

Please sign in to comment.