coresmart / persistencejs

persistence.js is an asynchronous Javascript database mapper library. You can use it in the browser, as well on the server (and you can share data models between them).
http://persistencejs.org
1.73k stars 240 forks source link

Cordova-SQLitePlugin does not work #144

Closed indrajit3010 closed 10 years ago

indrajit3010 commented 10 years ago

Hi, I have used Peristance.js many times in my previous projects and it is doing great. Now, I am working on Phonegap (Cordova) Android app. So wish to take advantage of persistance JS capability, but some how its not working with SQLitePlugin (no errors).

But it never reached to "Database created".

_In the log I see following:_ 04-01 18:03:52.932: I/Web Console(10500): [Tue Apr 01 2014 18:03:52 GMT+0530 (IST)]:[App] - Mobile initialized at file:///android_asset/www/js/Context.js:73 04-01 18:03:52.962: I/Web Console(10500): deviceready has not fired after 5 seconds. at file:///android_asset/www/cordova.js:6958 04-01 18:03:52.962: I/Web Console(10500): Channel not fired: onPluginsReady at file:///android_asset/www/cordova.js:6951 04-01 18:03:52.972: I/Web Console(10500): Channel not fired: onCordovaReady at file:///android_asset/www/cordova.js:6951 04-01 18:03:52.983: I/Web Console(10500): Channel not fired: onCordovaConnectionReady at file:///android_asset/www/cordova.js:6951 04-01 18:03:52.983: I/Web Console(10500): Channel not fired: onDOMContentLoaded at file:///android_asset/www/cordova.js:6951 04-01 18:03:54.432: I/Web Console(10500): [Tue Apr 01 2014 18:03:54 GMT+0530 (IST)]:[App] - Document is ready at file:///android_asset/www/js/Context.js:73 04-01 18:03:54.782: I/Web Console(10500): [Tue Apr 01 2014 18:03:54 GMT+0530 (IST)]:[App] - Device is ready at file:///android_asset/www/js/Context.js:73 04-01 18:03:55.222: I/Web Console(10500): SQLitePlugin openargs: {"name":"corporate","bgType":1} at file:///android_asset/www/js/plugins/SQLitePlugin.js:8 04-01 18:03:55.273: I/Web Console(10500): CREATE TABLE IF NOT EXISTS 'profiles' ('firstName' TEXT, 'lastName' TEXT, 'mobile' TEXT, 'email' TEXT, 'deviceId' TEXT, 'profileCreateDate' INT, 'VAR1' TEXT, 'VAR2' TEXT, 'VAR3' TEXT, 'id' VARCHAR(32) PRIMARY KEY) at file:///android_asset/www/js/libs/persistence.store.cordovasql.js:145

I have included required js for the same (source code as below).

<!-- Cordova JS -->
    <script src="js/libs/cordova.js"></script>
<!-- SQLite Plugin JS -->
    <script src="js/libs/SQLitePlugin.js"></script>
<!-- Persistence JS -->
    <script src="js/libs/persistence.js"></script>
    <script src="js/libs/persistence.store.sql.js"></script>
    <script src="js/libs/persistence.store.websql.js"></script>
    <script src="js/libs/persistence.store.memory.js"></script>
    <script src="js/libs/persistence.store.cordovasql.js"></script>
    <script src="js/libs/persistence.jquery.js"></script>
    <script src="js/libs/persistence.jquery.mobile.js"></script>
<script type="text/javascript">

    var ProfilesDTO = persistence.define('profiles', {
        firstName: "TEXT",
        lastName: "TEXT",
        mobile: "TEXT",
        email: "TEXT",
        deviceId: "TEXT",
        profileCreateDate: "DATE",
        VAR1 : "TEXT",
        VAR2 : "TEXT",
        VAR3 : "TEXT"
    });

    // configure the data store
    persistence.store.cordovasql.config(persistence, 'corporate_network_db', '0.0.1',
            'Corporate Network database', 5 * 1024 * 1024, 0);

    // turn ON/OFF debug mode
    persistence.debug = true;

    // create database
    persistence.schemaSync(function(tx) {
        context.debug('Database created');
    });
</script>

I don't know where my mistake is. Please guide.

Thank You, Indrajit

danielfbm commented 10 years ago

Hi, I just created an app to test this Cordova SQL plugin and the persistence.js "bridge". It works great for me on the mobile. Just a question, did you add plugin using the "cordova plugin add" command? Also, I didn't add this file:

js/libs/SQLitePlugin.js to the index.html file

I am using Cordova 3.4, I just created a basic HelloWorld app using $ cordova create test-app Then I added the plugin with: $ cordova plugin add https://github.com/brodysoft/Cordova-SQLitePlugin Here is my index.html file:

    <div class="app">
        <h1>Apache Cordova</h1>
        <div id="deviceready" class="blink">
            <p class="event listening">Connecting to Device</p>
            <p class="event received">Device is Ready</p>
        </div>
        <div id="console">
        </div>
    </div>
    <script type="text/javascript" src="cordova.js"></script>
    <script type="text/javascript" src="js/index.js"></script>
    <script type="text/javascript" src="js/persistence.js"></script>
    <script type="text/javascript" src="js/persistence.store.sql.js"></script>
    <script type="text/javascript" src="js/persistence.store.websql.js"></script>
    <script type="text/javascript" src="js/persistence.store.cordovasql.js"></script>
    <script type="text/javascript">
        app.initialize();
    </script>

and here is my index.js file: var app = { // Application Constructor initialize: function() { this.bindEvents(); }, // Bind Event Listeners // // Bind any events that are required on startup. Common events are: // 'load', 'deviceready', 'offline', and 'online'. bindEvents: function() { document.addEventListener('deviceready', this.onDeviceReady, false); }, // deviceready Event Handler // // The scope of 'this' is the event. In order to call the 'receivedEvent' // function, we must explicity call 'app.receivedEvent(...);' onDeviceReady: function() { app.receivedEvent('deviceready');

    app.setupDatabase();

    app.log("database fully setup");

    app.insertDummyData();

    app.log("dummy data sucessfully inserted");

    app.selectDummyData();

    app.log("dummy data check complete");        

},

setupDatabase: function(){

    app.Article = persistence.define('Article', {
        article_id: 'INT',
        author: 'TEXT',
        category: 'TEXT',
        total_count: 'INT'
    });

    // Paragraph DB Model
    app.Paragraph = persistence.define('Paragraph', {
        paragraph_id: 'INT',
        article_id: 'INT',
        number: 'INT',
        text: 'TEXT'
    });

    //Defining Database for articles (limit of 50 mb for app, 5 for web app);
    persistence.store.cordovasql.config(persistence, 'testdatabase', '0.0.3', 'Main database to store local information', 50 * 1024 * 1024, 1);

    //Removing verbose operations
    persistence.debug = false;

    //Defining relationships
    app.Article.hasMany('paragraphs', app.Paragraph, 'article');

    //Defining index and constraints
    app.Article.index(['article_id'], {unique: true});
    app.Paragraph.index(['article_id', 'number'], {unique: true});

    //Apply definitions to the DB
    persistence.schemaSync();

},

Article: null,
Paragraph: null,

numberOfArticles: 1000,
numberOfParagraphs: 10,

insertDummyData: function(){
    try{
    persistence.transaction(function (transaction) {
        app.log("insertDummyData: Checking the number of Articles inserted...");
        app.Article.all().list(transaction, function(data){
            app.log("insertDummyData: Total number of Articles: "+data.length);
            if (!data.length){
                app.log("insertDummyData: No Articles in the database. Inserting "+app.numberOfArticles+" records and Paragraphs");
                for (var i = 1, article, p = 1; i <= app.numberOfArticles; i++) {
                    article = new app.Article({article_id: i, author: "Author "+i, category: "category"+i, total_count: i});
                    //app.log("article var: "+article);
                    persistence.add(article);
                    for (var k = 1; k <= app.numberOfParagraphs; k++) {
                        persistence.add(new app.Paragraph({paragraph_id: p, article_id: i, number: k, text: "text "+i+" "+k, article: article}));
                        p++;
                    }
                    persistence.flush(transaction);
                }
            }
        });

    });
    }
    catch (exc) {
        app.log("insertDummyData: Error: "+exc);
    }
},

selectDummyData: function () {
     persistence.transaction(function (transaction) {
        app.log("selectDummyData: Checking the number of Articles inserted...");
        app.Article.all().list(transaction, function(data){
            app.log("selectDummyData: Total number of Articles: "+data.length);
            if (data.length === app.numberOfArticles) {
                app.log("selectDummyData: Total number of Articles is as expected: "+app.numberOfArticles);
            }
        });
        app.log("selectDummyData: Checking the number of Paragraphs inserted...");
        app.Paragraph.all().list(transaction, function(data) {
            app.log("selectDummyData: Total number of Paragraphs: "+data.length);
            if (data.length === app.numberOfArticles * app.numberOfParagraphs ) {
                app.log("selectDummyData: Total number of Paragraphs is as expected: "+app.numberOfArticles * app.numberOfParagraphs);
            }
        });
    });
},

log: function (string) {
    var pElement = document.createElement("p");
    pElement.appendChild(document.createTextNode(string));
    document.getElementById("console").appendChild(pElement);
    console.log(string);
},

// Update DOM on a Received Event
receivedEvent: function(id) {
    var parentElement = document.getElementById(id);
    var listeningElement = parentElement.querySelector('.listening');
    var receivedElement = parentElement.querySelector('.received');

    listeningElement.setAttribute('style', 'display:none;');
    receivedElement.setAttribute('style', 'display:block;');

    console.log('Received Event: ' + id);
}

};

Hope it helps.

indrajit3010 commented 10 years ago

Thanks Daniel,

I followed the steps you mentioned and removed "js/libs/SQLitePlugin.js" entry from index.html. But found that persistencejs creates "corporate_network_db.db" file under "com.demo.app\database" folder. But does not creates table or populates data into "corporate_network_db.db" darabase, instead it creates a new file (db) "file_00000005" under "com.demo.app\app_database\localstorage\file_0" folder and creates tables and populate records into it. And the above mention file db is not accessible from Android.

danielfbm commented 10 years ago

I see... Just one question... are you creating the database and populating data after the ondeviceready event?

The databases issues you have could be a fallback in the persistence.js library (Sorry not really aware of the details on this). for me it was like this: 04-10 18:23:22.360: V/info(19579): Open sqlite db: /data/data/io.cordova.hellocordova/databases/corporate_network_db.db

I just created a new Cordova app using the cordova create command and added your script to the onDeviceReady function... I noticed that you use context.debug(), which doesn't work for me... it could be some library that you are using, so I replaced it with console.log("");

After filtering the output of logcat (tag:Cordova) I got this:

04-10 18:13:01.680: D/CordovaActivity(19019): Resuming the App 04-10 18:13:01.680: D/CordovaActivity(19019): CB-3064: The errorUrl is null 04-10 18:13:01.860: D/CordovaActivity(19019): onMessage(onPageStarted,file:///android_asset/www/index.html) 04-10 18:13:01.935: D/CordovaLog(19019): file:///android_asset/www/index.html: Line 25 : Viewport target-densitydpi is not supported. 04-10 18:13:02.065: D/CordovaWebViewClient(19019): onPageFinished(file:///android_asset/www/index.html) 04-10 18:13:02.065: D/CordovaActivity(19019): onMessage(onPageFinished,file:///android_asset/www/index.html) 04-10 18:13:02.085: D/CordovaActivity(19019): onMessage(spinner,stop) 04-10 18:13:02.165: D/CordovaLog(19019): file:///android_asset/www/js/index.js: Line 72 : Received Event: deviceready 04-10 18:13:02.180: D/CordovaLog(19019): file:///android_asset/www/plugins/com.phonegap.plugins.sqlite/www/SQLitePlugin.js: Line 8 : SQLitePlugin openargs: {"name":"corporate_network_db","bgType":0} 04-10 18:13:02.255: D/CordovaLog(19019): file:///android_asset/www/js/persistence.store.cordovasql.js: Line 145 : CREATE TABLE IF NOT EXISTS profiles (firstName TEXT, lastName TEXT, mobile TEXT, email TEXT, deviceId TEXT, profileCreateDate INT, VAR1 TEXT, VAR2 TEXT, VAR3 TEXT, id VARCHAR(32) PRIMARY KEY) 04-10 18:13:02.265: D/CordovaLog(19019): file:///android_asset/www/js/index.js: Line 60 : DATABASE CREATED 04-10 18:13:04.085: D/CordovaActivity(19019): onMessage(spinner,stop)

After that I tried to add some records and read the added records from the database. After executing the app a few times it is always increasing the number of records... here is the code for the onDeviceReady function:

// deviceready Event Handler // // The scope of 'this' is the event. In order to call the 'receivedEvent' // function, we must explicity call 'app.receivedEvent(...);' onDeviceReady: function() { app.receivedEvent('deviceready');

    var ProfilesDTO = persistence.define('profiles', {
        firstName: "TEXT",
        lastName: "TEXT",
        mobile: "TEXT",
        email: "TEXT",
        deviceId: "TEXT",
        profileCreateDate: "DATE",
        VAR1 : "TEXT",
        VAR2 : "TEXT",
        VAR3 : "TEXT"
    });

    // configure the data store
    persistence.store.cordovasql.config(persistence, 'corporate_network_db', '0.0.1',
            'Corporate Network database', 5 * 1024 * 1024, 0);

    // turn ON/OFF debug mode
    persistence.debug = true;

    // create database
    persistence.schemaSync(function(tx) {
        //context.debug('Database created');
        console.log("DATABASE CREATED");
    });

    persistence.transaction(function (tx){
        console.log("adding 10 records...");
        for (var i = 0; i < 10; i++) {
            persistence.add(new ProfilesDTO({firstName: i, lastName: i, mobile: i, email: i}));
        }
        persistence.flush(tx);

        ProfilesDTO.all().list(function (results){
            console.log("listing all records in the database... total number of records: "+results.length);
            for (var i = 0; i < results.length; i++) {
                console.log(results[i].firstName);
            }
        });
    });
}

BTW: I am using Android 4.4, and Cordova 3.4 Try it out and let me know what you get

indrajit3010 commented 10 years ago

Hi, Yes, I am calling the above code from within "deviceready" handler. Still no DB is created under 'database'. Attached screen shot. device_database

indrajit3010 commented 10 years ago

Hi Daniel, Is it possible for you to share the code? I think there is some missing thing in my project which is causing this issue. And as I am using Windows machine, its very hard to make nodejs work on it. So I have created the project manually.

indrajit3010 commented 10 years ago

Lord Daniel :+1: , Issue is resolved, it was due to old version of cordova jar. I was using 2.9.1 version and for .js 3.4.0. When I added Cordova-SQLite plugin, initially .java file gave me errors about CordovaPlugin class which was not there in the old .jar file. Replaced old jar with new and Bingo!!! everything is working like charm.

Thousand Thanks to you. Indrajit

danielfbm commented 10 years ago

Nice you got it working. If you still need I can share the code with you.

I also had some problems with old versions and upgrades of cordova in my project. At some point I just created the project again and copied the files over. Saved a lot of headache.

Cheers. On Apr 10, 2014 11:05 PM, "indrajit3010" notifications@github.com wrote:

Lord Daniel [image: :+1:] , Issue is resolved, it was due to old version of cordova jar. I was using 2.9.1 version and for .js 3.4.0. When I added Cordova-SQLite plugin, initially .java file gave me errors about CordovaPlugin class which was not there in the old .jar file. Replaced old jar with new and Bingo!!! everything is working like charm.

Thousand Thanks to you. Indrajit

Reply to this email directly or view it on GitHubhttps://github.com/zefhemel/persistencejs/issues/144#issuecomment-40096623 .