2

I'm new to blackberry and I have a problem with a SQL connection: When I'm trying to execute a Query on a db I have and error from c++ but, when I consume the method from QML it works like a charm.

so the thing is here:
/* Copyright (c) 2012 Research In Motion Limited.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "customsqldatasource.h"

int const CustomSqlDataSource::LOAD_EXECUTION = 0;

CustomSqlDataSource::CustomSqlDataSource(QObject *parent) :
        QObject(parent)
{

}

CustomSqlDataSource::~CustomSqlDataSource()
{
    delete mSqlConnector;
}

void CustomSqlDataSource::copyFileToDataFolder(const QString fileName)
{
    // Since we need read and write access to the file, it has
    // to be moved to a folder where we have access to it. First,
    // we check if the file already exists (previously copied).
    QString dataFolder = QDir::homePath();
    QString newFileName = dataFolder + "/" + fileName;
    QFile newFile(newFileName);

    if (!newFile.exists()) {
        // If the file is not already in the data folder, we copy it from the
        // assets folder (read only) to the data folder (read and write).
        QString appFolder(QDir::homePath());
        appFolder.chop(4);
        QString originalFileName = appFolder + "app/native/assets/" + fileName;
        QFile originalFile(originalFileName);

        if (originalFile.exists()) {
            // Create sub folders if any creates the SQL folder for a file path like e.g. sql/quotesdb
            QFileInfo fileInfo(newFileName);
            QDir().mkpath (fileInfo.dir().path());

            if(!originalFile.copy(newFileName)) {
                qDebug() << "Failed to copy file to path: " << newFileName;
            }
        } else {
            qDebug() << "Failed to copy file data base file does not exists.";
        }
    }

    mSourceInDataFolder = newFileName;
}


void CustomSqlDataSource::setSource(const QString source)
{
    if (mSource.compare(source) != 0) {
        // Copy the file to the data folder to get read and write access.
        copyFileToDataFolder(source);
        mSource = source;
        emit sourceChanged(mSource);
    }
}

QString CustomSqlDataSource::source()
{
    return mSource;
}

void CustomSqlDataSource::setQuery(const QString query)
{
    if (mQuery.compare(query) != 0) {
        mQuery = query;
        emit queryChanged(mQuery);
    }
}

QString CustomSqlDataSource::query()
{
    return mQuery;
}

bool CustomSqlDataSource::checkConnection()
{
    if (mSqlConnector) {
        return true;
    } else {
        QFile newFile(mSourceInDataFolder);

        if (newFile.exists()) {

            // Remove the old connection if it exists
            if(mSqlConnector){
                disconnect(mSqlConnector, SIGNAL(reply(const bb::data::DataAccessReply&)), this,
                        SLOT(onLoadAsyncResultData(const bb::data::DataAccessReply&)));
                delete mSqlConnector;
            }

            // Set up a connection to the data base
            mSqlConnector = new SqlConnection(mSourceInDataFolder, "connect");

            // Connect to the reply function
            connect(mSqlConnector, SIGNAL(reply(const bb::data::DataAccessReply&)), this,
                    SLOT(onLoadAsyncResultData(const bb::data::DataAccessReply&)));

            return true;

        } else {
            qDebug() << "CustomSqlDataSource::checkConnection Failed to load data base, file does not exist.";
        }
    }
    return false;
}

void CustomSqlDataSource::execute (const QString& query, const QVariantMap &valuesByName, int id)
{
    if (checkConnection()) {
        mSqlConnector->execute(query, valuesByName, id);
    }
}


void CustomSqlDataSource::load()
{

    if (mQuery.isEmpty() == false) {
        if (checkConnection()) {
            mSqlConnector->execute(mQuery, LOAD_EXECUTION);
        }
    }
}

void CustomSqlDataSource::onLoadAsyncResultData(const bb::data::DataAccessReply& replyData)
{
    if (replyData.hasError()) {
        qWarning() << "onLoadAsyncResultData: " << replyData.id() << ", SQL error: " << replyData;
    } else {

        if(replyData.id() == LOAD_EXECUTION) {
            // The reply belongs to the execution of the query property of the data source
            // Emit the the data loaded signal so that the model can be populated.
            QVariantList resultList = replyData.result().value<QVariantList>();
            emit dataLoaded(resultList);
        } else {
            // Forward the reply signal.
            emit reply(replyData);
        }
    }
}

This is the cpp file that I use as an interface to connect to a sql.

here is where I'm calling the SQL from c++

....
    string sqlVersion = "update version set VERSION = " + ver;
    CustomSqlDataSource dataToLoad;

    dataToLoad.setQuery(sqlVersion.c_str());
        dataToLoad.load();
....

this generates an error

libbbdata.so.1.0.0@_ZN2bb4data15AsyncDataAccess7executeERK8QVarianti+0x5) mapaddr=0001d2ba. ref=00000035

but the strange thing is when I consume it from sql it works perfectly great I'm consuming it on varius qmls for example:

import bb.cascades 1.0
import com.lbc.data 1.0
import "customField"

Page {
    property string dropDownValue: "2"
    property string webViewText
    attachedObjects: [
        GroupDataModel {
            id: dataValueModel
            grouping: ItemGrouping.None
        },

        CustomSqlDataSource {
            id: asynkDataSource
            source: "sql/LBCData.db"
            query: "SELECT * FROM INFORMACION ORDER BY Id"
            property int loadCounter: 0

            onDataLoaded: {
                if (data.length > 0) {
                    dataValueModel.insertList(data);

                    var fetchColumData = dataValueModel.data([ dropDownValue ])
                    webViewText = fetchColumData.contenido
                    console.log(webViewText);
                }
            }
        }
    ]

    onCreationCompleted: {
        asynkDataSource.load();
    }

    Container {
        CustomHeader {
            text: "Tipo de Seguro:"
        }
        DropDown {
            id: dropdownVal
            horizontalAlignment: HorizontalAlignment.Center
            preferredWidth: 550
            Option {
                value: "1"
                text: "SEGUROS GENERALES"
            }
            Option {
                value: "2"
                text: "SEGUROS AUTOMOTORES"
                selected: true
            }
            Option {
                value: "5"
                text: "SEGUROS PERSONALES"
            }
            onSelectedValueChanged: {
                console.log("Value..." + dropdownVal.selectedOption.value);
                dropDownValue = dropdownVal.selectedOption.value;
                asynkDataSource.load();
            }
        }
        ScrollView {
            id: scrollView
            scrollViewProperties {
                scrollMode: ScrollMode.Vertical
            }
            WebView {
                id : webView
                html: webViewText
                settings.defaultFontSize: 42
                settings.minimumFontSize: 16


            }
        }
    }
}

if anyone has an Idea of what it can be, please let me know, is my first time with bb10 and also with momentics.

EDIT 1: I'va added the line to set the query but generates copyfile error, seems that the error is the file

dataToLoad.setSource("lbc/LBCData.db");


Failed to copy file data base file does not exists. 
Process 43913393 (LaBolivianaCiacruz) terminated SIGSEGV code=1 fltno=11 ip=fffffb34

EDIT 2: now I'm using the following code, this code is based on the official documentary, with the difference that I'm not sking for file.open since that is marked as a non valid function of the type file. The console gives back the no Error message on hasError but after that crashes, I review it and the sql sentences are executed and in good condition but anyways the app crashes. it gives back the following error:

Process 115667153 (LaBolivianaCiacruz) terminated SIGSEGV code=1 fltno=11 ip=0805f27a(/accounts/1000/appdata/com.lbc.movilexpres.testDev_movilexpreseb26522c/app/native/LaBolivianaCiacruz@_ZNSs6appendERKSsjj+0x4e5) ref=8b0020a9

QDir home = QDir::home();
    copyfiletoDir("sql/LBCData.db");
    bb::data::SqlDataAccess sda(home.absoluteFilePath("sql/LBCData.db"));
//  QFile file(home.absoluteFilePath("sql/LBCData.db"));
//  if(file.open());
        sda.execute(sqlVersion.c_str());
if(sda.hasError()){
            DataAccessError theError = sda.error();
            if (theError.errorType() == DataAccessErrorType::SourceNotFound)
                qDebug() << "Source not found: " + theError.errorMessage();
            else if (theError.errorType() == DataAccessErrorType::ConnectionFailure)
                qDebug() <<  "Connection failure: " + theError.errorMessage();
            else if (theError.errorType() == DataAccessErrorType::OperationFailure)
                qDebug() <<  "Operation failure: " + theError.errorMessage();
        } else {
            qDebug() << "No error.";
        }
Pedro Teran
  • 1,200
  • 3
  • 17
  • 43
  • I haven't looked at it that long, but isn't your querry when calling from C++ set to: "update version set VERSION = " + ver – Richard Dec 18 '13 at 02:28
  • don't think so, I use the same query on the android and iOS app that now I'm developing for bb10 and works perfectly, also I've commented the query and after that the ones who come from web service and crashes equally, and them are working as they come on android and iOS platafroms – Pedro Teran Dec 18 '13 at 13:36
  • I can't really help you out in depth, but if you know that it works one way `but the strange thing is when I consume it from sql it works perfectly great I'm consuming it on varius qmls for example:` you can study this in greater detail and compare it to the troublesome code. – Andrew Dec 21 '13 at 16:52

2 Answers2

2

In this line:

string sqlVersion = "update version set VERSION = " + ver;

Is your ver an integer? Otherwise (and in integer case also!), you must use a parameterized SQL command:

QVariantList values;
values<<ver;
sda.execute("update version set VERSION = :ver", values);
LS_ᴅᴇᴠ
  • 10,823
  • 1
  • 23
  • 46
1

I could add this on comment but i don't have sufficient rep

i think culprit is

sda.execute(sqlVersion.c_str());

"sqlVersion" is std::string sometime it doesn't work with cascades API. it should be QString

modify it like:

sda.execute(QString(sqlVersion));

or just do

QString sqlVersion = "update version set VERSION = " + ver;
sda.execute(sqlVersion);
Ajeet47
  • 1,849
  • 3
  • 14
  • 18