mirror of
https://github.com/antos-rde/antosdk-apps.git
synced 2024-11-08 06:28:29 +01:00
SQLiteDB: fix database select bug
This commit is contained in:
parent
04050f124f
commit
c8ddd5ec6e
@ -13,18 +13,22 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"coffee": {
|
||||
"ts": {
|
||||
"require": [
|
||||
"coffee"
|
||||
"ts"
|
||||
],
|
||||
"jobs": [
|
||||
{
|
||||
"name": "coffee-compile",
|
||||
"name": "ts-import",
|
||||
"data": ["sdk://core/ts/core.d.ts", "sdk://core/ts/jquery.d.ts","sdk://core/ts/antos.d.ts"]
|
||||
},
|
||||
{
|
||||
"name": "ts-compile",
|
||||
"data": {
|
||||
"src": [
|
||||
"main.coffee",
|
||||
"dialogs.coffee",
|
||||
"tags.coffee"
|
||||
"main.ts",
|
||||
"dialogs.ts",
|
||||
"tags.ts"
|
||||
],
|
||||
"dest": "build/debug/main.js"
|
||||
}
|
||||
@ -51,9 +55,7 @@
|
||||
"data": {
|
||||
"src": [
|
||||
"scheme.html",
|
||||
"cvsection.html",
|
||||
"api/sendmail.lua",
|
||||
"sendmail.html",
|
||||
"package.json",
|
||||
"README.md",
|
||||
"main.css"
|
||||
@ -62,6 +64,27 @@
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"locale": {
|
||||
"require": ["locale"],
|
||||
"jobs": [
|
||||
{
|
||||
"name":"locale-gen",
|
||||
"data": {
|
||||
"src": "",
|
||||
"exclude": ["build/", "api/"],
|
||||
"locale": "en_GB",
|
||||
"dest": "package.json"
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
"debug": {
|
||||
"depend": [
|
||||
"init",
|
||||
"ts",
|
||||
"copy"
|
||||
]
|
||||
},
|
||||
"release": {
|
||||
"require": [
|
||||
@ -69,7 +92,7 @@
|
||||
],
|
||||
"depend": [
|
||||
"init",
|
||||
"coffee",
|
||||
"ts",
|
||||
"uglify",
|
||||
"copy"
|
||||
],
|
||||
|
@ -1,30 +0,0 @@
|
||||
<afx-app-window data-id = "blogger-cv-sec-win" apptitle="Porforlio section" width="450" height="400">
|
||||
<afx-vbox padding="5">
|
||||
<afx-hbox data-height = "30" >
|
||||
<afx-label data-width= "70" text = "__(Title)"></afx-label>
|
||||
<input type = "text" name="title" input-class = "user-input"></input>
|
||||
</afx-hbox>
|
||||
<afx-hbox data-height = "30" >
|
||||
<afx-label text = "__(Subtitle)" data-width= "70"></afx-label>
|
||||
<input type = "text" name="subtitle" input-class = "user-input"></input>
|
||||
</afx-hbox>
|
||||
<afx-hbox data-height = "30" >
|
||||
<afx-label text = "__(Location)" data-width= "70"></afx-label>
|
||||
<input type = "text" name="location" input-class = "user-input"></input>
|
||||
</afx-hbox>
|
||||
<afx-hbox data-height = "30" >
|
||||
<afx-label text = "__(From)" data-width= "70"></afx-label>
|
||||
<input type = "text" name="start" input-class = "user-input"></input>
|
||||
<afx-label text = "To:" style="text-align:center;" data-width= "70"></afx-label>
|
||||
<input type = "text" name="end" input-class = "user-input"></input>
|
||||
</afx-hbox>
|
||||
<afx-label data-height = "30" text = "Content" style = "margin-left:5px;"></afx-label>
|
||||
<div data-id="editor-container">
|
||||
<textarea name="content" data-id = "contentarea" ></textarea>
|
||||
</div>
|
||||
<div data-height = "35" style="text-align: right;">
|
||||
<afx-switch data-id = "section-publish" data-width="30"></afx-switch>
|
||||
<afx-button iconclass = "fa fa-save" data-id = "bt-cv-sec-save" text = "__(Save)"></afx-button>
|
||||
</div>
|
||||
</afx-vbox>
|
||||
</afx-app-window>
|
File diff suppressed because one or more lines are too long
@ -1,14 +1,101 @@
|
||||
{
|
||||
"app":"Blogger",
|
||||
"name":"Blogging application",
|
||||
"description":"Backend manager for blogging",
|
||||
"info":{
|
||||
"app": "Blogger",
|
||||
"name": "Blogging application",
|
||||
"description": "Backend manager for blogging",
|
||||
"info": {
|
||||
"author": "Xuan Sang LE",
|
||||
"email": "xsang.le@gmail.com"
|
||||
},
|
||||
"version":"0.2.9-a",
|
||||
"category":"Internet",
|
||||
"iconclass":"fa fa-book",
|
||||
"dependencies": ["SimpleMDE@2.18.0-r","Katex@0.11.1-r"],
|
||||
"mimes":["none"]
|
||||
"version": "0.2.9-a",
|
||||
"category": "Internet",
|
||||
"iconclass": "fa fa-book",
|
||||
"dependencies": [
|
||||
"SimpleMDE@2.18.0-r",
|
||||
"Katex@0.11.1-r",
|
||||
"SQLiteDB@0.1.0-a"
|
||||
],
|
||||
"mimes": [
|
||||
"none"
|
||||
],
|
||||
"locales": {
|
||||
"en_GB": {
|
||||
"Pick a parent": "Pick a parent",
|
||||
"Category name": "Category name",
|
||||
"Ok": "Ok",
|
||||
"Cancel": "Cancel",
|
||||
"Title": "Title",
|
||||
"Subtitle": "Subtitle",
|
||||
"Location": "Location",
|
||||
"From": "From",
|
||||
"Save": "Save",
|
||||
"Send": "Send",
|
||||
"Please select a parent category": "Please select a parent category",
|
||||
"Please enter category name": "Please enter category name",
|
||||
"Parent can not be the category itself": "Parent can not be the category itself",
|
||||
"Title or content must not be blank": "Title or content must not be blank",
|
||||
"No email selected": "No email selected",
|
||||
"Unable to send mail to: {0}": "Unable to send mail to: {0}",
|
||||
"Error sending mail: {0}": "Error sending mail: {0}",
|
||||
"Cannot fetch subscribers data: {0}": "Cannot fetch subscribers data: {0}",
|
||||
"Open/create new database": "Open/create new database",
|
||||
"Unable to init database file: {0}": "Unable to init database file: {0}",
|
||||
"Select image file": "Select image file",
|
||||
"Unable to get file": "Unable to get file",
|
||||
"Add category": "Add category",
|
||||
"cv-cat-add: {0}": "cv-cat-add: {0}",
|
||||
"Edit category": "Edit category",
|
||||
"cv-cat-edit: {0}": "cv-cat-edit: {0}",
|
||||
"Delete category": "Delete category",
|
||||
"Do you really want to delete: {0}?": "Do you really want to delete: {0}?",
|
||||
"cv-cat-del: {0}": "cv-cat-del: {0}",
|
||||
"Please select a category": "Please select a category",
|
||||
"New section entry for {0}": "New section entry for {0}",
|
||||
"cv-sec-add: {0}": "cv-sec-add: {0}",
|
||||
"Please select a section to move": "Please select a section to move",
|
||||
"Move to": "Move to",
|
||||
"cv-sec-move: {0}": "cv-sec-move: {0}",
|
||||
"Please select a section to edit": "Please select a section to edit",
|
||||
"Modify section entry": "Modify section entry",
|
||||
"cv-sec-edit: {0}": "cv-sec-edit: {0}",
|
||||
"Cannot delete the section: {0}": "Cannot delete the section: {0}",
|
||||
"New": "New",
|
||||
"Cannot export file for embedding to text": "Cannot export file for embedding to text",
|
||||
"Preview": "Preview",
|
||||
"Send mail": "Send mail",
|
||||
"No post selected": "No post selected",
|
||||
"Emails sent": "Emails sent",
|
||||
"Error sending mails: {0}": "Error sending mails: {0}",
|
||||
"Cannot fetch the entry content": "Cannot fetch the entry content",
|
||||
"Delete a post": "Delete a post",
|
||||
"Do you really want to delete this post ?": "Do you really want to delete this post ?",
|
||||
"Cannot fetch user data": "Cannot fetch user data",
|
||||
"Full name must be entered": "Full name must be entered",
|
||||
"User data updated": "User data updated",
|
||||
"Cannot save user data": "Cannot save user data",
|
||||
"Unable to load categories": "Unable to load categories",
|
||||
"Found {0} sections": "Found {0} sections",
|
||||
"Please insert a title in the text: beginning with heading": "Please insert a title in the text: beginning with heading",
|
||||
"Please enter tags": "Please enter tags",
|
||||
"Cannot save blog: {0}": "Cannot save blog: {0}",
|
||||
"Cannot add new category": "Cannot add new category",
|
||||
"Unable to fetch categories": "Unable to fetch categories",
|
||||
"Cannot Edit category": "Cannot Edit category",
|
||||
"Cannot save section: {0}": "Cannot save section: {0}",
|
||||
"Cannot move section": "Cannot move section",
|
||||
"Cannot delete the category: {0} [{1}]": "Cannot delete the category: {0} [{1}]",
|
||||
"Cannot delete all content of: {0} [{1}]": "Cannot delete all content of: {0} [{1}]",
|
||||
"No post found: {0}": "No post found: {0}",
|
||||
"Created: {0}": "Created: {0}",
|
||||
"Updated: {0}": "Updated: {0}",
|
||||
"Full name": "Full name",
|
||||
"Address": "Address",
|
||||
"Phone": "Phone",
|
||||
"Email": "Email",
|
||||
"Url": "Url",
|
||||
"Photo": "Photo",
|
||||
"Short biblio": "Short biblio",
|
||||
"Categories": "Categories",
|
||||
"Tags": "Tags"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
<afx-app-window data-id = "blogger-send-mail-win" apptitle="Send mail" width="500" height="400" resizable = "false">
|
||||
<afx-hbox>
|
||||
<afx-menu data-width="150" data-id="email-list"></afx-menu>
|
||||
<afx-resizer data-width="3"></afx-resizer>
|
||||
<div data-width="5"></div>
|
||||
<afx-vbox >
|
||||
<div data-height="5"></div>
|
||||
<afx-label data-height="20" text = "__(Title)"></afx-label>
|
||||
<input type = "text" data-height="20" name="title" data-id = "mail-title"></input>
|
||||
<afx-label data-height = "20" text = "Content" ></afx-label>
|
||||
<textarea name="content" data-id = "contentarea" ></textarea>
|
||||
<div data-height="5"></div>
|
||||
<afx-hbox data-height = "30">
|
||||
<div></div>
|
||||
<afx-button iconclass = "fa fa-paper-plane" data-id = "bt-sendmail" data-width="60" text = "__(Send)"></afx-button>
|
||||
</afx-hbox>
|
||||
</afx-vbox>
|
||||
<div data-width="5"></div>
|
||||
</afx-hbox>
|
||||
</afx-app-window>
|
Binary file not shown.
@ -160,7 +160,7 @@ class BloggerSendmailDiaglog extends this.OS.GUI.BasicDialog
|
||||
content: (@find "contentarea").value
|
||||
@_api.apigateway data, false
|
||||
.then (d) =>
|
||||
return @notify __("Unable to send mail to: {0}", d.result.join(", ")) if d.error
|
||||
return @notify __("Unable to send mail to: {0}", d.result.join(",")) if d.error
|
||||
@quit()
|
||||
.catch (e) =>
|
||||
console.log e
|
||||
|
@ -1,14 +1,101 @@
|
||||
{
|
||||
"app":"Blogger",
|
||||
"name":"Blogging application",
|
||||
"description":"Backend manager for blogging",
|
||||
"info":{
|
||||
"app": "Blogger",
|
||||
"name": "Blogging application",
|
||||
"description": "Backend manager for blogging",
|
||||
"info": {
|
||||
"author": "Xuan Sang LE",
|
||||
"email": "xsang.le@gmail.com"
|
||||
},
|
||||
"version":"0.2.9-a",
|
||||
"category":"Internet",
|
||||
"iconclass":"fa fa-book",
|
||||
"dependencies": ["SimpleMDE@2.18.0-r","Katex@0.11.1-r"],
|
||||
"mimes":["none"]
|
||||
"version": "0.2.9-a",
|
||||
"category": "Internet",
|
||||
"iconclass": "fa fa-book",
|
||||
"dependencies": [
|
||||
"SimpleMDE@2.18.0-r",
|
||||
"Katex@0.11.1-r",
|
||||
"SQLiteDB@0.1.0-a"
|
||||
],
|
||||
"mimes": [
|
||||
"none"
|
||||
],
|
||||
"locales": {
|
||||
"en_GB": {
|
||||
"Pick a parent": "Pick a parent",
|
||||
"Category name": "Category name",
|
||||
"Ok": "Ok",
|
||||
"Cancel": "Cancel",
|
||||
"Title": "Title",
|
||||
"Subtitle": "Subtitle",
|
||||
"Location": "Location",
|
||||
"From": "From",
|
||||
"Save": "Save",
|
||||
"Send": "Send",
|
||||
"Please select a parent category": "Please select a parent category",
|
||||
"Please enter category name": "Please enter category name",
|
||||
"Parent can not be the category itself": "Parent can not be the category itself",
|
||||
"Title or content must not be blank": "Title or content must not be blank",
|
||||
"No email selected": "No email selected",
|
||||
"Unable to send mail to: {0}": "Unable to send mail to: {0}",
|
||||
"Error sending mail: {0}": "Error sending mail: {0}",
|
||||
"Cannot fetch subscribers data: {0}": "Cannot fetch subscribers data: {0}",
|
||||
"Open/create new database": "Open/create new database",
|
||||
"Unable to init database file: {0}": "Unable to init database file: {0}",
|
||||
"Select image file": "Select image file",
|
||||
"Unable to get file": "Unable to get file",
|
||||
"Add category": "Add category",
|
||||
"cv-cat-add: {0}": "cv-cat-add: {0}",
|
||||
"Edit category": "Edit category",
|
||||
"cv-cat-edit: {0}": "cv-cat-edit: {0}",
|
||||
"Delete category": "Delete category",
|
||||
"Do you really want to delete: {0}?": "Do you really want to delete: {0}?",
|
||||
"cv-cat-del: {0}": "cv-cat-del: {0}",
|
||||
"Please select a category": "Please select a category",
|
||||
"New section entry for {0}": "New section entry for {0}",
|
||||
"cv-sec-add: {0}": "cv-sec-add: {0}",
|
||||
"Please select a section to move": "Please select a section to move",
|
||||
"Move to": "Move to",
|
||||
"cv-sec-move: {0}": "cv-sec-move: {0}",
|
||||
"Please select a section to edit": "Please select a section to edit",
|
||||
"Modify section entry": "Modify section entry",
|
||||
"cv-sec-edit: {0}": "cv-sec-edit: {0}",
|
||||
"Cannot delete the section: {0}": "Cannot delete the section: {0}",
|
||||
"New": "New",
|
||||
"Cannot export file for embedding to text": "Cannot export file for embedding to text",
|
||||
"Preview": "Preview",
|
||||
"Send mail": "Send mail",
|
||||
"No post selected": "No post selected",
|
||||
"Emails sent": "Emails sent",
|
||||
"Error sending mails: {0}": "Error sending mails: {0}",
|
||||
"Cannot fetch the entry content": "Cannot fetch the entry content",
|
||||
"Delete a post": "Delete a post",
|
||||
"Do you really want to delete this post ?": "Do you really want to delete this post ?",
|
||||
"Cannot fetch user data": "Cannot fetch user data",
|
||||
"Full name must be entered": "Full name must be entered",
|
||||
"User data updated": "User data updated",
|
||||
"Cannot save user data": "Cannot save user data",
|
||||
"Unable to load categories": "Unable to load categories",
|
||||
"Found {0} sections": "Found {0} sections",
|
||||
"Please insert a title in the text: beginning with heading": "Please insert a title in the text: beginning with heading",
|
||||
"Please enter tags": "Please enter tags",
|
||||
"Cannot save blog: {0}": "Cannot save blog: {0}",
|
||||
"Cannot add new category": "Cannot add new category",
|
||||
"Unable to fetch categories": "Unable to fetch categories",
|
||||
"Cannot Edit category": "Cannot Edit category",
|
||||
"Cannot save section: {0}": "Cannot save section: {0}",
|
||||
"Cannot move section": "Cannot move section",
|
||||
"Cannot delete the category: {0} [{1}]": "Cannot delete the category: {0} [{1}]",
|
||||
"Cannot delete all content of: {0} [{1}]": "Cannot delete all content of: {0} [{1}]",
|
||||
"No post found: {0}": "No post found: {0}",
|
||||
"Created: {0}": "Created: {0}",
|
||||
"Updated: {0}": "Updated: {0}",
|
||||
"Full name": "Full name",
|
||||
"Address": "Address",
|
||||
"Phone": "Phone",
|
||||
"Email": "Email",
|
||||
"Url": "Url",
|
||||
"Photo": "Photo",
|
||||
"Short biblio": "Short biblio",
|
||||
"Categories": "Categories",
|
||||
"Tags": "Tags"
|
||||
}
|
||||
}
|
||||
}
|
@ -232,6 +232,7 @@ namespace OS {
|
||||
* user: "dany'",
|
||||
* $or: {
|
||||
* 'user.email': "test@mail.com",
|
||||
* age: [15, 20, 25],
|
||||
* age$lte: 30,
|
||||
* $and: {
|
||||
* 'user.birth$ne': 1986,
|
||||
@ -258,6 +259,9 @@ namespace OS {
|
||||
* ( contacts.user = 'dany''' ) AND
|
||||
* (
|
||||
* ( user.email = 'test@mail.com' ) OR
|
||||
* ( contacts.age = 15 ) OR
|
||||
* ( contacts.age = 20 ) OR
|
||||
* ( contacts.age = 25 ) OR
|
||||
* ( contacts.age <= 30 ) OR
|
||||
* (
|
||||
* ( user.birth != 1986 ) AND
|
||||
|
@ -99,12 +99,14 @@ handle.insert = function(data)
|
||||
end
|
||||
local sql = string.format("INSERT INTO %s (%s) VALUES(%s)", data.table_name, table.concat(keys,","), table.concat(vals,","))
|
||||
LOG_DEBUG("Execute query: [%s]", sql)
|
||||
local ret, err = sqlite.exec(db, sql);
|
||||
local ret, err = sqlite.exec(db, sql)
|
||||
local id = sqlite.last_insert_id(db)
|
||||
sqlite.dbclose(db)
|
||||
if not ret then
|
||||
return error("insert: Unable to insert to %s: %s", data.table_name, err)
|
||||
else
|
||||
return result(ret)
|
||||
|
||||
return result(id)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -99,12 +99,14 @@ handle.insert = function(data)
|
||||
end
|
||||
local sql = string.format("INSERT INTO %s (%s) VALUES(%s)", data.table_name, table.concat(keys,","), table.concat(vals,","))
|
||||
LOG_DEBUG("Execute query: [%s]", sql)
|
||||
local ret, err = sqlite.exec(db, sql);
|
||||
local ret, err = sqlite.exec(db, sql)
|
||||
local id = sqlite.last_insert_id(db)
|
||||
sqlite.dbclose(db)
|
||||
if not ret then
|
||||
return error("insert: Unable to insert to %s: %s", data.table_name, err)
|
||||
else
|
||||
return result(ret)
|
||||
|
||||
return result(id)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1,446 +1 @@
|
||||
|
||||
var OS;
|
||||
(function (OS) {
|
||||
let API;
|
||||
(function (API) {
|
||||
class SQLiteDBCore {
|
||||
constructor(path) {
|
||||
if (!SQLiteDBCore.REGISTY) {
|
||||
SQLiteDBCore.REGISTY = {};
|
||||
}
|
||||
this.db_file = path.asFileHandle();
|
||||
if (SQLiteDBCore.REGISTY[this.db_file.path]) {
|
||||
this.db_file = SQLiteDBCore.REGISTY[this.db_file.path];
|
||||
}
|
||||
else {
|
||||
SQLiteDBCore.REGISTY[this.db_file.path] = this.db_file;
|
||||
}
|
||||
}
|
||||
pwd() {
|
||||
return "pkg://SQLiteDB/".asFileHandle();
|
||||
}
|
||||
fileinfo() {
|
||||
return this.db_file.info;
|
||||
}
|
||||
/**
|
||||
* init and create the db file if it does not exist
|
||||
*/
|
||||
init() {
|
||||
return new Promise(async (ok, reject) => {
|
||||
try {
|
||||
if (this.db_file.ready) {
|
||||
return ok(true);
|
||||
}
|
||||
let request = {
|
||||
action: 'init',
|
||||
args: {
|
||||
db_source: this.db_file.path,
|
||||
}
|
||||
};
|
||||
let _result = await this.call(request);
|
||||
_result = await this.db_file.onready();
|
||||
if (!this.db_file || !this.db_file.ready || this.db_file.info.type !== "file") {
|
||||
throw __("DB file meta-data is invalid: {0}", this.db_file.path).__();
|
||||
}
|
||||
ok(true);
|
||||
}
|
||||
catch (e) {
|
||||
reject(__e(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
call(request) {
|
||||
return new Promise(async (ok, reject) => {
|
||||
request.args.db_source = this.db_file.path;
|
||||
let cmd = {
|
||||
path: this.pwd().path + "/api/api.lua",
|
||||
parameters: request
|
||||
};
|
||||
let data = await API.apigateway(cmd, false);
|
||||
if (!data.error) {
|
||||
ok(data.result);
|
||||
}
|
||||
else {
|
||||
reject(API.throwe(__("SQLiteDB server call error: {0}", data.error)));
|
||||
}
|
||||
});
|
||||
}
|
||||
request(rq) {
|
||||
return new Promise(async (ok, reject) => {
|
||||
try {
|
||||
if (!this.db_file.ready) {
|
||||
let _ = await this.init();
|
||||
}
|
||||
let result = await this.call(rq);
|
||||
ok(result);
|
||||
}
|
||||
catch (e) {
|
||||
reject(__e(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
select(filter) {
|
||||
let rq = {
|
||||
action: 'select',
|
||||
args: {
|
||||
filter
|
||||
}
|
||||
};
|
||||
return this.request(rq);
|
||||
}
|
||||
delete_records(filter) {
|
||||
let rq = {
|
||||
action: 'delete_records',
|
||||
args: {
|
||||
filter
|
||||
}
|
||||
};
|
||||
return this.request(rq);
|
||||
}
|
||||
drop_table(table_name) {
|
||||
let rq = {
|
||||
action: 'drop_table',
|
||||
args: { table_name }
|
||||
};
|
||||
return this.request(rq);
|
||||
}
|
||||
list_tables() {
|
||||
let rq = {
|
||||
action: 'list_table',
|
||||
args: {}
|
||||
};
|
||||
return this.request(rq);
|
||||
}
|
||||
create_table(table, scheme) {
|
||||
let rq = {
|
||||
action: 'create_table',
|
||||
args: {
|
||||
table_name: table,
|
||||
scheme
|
||||
}
|
||||
};
|
||||
return this.request(rq);
|
||||
}
|
||||
get_table_scheme(table_name) {
|
||||
let rq = {
|
||||
action: 'table_scheme',
|
||||
args: {
|
||||
table_name
|
||||
}
|
||||
};
|
||||
return this.request(rq);
|
||||
}
|
||||
insert(table_name, record, pk) {
|
||||
let rq = {
|
||||
action: 'insert',
|
||||
args: {
|
||||
table_name,
|
||||
record,
|
||||
pk
|
||||
}
|
||||
};
|
||||
return this.request(rq);
|
||||
}
|
||||
update(table_name, record, pk) {
|
||||
let rq = {
|
||||
action: 'update',
|
||||
args: {
|
||||
table_name,
|
||||
record,
|
||||
pk
|
||||
}
|
||||
};
|
||||
return this.request(rq);
|
||||
}
|
||||
last_insert_id() {
|
||||
let rq = {
|
||||
action: 'last_insert_id',
|
||||
args: {}
|
||||
};
|
||||
return this.request(rq);
|
||||
}
|
||||
}
|
||||
let VFS;
|
||||
(function (VFS) {
|
||||
/**
|
||||
* SQLite VFS handle for database accessing
|
||||
*
|
||||
* A Sqlite file handle shall be in the following formats:
|
||||
* * `sqlite://remote/path/to/file.db` refers to the entire databale (`remote/path/to/file.db` is relative to the home folder)
|
||||
* - read operation, will list all available tables
|
||||
* - write operations will create table
|
||||
* - rm operation will delete table
|
||||
* - meta operation will return file info
|
||||
* - other operations are not supported
|
||||
* * `sqlite://remote/path/to/file.db@table_name` refers to the table `table_name` in the database
|
||||
* - meta operation will return fileinfo with table scheme information
|
||||
* - read operation will read all records by filter defined by the filter as parameters
|
||||
* - write operations will insert a new record
|
||||
* - rm operation will delete records by filter as parameters
|
||||
* - other operations are not supported
|
||||
* - `sqlite://remote/path/to/file.db@table_name@id` refers to a records in `table_name` with ID `id`
|
||||
* - read operation will read the current record
|
||||
* - write operation will update current record
|
||||
* - rm operation will delete current record
|
||||
* - other operations are not supported
|
||||
*
|
||||
* Example of filter:
|
||||
* ```ts
|
||||
* {
|
||||
* table_name:'contacts';
|
||||
* where: {
|
||||
* id$gte: 10,
|
||||
* user: "dany'",
|
||||
* $or: {
|
||||
* 'user.email': "test@mail.com",
|
||||
* age$lte: 30,
|
||||
* $and: {
|
||||
* 'user.birth$ne': 1986,
|
||||
* age$not_between: [20,30],
|
||||
* name$not_like: "%LE"
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* fields: ['name as n', 'id', 'email'],
|
||||
* order: ['user.name$asc', "id$desc"],
|
||||
* joins: {
|
||||
* cid: 'Category.id',
|
||||
* did: 'Country.id',
|
||||
* uid: "User.id"
|
||||
* }
|
||||
*}
|
||||
* ```
|
||||
* This will generate the followings expressions:
|
||||
* - `( self.name as n,self.id,self.email )` for fields
|
||||
* - condition:
|
||||
* ```
|
||||
* (
|
||||
* ( contacts.id >= 10 ) AND
|
||||
* ( contacts.user = 'dany''' ) AND
|
||||
* (
|
||||
* ( user.email = 'test@mail.com' ) OR
|
||||
* ( contacts.age <= 30 ) OR
|
||||
* (
|
||||
* ( user.birth != 1986 ) AND
|
||||
* ( contacts.age NOT BETWEEN 20 AND 30 ) AND
|
||||
* ( contacts.name NOT LIKE '%LE' )
|
||||
* )
|
||||
* )
|
||||
* )
|
||||
* ```
|
||||
* - order: `user.name ASC,contacts.id DESC`
|
||||
* - joining:
|
||||
* ```
|
||||
* INNER JOIN Category ON contacts.cid = Category.id
|
||||
* INNER JOIN Country ON contacts.did = Country.id
|
||||
* INNER JOIN Country ON contacts.did = Country.id
|
||||
* ```
|
||||
*
|
||||
* @class SqliteFileHandle
|
||||
* @extends {BaseFileHandle}
|
||||
*/
|
||||
class SqliteFileHandle extends VFS.BaseFileHandle {
|
||||
/**
|
||||
* Set a file path to the current file handle
|
||||
*
|
||||
*
|
||||
* @param {string} p
|
||||
* @returns {void}
|
||||
* @memberof SqliteFileHandle
|
||||
*/
|
||||
setPath(p) {
|
||||
let arr = p.split("@");
|
||||
super.setPath(arr[0]);
|
||||
if (arr.length > 3) {
|
||||
throw new Error(__("Invalid file path").__());
|
||||
}
|
||||
this.path = p;
|
||||
this._table_name = arr[1];
|
||||
this._id = arr[2] ? parseInt(arr[2]) : undefined;
|
||||
this._handle = new SQLiteDBCore(`home://${this.genealogy.join("/")}`);
|
||||
}
|
||||
/**
|
||||
* Read database file meta-data
|
||||
*
|
||||
* Return file info on the target database file, if the table_name is specified
|
||||
* return also the table scheme
|
||||
*
|
||||
* @returns {Promise<RequestResult>}
|
||||
* @memberof SqliteFileHandle
|
||||
*/
|
||||
meta() {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
await this._handle.init();
|
||||
let d = {
|
||||
result: {
|
||||
file: this._handle.fileinfo(),
|
||||
schema: undefined
|
||||
}, error: false
|
||||
};
|
||||
if (this._table_name) {
|
||||
const data = await this._handle.get_table_scheme(this._table_name);
|
||||
if (data.length == 0) {
|
||||
d.result.schema = undefined;
|
||||
}
|
||||
else {
|
||||
d.result.schema = {
|
||||
fields: [],
|
||||
types: {},
|
||||
pk: undefined
|
||||
};
|
||||
d.result.schema.fields = data.map(e => e.name);
|
||||
for (let v of data) {
|
||||
d.result.schema.types[v.name] = v.type;
|
||||
if (v.pk) {
|
||||
d.result.schema.pk = v.name;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return resolve(d);
|
||||
}
|
||||
catch (e) {
|
||||
return reject(__e(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Query the database based on the provided info
|
||||
*
|
||||
* If no table is provided, return list of tables in the
|
||||
* data base.
|
||||
* If the current table is specified:
|
||||
* - if the record id is specfied return the record
|
||||
* - otherwise, return the records in the table using the specified filter
|
||||
*
|
||||
* @protected
|
||||
* @param {any} t filter type
|
||||
* @returns {Promise<any>}
|
||||
* @memberof SqliteFileHandle
|
||||
*/
|
||||
_rd(user_data) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
if (this._table_name && !this.info.schema) {
|
||||
throw new Error(__("Table `{0}` does not exists in database: {1}", this._table_name, this.path).__());
|
||||
}
|
||||
if (!this._table_name) {
|
||||
// return list of tables in form of data base file handles in ready mode
|
||||
let list = await this._handle.list_tables();
|
||||
const map = {};
|
||||
for (let v of list) {
|
||||
map[v.name] = `${this.path}@${v.name}`.asFileHandle();
|
||||
}
|
||||
this.cache = map;
|
||||
resolve(map);
|
||||
}
|
||||
else {
|
||||
// return all the data in the table set by the filter
|
||||
// if this is a table, return the filtered records
|
||||
// otherwise, it is a record, fetch only that record
|
||||
let filter = user_data;
|
||||
if (!filter || this._id) {
|
||||
filter = {};
|
||||
}
|
||||
filter.table_name = this._table_name;
|
||||
if (this._id) {
|
||||
filter.where = { id: this._id };
|
||||
}
|
||||
let data = await this._handle.select(filter);
|
||||
if (this._id) {
|
||||
this.cache = data[0];
|
||||
}
|
||||
else {
|
||||
this.cache = data;
|
||||
}
|
||||
resolve(this.cache);
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
return reject(__e(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Write commit file cache to the remote database
|
||||
*
|
||||
* @protected
|
||||
* @param {string} t is table name, used only when create table
|
||||
* @returns {Promise<RequestResult>}
|
||||
* @memberof SqliteFileHandle
|
||||
*/
|
||||
_wr(t) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
if (!this.cache) {
|
||||
throw new Error(__("No data to submit to remote database, please check the `cache` field").__());
|
||||
}
|
||||
await this.onready();
|
||||
if (this._id && this._table_name) {
|
||||
this.cache.id = this._id;
|
||||
const ret = await this._handle.update(this._table_name, this.cache, this.info.schema.pk);
|
||||
resolve({ result: ret, error: false });
|
||||
return;
|
||||
}
|
||||
if (this._table_name) {
|
||||
const ret = await this._handle.insert(this._table_name, this.cache, this.info.schema.pk);
|
||||
resolve({ result: ret, error: false });
|
||||
return;
|
||||
}
|
||||
// create a new table with the scheme provided in the cache
|
||||
let r = await this._handle.create_table(t, this.cache);
|
||||
resolve({ result: r, error: false });
|
||||
}
|
||||
catch (e) {
|
||||
return reject(__e(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
/**
|
||||
* Delete data from remote database
|
||||
*
|
||||
* @protected
|
||||
* @param {any} user_data is table name, for delete table, otherwise, filter object for deleting records
|
||||
* @returns {Promise<RequestResult>}
|
||||
* @memberof SqliteFileHandle
|
||||
*/
|
||||
_rm(user_data) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
if (this._table_name && !this.info.schema) {
|
||||
throw new Error(__("Table `{0}` does not exists in database: {1}", this._table_name, this.path).__());
|
||||
}
|
||||
if (!this._table_name) {
|
||||
let table_name = user_data;
|
||||
if (!table_name) {
|
||||
throw new Error(__("No table specified for dropping").__());
|
||||
}
|
||||
let ret = await this._handle.drop_table(table_name);
|
||||
resolve({ result: ret, error: false });
|
||||
// delete the table
|
||||
}
|
||||
else {
|
||||
let filter = user_data;
|
||||
// delete the records in the table using the filter
|
||||
if (!filter || this._id) {
|
||||
filter = {};
|
||||
}
|
||||
filter.table_name = this._table_name;
|
||||
if (this._id) {
|
||||
filter.where = { id: this._id };
|
||||
}
|
||||
let ret = await this._handle.delete_records(filter);
|
||||
resolve({ result: ret, error: false });
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
return reject(__e(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
VFS.register("^sqlite$", SqliteFileHandle);
|
||||
})(VFS = API.VFS || (API.VFS = {}));
|
||||
})(API = OS.API || (OS.API = {}));
|
||||
})(OS || (OS = {}));
|
||||
var OS;!function(e){let t;!function(e){class t{constructor(e){t.REGISTY||(t.REGISTY={}),this.db_file=e.asFileHandle(),t.REGISTY[this.db_file.path]?this.db_file=t.REGISTY[this.db_file.path]:t.REGISTY[this.db_file.path]=this.db_file}pwd(){return"pkg://SQLiteDB/".asFileHandle()}fileinfo(){return this.db_file.info}init(){return new Promise(async(e,t)=>{try{if(this.db_file.ready)return e(!0);let t={action:"init",args:{db_source:this.db_file.path}},a=await this.call(t);if(a=await this.db_file.onready(),!this.db_file||!this.db_file.ready||"file"!==this.db_file.info.type)throw __("DB file meta-data is invalid: {0}",this.db_file.path).__();e(!0)}catch(e){t(__e(e))}})}call(t){return new Promise(async(a,i)=>{t.args.db_source=this.db_file.path;let s={path:this.pwd().path+"/api/api.lua",parameters:t},r=await e.apigateway(s,!1);r.error?i(e.throwe(__("SQLiteDB server call error: {0}",r.error))):a(r.result)})}request(e){return new Promise(async(t,a)=>{try{this.db_file.ready||await this.init(),t(await this.call(e))}catch(e){a(__e(e))}})}select(e){let t={action:"select",args:{filter:e}};return this.request(t)}delete_records(e){let t={action:"delete_records",args:{filter:e}};return this.request(t)}drop_table(e){let t={action:"drop_table",args:{table_name:e}};return this.request(t)}list_tables(){return this.request({action:"list_table",args:{}})}create_table(e,t){let a={action:"create_table",args:{table_name:e,scheme:t}};return this.request(a)}get_table_scheme(e){let t={action:"table_scheme",args:{table_name:e}};return this.request(t)}insert(e,t,a){let i={action:"insert",args:{table_name:e,record:t,pk:a}};return this.request(i)}update(e,t,a){let i={action:"update",args:{table_name:e,record:t,pk:a}};return this.request(i)}last_insert_id(){return this.request({action:"last_insert_id",args:{}})}}let a;!function(e){class a extends e.BaseFileHandle{setPath(e){let a=e.split("@");if(super.setPath(a[0]),a.length>3)throw new Error(__("Invalid file path").__());this.path=e,this._table_name=a[1],this._id=a[2]?parseInt(a[2]):void 0,this._handle=new t("home://"+this.genealogy.join("/"))}meta(){return new Promise(async(e,t)=>{try{await this._handle.init();let t={result:{file:this._handle.fileinfo(),schema:void 0},error:!1};if(this._table_name){const e=await this._handle.get_table_scheme(this._table_name);if(0==e.length)t.result.schema=void 0;else{t.result.schema={fields:[],types:{},pk:void 0},t.result.schema.fields=e.map(e=>e.name);for(let a of e)t.result.schema.types[a.name]=a.type,a.pk&&(t.result.schema.pk=a.name)}}return e(t)}catch(e){return t(__e(e))}})}_rd(e){return new Promise(async(t,a)=>{try{if(this._table_name&&!this.info.schema)throw new Error(__("Table `{0}` does not exists in database: {1}",this._table_name,this.path).__());if(this._table_name){let a=e;a&&!this._id||(a={}),a.table_name=this._table_name,this._id&&(a.where={id:this._id});let i=await this._handle.select(a);this._id?this.cache=i[0]:this.cache=i,t(this.cache)}else{let e=await this._handle.list_tables();const a={};for(let t of e)a[t.name]=`${this.path}@${t.name}`.asFileHandle();this.cache=a,t(a)}}catch(e){return a(__e(e))}})}_wr(e){return new Promise(async(t,a)=>{try{if(!this.cache)throw new Error(__("No data to submit to remote database, please check the `cache` field").__());if(await this.onready(),this._id&&this._table_name)return this.cache.id=this._id,void t({result:await this._handle.update(this._table_name,this.cache,this.info.schema.pk),error:!1});if(this._table_name)return void t({result:await this._handle.insert(this._table_name,this.cache,this.info.schema.pk),error:!1});t({result:await this._handle.create_table(e,this.cache),error:!1})}catch(e){return a(__e(e))}})}_rm(e){return new Promise(async(t,a)=>{try{if(this._table_name&&!this.info.schema)throw new Error(__("Table `{0}` does not exists in database: {1}",this._table_name,this.path).__());if(this._table_name){let a=e;a&&!this._id||(a={}),a.table_name=this._table_name,this._id&&(a.where={id:this._id}),t({result:await this._handle.delete_records(a),error:!1})}else{let a=e;if(!a)throw new Error(__("No table specified for dropping").__());t({result:await this._handle.drop_table(a),error:!1})}}catch(e){return a(__e(e))}})}}e.register("^sqlite$",a)}(a=e.VFS||(e.VFS={}))}(t=e.API||(e.API={}))}(OS||(OS={}));
|
File diff suppressed because one or more lines are too long
BIN
SQLiteDB/build/release/SQLiteDB.zip
Normal file
BIN
SQLiteDB/build/release/SQLiteDB.zip
Normal file
Binary file not shown.
@ -86,11 +86,21 @@ namespace OS {
|
||||
}
|
||||
private async openFile() {
|
||||
try {
|
||||
const d_1 = await this.openDialog("FileDialog",{
|
||||
title: __("Open file"),
|
||||
mimes: this.meta().mimes
|
||||
});
|
||||
this.filehandle=`sqlite://${d_1.file.path.asFileHandle().genealogy.join("/")}`.asFileHandle();
|
||||
let file: API.VFS.BaseFileHandle;
|
||||
if (this.args && this.args.length > 0) {
|
||||
file = this.args[0].path.asFileHandle();
|
||||
}
|
||||
else
|
||||
{
|
||||
const d_1 = await this.openDialog("FileDialog",{
|
||||
title: __("Open file"),
|
||||
mimes: this.meta().mimes
|
||||
});
|
||||
file = d_1.file.path.asFileHandle();
|
||||
}
|
||||
|
||||
|
||||
this.filehandle=`sqlite://${file.genealogy.join("/")}`.asFileHandle();
|
||||
await this.filehandle.onready();
|
||||
this.list_tables();
|
||||
}
|
||||
@ -239,7 +249,7 @@ namespace OS {
|
||||
this.grid_table.header = headers;
|
||||
this.grid_table.rows = [];
|
||||
const records = await handle.read({fields:["COUNT(*)"]});
|
||||
this.n_records = records[0]["(COUNT(*))"];
|
||||
this.n_records = records[0]["COUNT(*)"];
|
||||
this.btn_loadmore.text = `0/${this.n_records}`;
|
||||
await this.load_table();
|
||||
this.container.selectedIndex = 1;
|
||||
@ -252,6 +262,7 @@ namespace OS {
|
||||
this.grid_table.oncelldbclick = async (e) => {
|
||||
this.edit_record();
|
||||
}
|
||||
|
||||
this.openFile();
|
||||
}
|
||||
private async add_record()
|
||||
|
Loading…
Reference in New Issue
Block a user