Skip to content

Commit

Permalink
test and document usage with numbered parameters
Browse files Browse the repository at this point in the history
resolves #787
  • Loading branch information
Christopher J. Brody committed Jun 29, 2018
1 parent 1c1b822 commit a488c90
Show file tree
Hide file tree
Showing 5 changed files with 258 additions and 2 deletions.
78 changes: 76 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ Native SQLite component with API based on HTML5/[Web SQL (DRAFT) API](http://www
- macOS ("osx" platform)
- Windows 10 (UWP) DESKTOP and MOBILE (see below for major limitations)

Browser platform is supported as described in [Browser platform usage notes](#browser-platform-usage-notes) section below.
Browser platform is supported _with some limitations (no support for numbered parameters)_ as described in [Browser platform usage notes](#browser-platform-usage-notes) section below.

**LICENSE:** MIT, with Apache 2.0 option for Android and Windows platforms (see [LICENSE.md](./LICENSE.md) for details, including third-party components used by this plugin)

Expand All @@ -31,7 +31,7 @@ New release in July 2018 will include the following major enhancements ([litehel

## Browser platform usage notes

As stated above the browser platform will be supported using [kripken / sql.js](https://github.com/kripken/sql.js) (see [litehelpers/Cordova-sqlite-storage#576](https://github.com/litehelpers/Cordova-sqlite-storage/pull/576)) in the near future. Alternative solutions for now:
As stated above the browser platform will be supported _(with numbered parameters working_ using [kripken / sql.js](https://github.com/kripken/sql.js) (see [litehelpers/Cordova-sqlite-storage#576](https://github.com/litehelpers/Cordova-sqlite-storage/pull/576)) in the near future. Alternative solutions for now _(with no support for numbered parameters such as `?1`, `?2`, ...)_:

- Use [brodybits / sql-promise-helper](https://github.com/brodybits/sql-promise-helper) as described in [brodybits/sql-promise-helper#4](https://github.com/brodybits/sql-promise-helper/issues/4)
- Mocking on Ionic Native is possible as described in <https://www.techiediaries.com/mocking-native-sqlite-plugin/> and <https://medium.com/@tintin301/ionic-sqlite-storage-setting-up-for-browser-development-and-testing-67c0f17fc7af>
Expand Down Expand Up @@ -128,6 +128,20 @@ To populate a database using the DRAFT standard transaction API:
});
```

or using numbered parameters as documented in <https://www.sqlite.org/c3ref/bind_blob.html>:

```Javascript
db.transaction(function(tx) {
tx.executeSql('CREATE TABLE IF NOT EXISTS DemoTable (name, score)');
tx.executeSql('INSERT INTO DemoTable VALUES (?1,?2)', ['Alice', 101]);
tx.executeSql('INSERT INTO DemoTable VALUES (?1,?2)', ['Betty', 202]);
}, function(error) {
console.log('Transaction ERROR: ' + error.message);
}, function() {
console.log('Populated database OK');
});
```

To check the data using the "standard" (deprecated) transaction API:

```Javascript
Expand Down Expand Up @@ -156,6 +170,20 @@ To populate a database using the SQL batch API:
});
```

or using numbered parameters as documented in <https://www.sqlite.org/c3ref/bind_blob.html>:

```Javascript
db.sqlBatch([
'CREATE TABLE IF NOT EXISTS DemoTable (name, score)',
[ 'INSERT INTO DemoTable VALUES (?1,?2)', ['Alice', 101] ],
[ 'INSERT INTO DemoTable VALUES (?1,?2)', ['Betty', 202] ],
], function() {
console.log('Populated database OK');
}, function(error) {
console.log('SQL batch ERROR: ' + error.message);
});
```

To check the data using the single SQL statement API:

```Javascript
Expand Down Expand Up @@ -490,6 +518,7 @@ As "strongly recommended" by [Web SQL Database API 8.5 SQL injection](https://ww
- In certain cases such as `transaction.executeSql()` with no arguments (Android/iOS WebKit) Web SQL includes includes a code member with value of 0 (SQLError.UNKNOWN_ERR) in the exception while the plugin includes no such code member.
- If the SQL arguments are passed in an `Array` subclass object where the `constructor` does not point to `Array` then the SQL arguments are ignored by the plugin.
- The results data objects are not immutable as specified/implied by [Web SQL (DRAFT) API section 4.5](https://www.w3.org/TR/webdatabase/#database-query-results).
- This plugin supports use of numbered parameters (`?1`, `?2`, etc.) as documented in <https://www.sqlite.org/c3ref/bind_blob.html>, not supported by HTML5/[Web SQL (DRAFT) API](http://www.w3.org/TR/webdatabase/) ref: [Web SQL (DRAFT) API section 4.2](https://www.w3.org/TR/webdatabase/#parsing-and-processing-sql-statements).

### Security of deleted data

Expand Down Expand Up @@ -577,6 +606,7 @@ Additional limitations are tracked in [marked Cordova-sqlite-storage doc-todo is
- Extremely large and small INTEGER and REAL values ref: [litehelpers/Cordova-sqlite-storage#627](https://github.com/litehelpers/Cordova-sqlite-storage/issues/627)
- More emojis and other 4-octet UTF-8 characters
- More database file names with some more control characters and multi-byte UTF-8 characters (including emojis and other 4-byte UTF-8 characters)
- Use of numbered parameters (`?1`, `?2`, etc.) as documented in <https://www.sqlite.org/c3ref/bind_blob.html>
- Use of `?NNN`/`:AAA`/`@AAAA`/`$AAAA` parameter placeholders as documented in <https://www.sqlite.org/lang_expr.html#varparam> and <https://www.sqlite.org/c3ref/bind_blob.html>) (currently NOT supported by this plugin) ref: [litehelpers/Cordova-sqlite-storage#717](https://github.com/litehelpers/Cordova-sqlite-storage/issues/717)
- Single-statement and SQL batch transaction calls with invalid arguments (TBD behavior subject to change)
- Plugin vs (WebKit) Web SQL transaction behavior in case of an error handler which returns various falsy vs truthy values
Expand Down Expand Up @@ -927,6 +957,17 @@ db.executeSql('INSERT INTO MyTable VALUES (?)', ['test-value'], function (result
});
```

or using numbered parameters as documented in <https://www.sqlite.org/c3ref/bind_blob.html>:

```Javascript
db.executeSql('INSERT INTO MyTable VALUES (?1)', ['test-value'], function (resultSet) {
console.log('resultSet.insertId: ' + resultSet.insertId);
console.log('resultSet.rowsAffected: ' + resultSet.rowsAffected);
}, function(error) {
console.log('SELECT error: ' + error.message);
});
```

Sample with SELECT:

```Javascript
Expand Down Expand Up @@ -968,6 +1009,20 @@ db.sqlBatch([
});
```

or using numbered parameters as documented in <https://www.sqlite.org/c3ref/bind_blob.html>:

```Javascript
db.sqlBatch([
'CREATE TABLE MyTable IF NOT EXISTS (name STRING, balance INTEGER)',
[ 'INSERT INTO MyTable VALUES (?1,?2)', ['Alice', 100] ],
[ 'INSERT INTO MyTable VALUES (?1,?2)', ['Betty', 200] ],
], function() {
console.log('MyTable is now populated.');
}, function(error) {
console.log('Populate table error: ' + error.message);
});
```

In case of an error, all changes in a sql batch are automatically discarded using ROLLBACK.

<!-- END SQL batch transactions -->
Expand All @@ -993,6 +1048,25 @@ db.transaction(function(tx) {
});
```

or using numbered parameters as documented in <https://www.sqlite.org/c3ref/bind_blob.html>:

```Javascript
db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS MyTable');
tx.executeSql('CREATE TABLE MyTable (SampleColumn)');
tx.executeSql('INSERT INTO MyTable VALUES (?1)', ['test-value'], function(tx, resultSet) {
console.log('resultSet.insertId: ' + resultSet.insertId);
console.log('resultSet.rowsAffected: ' + resultSet.rowsAffected);
}, function(tx, error) {
console.log('INSERT error: ' + error.message);
});
}, function(error) {
console.log('transaction error: ' + error.message);
}, function() {
console.log('transaction ok');
});
```

In case of a read-only transaction, it is possible to use `readTransaction` which will not use BEGIN, COMMIT, or ROLLBACK:

```Javascript
Expand Down
25 changes: 25 additions & 0 deletions spec/www/spec/db-sql-operations-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -664,6 +664,31 @@ var mytests = function() {

});

describe(pluginScenarioList[i] + ': db.executeSql numbered parameters storage test(s)', function() {

it(suiteName + 'db.executeSql store numbered parameters (reversed) and check', function(done) {
var db = openDatabase('DB-executeSql-store-numbered-parameters-reversed-and-check.db');

db.executeSql('DROP TABLE IF EXISTS MyTable');
db.executeSql('CREATE TABLE MyTable (x,y)');
db.executeSql('INSERT INTO MyTable VALUES (?2,?1)', ['a',1]);

db.executeSql('SELECT * FROM MyTable', [], function (resultSet) {
// EXPECTED: CORRECT RESULT:
expect(resultSet).toBeDefined();
expect(resultSet.rows).toBeDefined();
expect(resultSet.rows.length).toBe(1);

var resultRow = resultSet.rows.item(0);
expect(resultRow).toBeDefined();
expect(resultRow.x).toBe(1);
expect(resultRow.y).toBe('a');
db.close(done, done);
});
}, MYTIMEOUT);

});

describe(pluginScenarioList[i] + ': more db.executeSql SELECT result test(s)', function() {

it(suiteName + 'db.executeSql string result test with new String for SQL', function(done) {
Expand Down
54 changes: 54 additions & 0 deletions spec/www/spec/db-tx-string-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,60 @@ var mytests = function() {
});
}, MYTIMEOUT);

it(suiteName + 'String concatenation test with numbered parameters', function(done) {
var db = openDatabase('string-concat-with-numbered-parameters-test.db');

db.transaction(function(tx) {

tx.executeSql('SELECT (?1 || ?2) AS myResult', ['First', '-second'], function(ignored, rs) {
expect(rs).toBeDefined();
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBe(1);

var resultRow = rs.rows.item(0);
expect(resultRow).toBeDefined();
expect(resultRow.myResult).toBeDefined();
expect(resultRow.myResult).toBe('First-second');

// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('--');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, MYTIMEOUT);

it(suiteName + 'String concatenation test with reversed numbered parameters', function(done) {
var db = openDatabase('string-concat-with-reversed-numbered-parameters-test.db');

db.transaction(function(tx) {

tx.executeSql('SELECT (?2 || ?1) AS myResult', ['Alice', 'Betty'], function(ignored, rs) {
expect(rs).toBeDefined();
expect(rs.rows).toBeDefined();
expect(rs.rows.length).toBe(1);

var resultRow = rs.rows.item(0);
expect(resultRow).toBeDefined();
expect(resultRow.myResult).toBeDefined();
expect(resultRow.myResult).toBe('BettyAlice');

// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('--');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, MYTIMEOUT);

it(suiteName + 'tx.executeSql(new String(sql))', function(done) {
var db = openDatabase('tx-executeSql-new-String-test.db');

Expand Down
78 changes: 78 additions & 0 deletions spec/www/spec/db-tx-value-bindings-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -954,6 +954,84 @@ var mytests = function() {

});

describe(suiteName + 'numbered argument parameters storage tests', function() {

it(suiteName + 'INSERT with numbered argument parameters', function(done) {
var db = openDatabase('INSERT-with-numbered-argument-parameters-test.db');

db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS MyTable');
// create columns with no type affinity
tx.executeSql('CREATE TABLE IF NOT EXISTS MyTable (id integer primary key, data1, data2)', null, function(ignored1, ignored2) {

tx.executeSql("INSERT INTO MyTable (data1, data2) VALUES (?1,?2)", ['a', 1], function(tx, rs1) {
expect(rs1).toBeDefined();
expect(rs1.rowsAffected).toBe(1);

tx.executeSql("SELECT * FROM MyTable", [], function(tx_ignored, rs2) {
expect(rs2).toBeDefined();
expect(rs2.rows).toBeDefined();
expect(rs2.rows.length).toBe(1);

var resultRow2 = rs2.rows.item(0);
expect(resultRow2).toBeDefined();
expect(resultRow2.id).toBe(1);
expect(resultRow2.data1).toBe('a');
expect(resultRow2.data2).toBe(1);

// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, MYTIMEOUT);

it(suiteName + 'INSERT with numbered argument parameters reversed', function(done) {
var db = openDatabase('INSERT-with-numbered-argument-parameters-reversed-test.db');

db.transaction(function(tx) {
tx.executeSql('DROP TABLE IF EXISTS MyTable');
// create columns with no type affinity
tx.executeSql('CREATE TABLE IF NOT EXISTS MyTable (id integer primary key, data1, data2)', null, function(ignored1, ignored2) {

tx.executeSql("INSERT INTO MyTable (data1, data2) VALUES (?2,?1)", ['a', 1], function(tx, rs1) {
expect(rs1).toBeDefined();
expect(rs1.rowsAffected).toBe(1);

tx.executeSql("SELECT * FROM MyTable", [], function(tx_ignored, rs2) {
expect(rs2).toBeDefined();
expect(rs2.rows).toBeDefined();
expect(rs2.rows.length).toBe(1);

var resultRow2 = rs2.rows.item(0);
expect(resultRow2).toBeDefined();
expect(resultRow2.id).toBe(1);
expect(resultRow2.data1).toBe(1);
expect(resultRow2.data2).toBe('a');

// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
});
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('---');
// Close (plugin only) & finish:
(isWebSql) ? done() : db.close(done, done);
});
}, MYTIMEOUT);

});

describe(suiteName + 'INLINE BLOB value storage tests', function() {

it(suiteName + "INSERT inline BLOB value (X'40414243') and check stored data [TBD SELECT BLOB value ERROR EXPECTED on Windows, WP8, and Android with androidDatabaseImplementation: 2 setting; with default sqlite HEX encoding: UTF-6le on Android 4.1-4.3 (WebKit) Web SQL, UTF-8 otherwise]", function(done) {
Expand Down
25 changes: 25 additions & 0 deletions spec/www/spec/sql-batch-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,31 @@ var mytests = function() {
});
}, MYTIMEOUT);

it(suiteName + 'sqlBatch INSERT with numbered parameters (reversed)', function(done) {
var db = openDatabase('sqlBatch-INSERT-with-numbered-parameters-reversed-test.db');

expect(db).toBeDefined();

db.sqlBatch([
'DROP TABLE IF EXISTS MyTable',
'CREATE TABLE MyTable (x,y)',
[ 'INSERT INTO MyTable VALUES (?2,?1)', ['a',1] ],
], function() {
db.executeSql('SELECT * FROM MyTable', [], function (resultSet) {
// EXPECTED: CORRECT RESULT:
expect(resultSet.rows.length).toBe(1);
expect(resultSet.rows.item(0).x).toBe(1);
expect(resultSet.rows.item(0).y).toBe('a');
db.close(done, done);
});
}, function(error) {
// NOT EXPECTED:
expect(false).toBe(true);
expect(error.message).toBe('--');
db.close(done, done);
});
}, MYTIMEOUT);

it(suiteName + 'batch sql with syntax error', function(done) {
var db = openDatabase('batch-sql-syntax-error-test.db');

Expand Down

0 comments on commit a488c90

Please sign in to comment.