Skip to content

Commit

Permalink
Merge branch '8_1_X' into TIMOB-27188-8_1_X
Browse files Browse the repository at this point in the history
  • Loading branch information
keerthi1032 committed Jun 28, 2019
2 parents 87fc6f2 + e2e482d commit 7791357
Show file tree
Hide file tree
Showing 9 changed files with 577 additions and 117 deletions.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -296,4 +296,14 @@ public String getApiName()
{
return "Ti.Database.ResultSet";
}

@Override
public void release()
{

// Close ResultSet on cleanup.
this.close();

super.release();
}
}
50 changes: 48 additions & 2 deletions apidoc/Titanium/Database/DB.yml
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,7 @@ methods:
var rows = db.execute('SELECT rowid,name,phone_number,city FROM people');
db.close();
while (rows.isValidRow())
{
while (rows.isValidRow()) {
Ti.API.info('Person ---> ROWID: ' + rows.fieldByName('rowid') + ', name:' + rows.field(1) + ', phone_number: ' + rows.fieldByName('phone_number') + ', city: ' + rows.field(3));
rows.next();
}
Expand All @@ -61,6 +60,53 @@ methods:
Note that the above `SELECT` query contains the [rowid](http://www.sqlite.org/lang_createtable.html#rowid)
column, which is a SQLite-specific column that stores the unique identifier for each row.
- name: executeAsync
summary: |
Asynchronously executes an SQL statement against the database and fires a callback with a `ResultSet`.
platforms: [android]
parameters:
- name: query
summary: SQL query to execute. May include placeholders for parameter substitution.
type: String

- name: vararg
summary: |
Either a variable ordered list of zero or more values, or an array of values,
to be substituted with the respective `?` placeholder of the query.
type: [String, Array<String>, Object, Array<Object>]
optional: true

- name: callback
summary: Callback when query execution has completed.
type: Callback<Titanium.Database.ResultSet>
since: { android: "8.1.0" }

- name: executeAll
summary: |
Synchronously executes an array of SQL statements against the database and fires a callback with an array of `ResultSet`.
returns:
type: Array<Titanium.Database.ResultSet>
platforms: [android]
parameters:
- name: queries
summary: Array of SQL queries to execute.
type: Array<String>
since: { android: "8.1.0" }

- name: executeAllAsync
summary: |
Asynchronously executes an array of SQL statements against the database and fires a callback with an array of `ResultSet`.
platforms: [android]
parameters:
- name: queries
summary: Array of SQL queries to execute.
type: Array<String>

- name: callback
summary: Callback when query execution has completed.
type: Callback<Array<Titanium.Database.ResultSet>>
since: { android: "8.1.0" }

- name: remove
summary: |
Removes the database files for this instance from disk. WARNING: this is a destructive
Expand Down
25 changes: 25 additions & 0 deletions iphone/Classes/TiUtils+Addons.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2019-present by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/

#import <TitaniumKit/TiUtils.h>

NS_ASSUME_NONNULL_BEGIN

@interface TiUtils (Addons)

/**
Returns a unique identifier for this app.
This will change upon a fresh install.
@return UUID for this app.
*/
+ (NSString *)appIdentifier;

@end

NS_ASSUME_NONNULL_END
27 changes: 27 additions & 0 deletions iphone/Classes/TiUtils+Addons.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/**
* Appcelerator Titanium Mobile
* Copyright (c) 2019-present by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/

#import "TiUtils+Addons.h"

static NSString *kAppUUIDString = @"com.appcelerator.uuid";

@implementation TiUtils (Addons)

+ (NSString *)appIdentifier
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *uid = [defaults stringForKey:kAppUUIDString];
if (uid == nil) {
uid = [TiUtils createUUID];
[defaults setObject:uid forKey:kAppUUIDString];
[defaults synchronize];
}

return uid;
}

@end
2 changes: 0 additions & 2 deletions iphone/TitaniumKit/TitaniumKit/Sources/API/TiUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -793,8 +793,6 @@ typedef enum {
*/
+ (NSString *)convertToHex:(unsigned char *)input length:(size_t)length;

+ (NSString *)appIdentifier;

+ (NSString *)getResponseHeader:(NSString *)header fromHeaders:(NSDictionary *)responseHeaders;

+ (UIImage *)loadBackgroundImage:(id)image forProxy:(TiProxy *)proxy;
Expand Down
14 changes: 0 additions & 14 deletions iphone/TitaniumKit/TitaniumKit/Sources/API/TiUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
static NSDictionary *encodingMap = nil;
static NSDictionary *typeMap = nil;
static NSDictionary *sizeMap = nil;
static NSString *kAppUUIDString = @"com.appcelerator.uuid"; // don't obfuscate

@implementation TiUtils

Expand Down Expand Up @@ -1904,19 +1903,6 @@ + (NSString *)md5:(NSData *)data
return [self convertToHex:(unsigned char *)&result length:CC_MD5_DIGEST_LENGTH];
}

+ (NSString *)appIdentifier
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *uid = [defaults stringForKey:kAppUUIDString];
if (uid == nil) {
uid = [TiUtils createUUID];
[defaults setObject:uid forKey:kAppUUIDString];
[defaults synchronize];
}

return uid;
}

// In pre-iOS 5, it looks like response headers were case-mangled.
// (i.e. WWW-Authenticate became Www-Authenticate). So we have to take this
// mangling into mind; headers such as FooBar-XYZ may also have been mangled
Expand Down
10 changes: 8 additions & 2 deletions iphone/iphone/Titanium.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@
3AB9137C1BB60F070063A4AD /* TiPreviewingDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AB9137B1BB60F070063A4AD /* TiPreviewingDelegate.m */; };
3AB913801BB61FDA0063A4AD /* TiUIiOSPreviewActionProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AB9137F1BB61FDA0063A4AD /* TiUIiOSPreviewActionProxy.m */; };
3ABA85AB1D7204B100BCD3F1 /* TiAppiOSSearchQueryProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 3ABA85AA1D7204B100BCD3F1 /* TiAppiOSSearchQueryProxy.m */; };
4A4D3A9022C0CE6A003D2DB7 /* TiUtils+Addons.m in Sources */ = {isa = PBXBuildFile; fileRef = 4A4D3A8F22C0CE6A003D2DB7 /* TiUtils+Addons.m */; };
502A68DA16EEAA7500661EF6 /* TiUIListItem.m in Sources */ = {isa = PBXBuildFile; fileRef = 502A68D116EEAA7500661EF6 /* TiUIListItem.m */; };
502A68DD16EEAA7500661EF6 /* TiUIListItemProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 502A68D316EEAA7500661EF6 /* TiUIListItemProxy.m */; };
502A68E016EEAA7500661EF6 /* TiUIListSectionProxy.m in Sources */ = {isa = PBXBuildFile; fileRef = 502A68D516EEAA7500661EF6 /* TiUIListSectionProxy.m */; };
Expand Down Expand Up @@ -625,6 +626,8 @@
3AB9137F1BB61FDA0063A4AD /* TiUIiOSPreviewActionProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiUIiOSPreviewActionProxy.m; sourceTree = "<group>"; };
3ABA85A91D7204B100BCD3F1 /* TiAppiOSSearchQueryProxy.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiAppiOSSearchQueryProxy.h; sourceTree = "<group>"; };
3ABA85AA1D7204B100BCD3F1 /* TiAppiOSSearchQueryProxy.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiAppiOSSearchQueryProxy.m; sourceTree = "<group>"; };
4A4D3A8E22C0CE6A003D2DB7 /* TiUtils+Addons.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "TiUtils+Addons.h"; sourceTree = "<group>"; };
4A4D3A8F22C0CE6A003D2DB7 /* TiUtils+Addons.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "TiUtils+Addons.m"; sourceTree = "<group>"; };
50115A9315D5DE0500122055 /* ThirdpartyNS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ThirdpartyNS.h; path = ../Classes/ThirdpartyNS.h; sourceTree = SOURCE_ROOT; };
502A68D016EEAA7500661EF6 /* TiUIListItem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TiUIListItem.h; sourceTree = "<group>"; };
502A68D116EEAA7500661EF6 /* TiUIListItem.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TiUIListItem.m; sourceTree = "<group>"; };
Expand Down Expand Up @@ -1983,10 +1986,12 @@
DBF30940210F36E10001F770 /* TitaniumKit Extensions */ = {
isa = PBXGroup;
children = (
DBF30942210F37080001F770 /* TiWindowProxy+Addons.h */,
DBF30943210F37080001F770 /* TiWindowProxy+Addons.m */,
DBF30945210F3B420001F770 /* TiApp+Addons.h */,
DBF30946210F3B420001F770 /* TiApp+Addons.m */,
4A4D3A8E22C0CE6A003D2DB7 /* TiUtils+Addons.h */,
4A4D3A8F22C0CE6A003D2DB7 /* TiUtils+Addons.m */,
DBF30942210F37080001F770 /* TiWindowProxy+Addons.h */,
DBF30943210F37080001F770 /* TiWindowProxy+Addons.m */,
);
name = "TitaniumKit Extensions";
sourceTree = "<group>";
Expand Down Expand Up @@ -2194,6 +2199,7 @@
1592CC3A1C496EFB00C3DB83 /* TiUIiOSRowAnimationStyleProxy.m in Sources */,
24CA8BAA111161FE0084E2DE /* TiUIButton.m in Sources */,
24CA8BAC111161FE0084E2DE /* TiUIAlertDialogProxy.m in Sources */,
4A4D3A9022C0CE6A003D2DB7 /* TiUtils+Addons.m in Sources */,
24CA8BAE111161FE0084E2DE /* TiUIActivityIndicatorProxy.m in Sources */,
24CA8BAF111161FE0084E2DE /* TiUIActivityIndicator.m in Sources */,
24CA8BBC111161FE0084E2DE /* TiMediaVideoPlayerProxy.m in Sources */,
Expand Down
175 changes: 175 additions & 0 deletions tests/Resources/ti.database.2.addontest.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*
* Appcelerator Titanium Mobile
* Copyright (c) 2011-Present by Appcelerator, Inc. All Rights Reserved.
* Licensed under the terms of the Apache Public License
* Please see the LICENSE included with this distribution for details.
*/
/* eslint-env mocha */
/* global Ti */
/* eslint no-unused-expressions: "off" */
'use strict';
const should = require('./utilities/assertions');

describe('Titanium.Database', function () {
describe('#executeAsync()', () => {
it.android('is a function', () => {
const db = Ti.Database.open('execute_async.db');
try {
should(db.executeAsync).be.a.Function;
} finally {
db.close();
}
});

it.android('executes asynchronously', function (finish) {
this.timeout(5000);
const db = Ti.Database.open('execute_async.db');
// Execute a query to create a test table
db.executeAsync('CREATE TABLE IF NOT EXISTS testTable (text TEXT, number INTEGER)', () => {
// Delete any existing data if the table already existed
db.executeAsync('DELETE FROM testTable', () => {
// Define test data
const testName = 'John Smith';
const testNumber = 123456789;

// Insert test data into the table
db.executeAsync('INSERT INTO testTable (text, number) VALUES (?, ?)', testName, testNumber, () => {
// Validate that only one row has been affected
should(db.rowsAffected).be.eql(1);

// Execute a query to return the rows of the database
db.executeAsync('SELECT rowid, text, number FROM testTable', rows => {
try {
// Validate the returned 'rows' object
should(rows).be.a.Object;
should(rows.rowCount).be.eql(1);
should(rows.fieldCount).be.eql(3);
should(rows.validRow).be.true;

finish();
} catch (e) {
finish(e);
} finally {
// Close the 'rows' object
rows.close();
db.close();
}
});
});
});
});
});
});

describe('#executeAll()', () => {
it.android('is a function', () => {
const db = Ti.Database.open('execute_all.db');
try {
should(db.executeAll).be.a.Function;
} finally {
db.close();
}
});

it.android('executes synchronously', function (finish) {
this.timeout(5000);
const db = Ti.Database.open('execute_all.db');

// FIXME: There's no way to send in binding paramaters, you have to bake them into the query string with this API
const queries = [
// Execute a query to create a test table
'CREATE TABLE IF NOT EXISTS testTable (text TEXT, number INTEGER)',
// Delete any existing data if the table already existed
'DELETE FROM testTable',
// Insert test data into the table
'INSERT INTO testTable (text, number) VALUES (\'John Smith\', 123456789)',
// Execute a query to return the rows of the database
'SELECT rowid, text, number FROM testTable',
];

let rows;
try {
const results = db.executeAll(queries);
// the returned results array should be the same length as the input query array
should(results.length).eql(queries.length);

rows = results[3];
// TODO: If a consumer calls executeAll and some of them return a result set, is the caller expected to explicitly close
// all the non-null result sets returned?!

// Validate the returned 'rows' object
should(rows).be.a.Object;
should(rows.rowCount).be.eql(1);
should(rows.fieldCount).be.eql(3);
should(rows.validRow).be.true;

finish();
} catch (e) {
finish(e);
} finally {
// Close the 'rows' object
if (rows) {
rows.close();
}
db.close();
}
});
});

describe('#executeAllAsync()', () => {
it('is a function', () => {
const db = Ti.Database.open('execute_all_async.db');
try {
should(db.executeAllAsync).be.a.Function;
} finally {
db.close();
}
});

it.android('executes asynchronously', function (finish) {
this.timeout(5000);
const db = Ti.Database.open('execute_all.db');

const queries = [
// Execute a query to create a test table
'CREATE TABLE IF NOT EXISTS testTable (text TEXT, number INTEGER)',
// Delete any existing data if the table already existed
'DELETE FROM testTable',
// Insert test data into the table
'INSERT INTO testTable (text, number) VALUES (\'John Smith\', 123456789)',
// Execute a query to return the rows of the database
'SELECT rowid, text, number FROM testTable',
];

try {
db.executeAllAsync(queries, results => {
let rows;
try {
// the returned results array should be the same length as the input query array
should(results.length).eql(queries.length);

rows = results[3];
// Validate the returned 'rows' object
should(rows).be.a.Object;
should(rows.rowCount).be.eql(1);
should(rows.fieldCount).be.eql(3);
should(rows.validRow).be.true;

finish();
} catch (e) {
finish(e);
} finally {
// Close the 'rows' object
if (rows) {
rows.close();
}
db.close();
}
});
} catch (e) {
db.close();
finish(e);
}
});
});
});

0 comments on commit 7791357

Please sign in to comment.