Ignore:
Timestamp:
06/13/12 17:38:21 (12 years ago)
Author:
tbretz
Message:
Added a simple database interface.
File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/FACT++/src/InterpreterV8.cc

    r14135 r14177  
    11#include "InterpreterV8.h"
     2
     3#ifdef HAVE_SQL
     4#include "Database.h"
     5#endif
    26
    37#include <boost/tokenizer.hpp>
     
    294298}
    295299
    296 Handle<Value> Convert(char type, const char* &ptr)
     300Handle<Value> InterpreterV8::FuncDbClose(const Arguments &args)
     301{
     302    HandleScope handle_scope;
     303
     304    void *ptr = Local<External>::Cast(args.This()->GetInternalField(0))->Value();
     305    if (!ptr)
     306        return Boolean::New(false);
     307
     308#ifdef HAVE_SQL
     309    Database *db = reinterpret_cast<Database*>(ptr);
     310    auto it = find(fDatabases.begin(), fDatabases.end(), db);
     311    fDatabases.erase(it);
     312    delete db;
     313#endif
     314
     315    args.This()->SetInternalField(0, External::New(0));
     316
     317    return Boolean::New(true);
     318}
     319Handle<Value> InterpreterV8::FuncDbQuery(const Arguments &args)
     320{
     321    if (args.Length()!=1)
     322        return ThrowException(String::New("Number of arguments must be exactly 1."));
     323
     324    if (!args[0]->IsString())
     325        return ThrowException(String::New("Both arguments must be a string."));
     326
     327    HandleScope handle_scope;
     328
     329    void *ptr = Local<External>::Cast(args.This()->GetInternalField(0))->Value();
     330    if (!ptr)
     331        return Undefined();
     332
     333    const String::Utf8Value query(args[0]);
     334
     335#ifdef HAVE_SQL
     336    try
     337    {
     338        Database *db = reinterpret_cast<Database*>(ptr);
     339
     340        const mysqlpp::StoreQueryResult res = db->query(*query).store();
     341
     342        Handle<Array> ret = Array::New();
     343        ret->Set(String::New("table"), String::New(res.table()));
     344
     345        int irow=0;
     346        for (vector<mysqlpp::Row>::const_iterator it=res.begin(); it<res.end(); it++)
     347        {
     348            Handle<Array> row = Array::New();
     349
     350            const mysqlpp::FieldNames *list = it->field_list().list;
     351
     352            for (size_t i=0; i<it->size(); i++)
     353            {
     354                const Handle<Value> name = String::New((*list)[i].c_str());
     355
     356                if ((*it)[i].is_null())
     357                {
     358                    row->Set(name, Undefined());
     359                    continue;
     360                }
     361
     362                const string sql_type = (*it)[i].type().sql_name();
     363
     364                const bool uns = sql_type.find("UNSIGNED")==string::npos;
     365
     366                if (sql_type.find("BIGINT")!=string::npos)
     367                {
     368                    if (uns)
     369                    {
     370                        const uint64_t val = (uint64_t)(*it)[i];
     371                        if (val>UINT32_MAX)
     372                            row->Set(name, Number::New(val));
     373                        else
     374                            row->Set(name, Integer::NewFromUnsigned(val));
     375                    }
     376                    else
     377                    {
     378                        const int64_t val = (int64_t)(*it)[i];
     379                        if (val<INT32_MIN || val>INT32_MAX)
     380                            row->Set(name, Number::New(val));
     381                        else
     382                            row->Set(name, Integer::NewFromUnsigned(val));
     383                    }
     384                    continue;
     385                }
     386
     387                // 32 bit
     388                if (sql_type.find("INT")!=string::npos)
     389                {
     390                    if (uns)
     391                        row->Set(name, Integer::NewFromUnsigned((uint32_t)(*it)[i]));
     392                    else
     393                        row->Set(name, Integer::New((int32_t)(*it)[i]));
     394                }
     395
     396                if (sql_type.find("BOOL")!=string::npos )
     397                {
     398                    row->Set(name, Boolean::New((bool)(*it)[i]));
     399                    continue;
     400                }
     401
     402                if (sql_type.find("FLOAT")!=string::npos)
     403                {
     404                    ostringstream val;
     405                    val << setprecision(7) << (float)(*it)[i];
     406                    row->Set(name, Number::New(stod(val.str())));
     407                    continue;
     408
     409                }
     410                if (sql_type.find("DOUBLE")!=string::npos)
     411                {
     412                    row->Set(name, Number::New((double)(*it)[i]));
     413                    continue;
     414                }
     415
     416                if (sql_type.find("CHAR")!=string::npos ||
     417                    sql_type.find("TEXT")!=string::npos)
     418                {
     419                    row->Set(name, String::New((const char*)(*it)[i]));
     420                    continue;
     421                }
     422
     423                if (sql_type.find("TIMESTAMP")!=string::npos)
     424                {
     425                    row->Set(name, Date::New(time_t(mysqlpp::Time((*it)[i]))*1000));
     426                    continue;
     427                }
     428
     429                if (sql_type.find("DATETIME")!=string::npos)
     430                {
     431                    row->Set(name, Date::New(time_t(mysqlpp::DateTime((*it)[i]))*1000));
     432                    continue;
     433                }
     434
     435                if (sql_type.find(" DATE ")!=string::npos)
     436                {
     437                    row->Set(name, Date::New(time_t((mysqlpp::Date)(*it)[i])*1000));
     438                    continue;
     439                }
     440
     441            }
     442
     443            ret->Set(Integer::New(irow++), row);
     444        }
     445
     446        return handle_scope.Close(ret);
     447    }
     448    catch (const exception &e)
     449    {
     450        return ThrowException(String::New(e.what()));
     451    }
     452#endif
     453}
     454
     455Handle<Value> InterpreterV8::FuncDatabase(const Arguments &args)
     456{
     457    if (args.Length()!=1)
     458        return ThrowException(String::New("Number of arguments must be exactly 1."));
     459
     460    if (!args[0]->IsString())
     461        return ThrowException(String::New("Argument 1 must be a string."));
     462
     463    HandleScope handle_scope;
     464
     465    const String::Utf8Value database(args[0]);
     466    const String::Utf8Value query   (args[1]);
     467
     468#ifdef HAVE_SQL
     469    try
     470    {
     471        Database *db = new Database(*database);
     472        fDatabases.push_back(db);
     473
     474        Handle<ObjectTemplate> tem = ObjectTemplate::New();
     475        tem->Set(String::New("user"),     String::New(db->user.c_str()), ReadOnly);
     476        tem->Set(String::New("server"),   String::New(db->server.c_str()), ReadOnly);
     477        tem->Set(String::New("database"), String::New(db->db.c_str()), ReadOnly);
     478        tem->Set(String::New("port"),     db->port==0?Undefined():Integer::NewFromUnsigned(db->port), ReadOnly);
     479        tem->Set(String::New("query"),    FunctionTemplate::New(WrapDbQuery), ReadOnly);
     480        tem->Set(String::New("close"),    FunctionTemplate::New(WrapDbClose),   ReadOnly);
     481        tem->SetInternalFieldCount(1);
     482
     483        Handle<Object> obj = tem->NewInstance();
     484        obj->SetInternalField(0, External::New(db));
     485
     486        return handle_scope.Close(obj);
     487    }
     488    catch (const exception &e)
     489    {
     490        return ThrowException(String::New(e.what()));
     491    }
     492#endif
     493}
     494
     495Handle<Value> InterpreterV8::Convert(char type, const char* &ptr)
    297496{
    298497    // Dim values are always unsigned per (FACT++) definition
     
    327526}
    328527
    329 
    330528Handle<Value> InterpreterV8::FuncClose(const Arguments &args)
    331529{
     
    477675    // Create a template for the global object.
    478676    Handle<ObjectTemplate> dim = ObjectTemplate::New();
    479     dim->Set(String::New("print"),   FunctionTemplate::New(WrapPrint), ReadOnly);
    480     dim->Set(String::New("out"),     FunctionTemplate::New(WrapOut),   ReadOnly);
    481     dim->Set(String::New("wait"),    FunctionTemplate::New(WrapWait),  ReadOnly);
    482     dim->Set(String::New("send"),    FunctionTemplate::New(WrapSend),  ReadOnly);
    483     dim->Set(String::New("state"),   FunctionTemplate::New(WrapState), ReadOnly);
    484     dim->Set(String::New("sleep"),   FunctionTemplate::New(WrapSleep), ReadOnly);
    485     dim->Set(String::New("open"),    FunctionTemplate::New(WrapOpen),  ReadOnly);
     677    dim->Set(String::New("print"),    FunctionTemplate::New(WrapPrint),    ReadOnly);
     678    dim->Set(String::New("out"),      FunctionTemplate::New(WrapOut),      ReadOnly);
     679    dim->Set(String::New("wait"),     FunctionTemplate::New(WrapWait),     ReadOnly);
     680    dim->Set(String::New("send"),     FunctionTemplate::New(WrapSend),     ReadOnly);
     681    dim->Set(String::New("state"),    FunctionTemplate::New(WrapState),    ReadOnly);
     682    dim->Set(String::New("sleep"),    FunctionTemplate::New(WrapSleep),    ReadOnly);
     683    dim->Set(String::New("open"),     FunctionTemplate::New(WrapOpen),     ReadOnly);
     684    dim->Set(String::New("database"), FunctionTemplate::New(WrapDatabase), ReadOnly);
    486685
    487686    Handle<ObjectTemplate> global = ObjectTemplate::New();
     
    492691
    493692    // Persistent
    494     Handle<Context> context = Context::New(NULL, global);
     693    Persistent<Context> context = Context::New(NULL, global);
    495694    if (context.IsEmpty())
    496695    {
     
    515714    //context->Exit();
    516715
    517     //context.Dispose();
     716    context.Dispose();
     717
     718#ifdef HAVE_SQL
     719    for (auto it=fDatabases.begin(); it!=fDatabases.end(); it++)
     720        delete *it;
     721    fDatabases.clear();
     722#endif
     723
    518724
    519725    JsEnd(filename);
Note: See TracChangeset for help on using the changeset viewer.