Logo Search packages:      
Sourcecode: gambas version File versions  Download package

CConnection.c

/***************************************************************************

  CConnection.c

  (c) 2000-2004 Benoît Minisini <gambas@users.sourceforge.net>

  This program is free software; you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation; either version 1, or (at your option)
  any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program; if not, write to the Free Software
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

***************************************************************************/

#define __CCONNECTION_C

#include "main.h"

#include "CTable.h"
#include "CDatabase.h"
#include "CUser.h"
#include "CConnection.h"


/***************************************************************************

  Connection

***************************************************************************/

static CCONNECTION *_current = NULL;

static GB_SUBCOLLECTION_DESC _databases_desc = 
{
  ".ConnectionDatabases",
  (void *)CDATABASE_get,
  (void *)CDATABASE_exist,
  (void *)CDATABASE_list
};

static GB_SUBCOLLECTION_DESC _users_desc = 
{
  ".ConnectionUsers",
  (void *)CUSER_get,
  (void *)CUSER_exist,
  (void *)CUSER_list
};

static GB_SUBCOLLECTION_DESC _tables_desc = 
{
  ".ConnectionTables",
  (void *)CTABLE_get,
  (void *)CTABLE_exist,
  (void *)CTABLE_list
};



static bool check_opened(CCONNECTION *_object)
{
  if (!THIS->handle)
  {
    GB.Error("Connection is not opened");
    return TRUE;
  }
  else
    return FALSE;
}

#define CHECK_OPEN() \
  if (check_opened(THIS)) \
    return;

static int get_current(CCONNECTION **current)
{
  if (*current == NULL)
  {
    if (_current == NULL)
    {
      GB.Error("No current connection");
      return TRUE;
    }
    *current = _current;
  }

  return FALSE;
}

#define CHECK_DB() \
  if (get_current((CCONNECTION **)&_object)) \
    return;

static void close_connection(CCONNECTION *_object)
{
  if (!THIS->handle)
    return;

  /*GB.Unref((void **)&THIS->databases);
  GB.Unref((void **)&THIS->users);
  GB.Unref((void **)&THIS->tables);*/
        
  THIS->driver->Close(THIS->handle);
  THIS->handle = NULL;
  GB.FreeString(&THIS->charset);

  if (_current == THIS)
    _current = NULL;
}


// BEGIN_METHOD(CCONNECTION_new, GB_STRING url)
BEGIN_METHOD_VOID(CCONNECTION_new)

  /*int i, state, p;
  char c;*/

  THIS->handle = NULL;

  if (_current == NULL)
    _current = THIS;

#if 0
  if (!MISSING(url))
  {
    char *url = GB.ToZeroString(ARG(url));

    state = 0;
    p = 0;
    for (i = 0; i <= LENGTH(url); i++)
    {
      c = url[i];

      switch (state)
      {
        case 0: /* type */
          if (c == ':' || c == 0)
          {
            GB.NewString(&THIS->desc.type, &url[p], i - p);
            state++;
            p = i + 3; /* On saute '://' */
          }
          break;

        case 1: /* // */
        case 2:
          if (c && c != '/')
            goto BAD_URL;

          state++;
          break;

        case 3: /* host */
          if (c == ':' || c == '/' || c == 0)
          {
            if (i > p)
              GB.NewString(&THIS->desc.host, &url[p], i - p);
            p = i + 1;
            state++;
            if (c != ':')
              state++;
          }
          break;

        case 4: /* port */
          if (c == '/' || c == 0)
          {
            if (i == p)
              goto BAD_URL;

            GB.NewString(&THIS->desc.port, &url[p], i - p);
            p = i + 1;
            state++;
          }
          break;

        case 5: /* name */
          if (c == 0 && i > p)
            GB.NewString(&THIS->desc.name, &url[p], i - p);
          break;
      }
    }
  }

  return;

BAD_URL:

  GB.Error("Malformed URL");
  return;
#endif

END_METHOD


BEGIN_METHOD_VOID(CCONNECTION_free)

  close_connection(THIS);

  GB.StoreString(NULL, &THIS->desc.type);
  GB.StoreString(NULL, &THIS->desc.host);
  GB.StoreString(NULL, &THIS->desc.user);
  GB.StoreString(NULL, &THIS->desc.password);
  GB.StoreString(NULL, &THIS->desc.name);
  GB.StoreString(NULL, &THIS->desc.port);
  GB.StoreString(NULL, &THIS->charset);

END_METHOD


#define IMPLEMENT(_prop) \
BEGIN_PROPERTY(CCONNECTION_##_prop) \
\
  if (READ_PROPERTY) \
    GB.ReturnString(THIS->desc._prop); \
  else \
    GB.StoreString(PROP(GB_STRING), &THIS->desc._prop); \
\
END_PROPERTY

IMPLEMENT(type)
IMPLEMENT(host)
IMPLEMENT(user)
IMPLEMENT(password)
IMPLEMENT(name)
IMPLEMENT(port)


BEGIN_PROPERTY(CCONNECTION_version)

  GB.ReturnInteger(THIS->desc.version);
      
END_PROPERTY


BEGIN_METHOD_VOID(CCONNECTION_open)

  CHECK_DB();

  if (THIS->handle)
  {
    GB.Error("Connection already opened.");
    return;
  }

  DB_Open(&THIS->desc, &THIS->driver, &THIS->handle, &THIS->charset);
  
END_METHOD


BEGIN_METHOD_VOID(CCONNECTION_close)

  CHECK_DB();

  close_connection(THIS);

END_METHOD


BEGIN_METHOD_VOID(CCONNECTION_begin)

  CHECK_DB();

  CHECK_OPEN();

  THIS->driver->Begin(THIS->handle);

END_METHOD


BEGIN_METHOD_VOID(CCONNECTION_commit)

  CHECK_DB();

  CHECK_OPEN();

  THIS->driver->Commit(THIS->handle);

END_METHOD


BEGIN_METHOD_VOID(CCONNECTION_rollback)

  CHECK_DB();

  CHECK_OPEN();

  THIS->driver->Rollback(THIS->handle);

END_METHOD


BEGIN_METHOD(CCONNECTION_exec, GB_STRING query; GB_VALUE param[0])

  char *query;
  CRESULT *result;

  CHECK_DB();

  CHECK_OPEN();

  query = DB_MakeQuery(THIS->driver, STRING(query), LENGTH(query), GB.NParam(), ARG(param[0]));
  if (!query)
    return;

  result = DB_MakeResult(THIS, RESULT_FIND, NULL, query);

  if (result)
    GB.ReturnObject(result);

END_METHOD


BEGIN_METHOD(CCONNECTION_create, GB_STRING table)

  CRESULT *result;
  char *table = GB.ToZeroString(ARG(table));

  CHECK_DB();

  CHECK_OPEN();

  /*if (check_table(THIS, table, TRUE))
    return;*/

  result = DB_MakeResult(THIS, RESULT_CREATE, table, NULL);

  if (result)
    GB.ReturnObject(result);

END_METHOD


static char *get_query(CCONNECTION *_object, char *table, long len_table, char *query, long len_query, GB_VALUE *arg)
{
  q_init();

  q_add("SELECT * FROM ");
  q_add(THIS->driver->GetQuote());
  q_add_length(table, len_table);
  q_add(THIS->driver->GetQuote());

  if (query)
  {
    q_add(" WHERE ");
    q_add_length(query, len_query);

    query = DB_MakeQuery(THIS->driver, q_get(), q_length(), GB.NParam(), arg);
  }
  else
  {
    query = q_get();
  }

  return query;
}


BEGIN_METHOD(CCONNECTION_find, GB_STRING table; GB_STRING query; GB_VALUE param[0])

  char *query;
  CRESULT *result;
  /*char *table = GB.ToZeroString(ARG(table));*/

  CHECK_DB();

  CHECK_OPEN();

  /*if (check_table(THIS, table, TRUE))
    return;*/

  query = get_query(THIS, STRING(table), LENGTH(table),
    MISSING(query) ? NULL : STRING(query),
    MISSING(query) ? 0 : LENGTH(query),
    ARG(param[0]));

  if (!query)
    return;

  result = DB_MakeResult(THIS, RESULT_FIND, NULL, query);

  if (result)
    GB.ReturnObject(result);

END_METHOD


BEGIN_METHOD(CCONNECTION_edit, GB_STRING table; GB_STRING query; GB_VALUE param[0])

  char *query;
  CRESULT *result;
  /*char *table = GB.ToZeroString(ARG(table));*/

  CHECK_DB();

  CHECK_OPEN();

  /*if (check_table(THIS, table, TRUE))
    return;*/

  query = get_query(THIS, STRING(table), LENGTH(table),
    MISSING(query) ? NULL : STRING(query),
    MISSING(query) ? 0 : LENGTH(query),
    ARG(param[0]));

  if (!query)
    return;

  result = DB_MakeResult(THIS, RESULT_EDIT, GB.ToZeroString(ARG(table)), query);

  if (result)
    GB.ReturnObject(result);

END_METHOD


BEGIN_METHOD(CCONNECTION_quote, GB_STRING name)

  CHECK_DB();
  CHECK_OPEN();
  
  q_init();
  q_add(THIS->driver->GetQuote());
  q_add_length(STRING(name), LENGTH(name));
  q_add(THIS->driver->GetQuote());
  
  /* q_get() returns a gambas string */
  GB.ReturnString(q_get());
  
END_METHOD


BEGIN_PROPERTY(CCONNECTION_current)

  if (READ_PROPERTY)
    GB.ReturnObject(_current);
  else
    _current = (CCONNECTION *)VPROP(GB_OBJECT);

END_PROPERTY


BEGIN_PROPERTY(CCONNECTION_charset)

  CHECK_DB();
  CHECK_OPEN();
  if (THIS->charset)
    GB.ReturnString(THIS->charset);
  else
    GB.ReturnConstZeroString("ASCII");

END_PROPERTY


BEGIN_PROPERTY(CCONNECTION_databases)

  CHECK_DB();
  CHECK_OPEN();

  GB.SubCollection.New(&THIS->databases, &_databases_desc, THIS);
  GB.ReturnObject(THIS->databases);

END_PROPERTY


BEGIN_PROPERTY(CCONNECTION_users)

  CHECK_DB();
  CHECK_OPEN();

  GB.SubCollection.New(&THIS->users, &_users_desc, THIS);
  GB.ReturnObject(THIS->users);
  
END_PROPERTY


BEGIN_PROPERTY(CCONNECTION_tables)

  CHECK_DB();
  CHECK_OPEN();

  GB.SubCollection.New(&THIS->tables, &_tables_desc, THIS);  
  GB.ReturnObject(THIS->tables);
  
END_PROPERTY


BEGIN_PROPERTY(CCONNECTION_debug)

  if (READ_PROPERTY)
    GB.ReturnBoolean(DB_IsDebug());
  else
    DB_SetDebug(VPROP(GB_BOOLEAN));

END_PROPERTY


GB_DESC CConnectionDesc[] =
{
  GB_DECLARE("Connection", sizeof(CCONNECTION)),

  GB_METHOD("_new", NULL, CCONNECTION_new, NULL), //"[(URL)s]"),
  GB_METHOD("_free", NULL, CCONNECTION_free, NULL),

  GB_PROPERTY("Type", "s", CCONNECTION_type),
  GB_PROPERTY("Host", "s", CCONNECTION_host),
  GB_PROPERTY("Login", "s", CCONNECTION_user),
  GB_PROPERTY("Password", "s", CCONNECTION_password),
  GB_PROPERTY("Name", "s", CCONNECTION_name),
  GB_PROPERTY("Port", "s", CCONNECTION_port),
  GB_PROPERTY_READ("Charset", "s", CCONNECTION_charset),
  GB_PROPERTY_READ("Version", "i", CCONNECTION_version),

  GB_METHOD("Open", "b", CCONNECTION_open, NULL),
  GB_METHOD("Close", NULL, CCONNECTION_close, NULL),

  GB_METHOD("Exec", "Result", CCONNECTION_exec, "(Request)s(Arguments)."),
  GB_METHOD("Create", "Result", CCONNECTION_create, "(Table)s"),
  GB_METHOD("Find", "Result", CCONNECTION_find, "(Table)s[(Request)s(Arguments).]"),
  GB_METHOD("Edit", "Result", CCONNECTION_edit, "(Table)s[(Request)s(Arguments).]"),

  GB_METHOD("Begin", NULL, CCONNECTION_begin, NULL),
  GB_METHOD("Commit", NULL, CCONNECTION_commit, NULL),
  GB_METHOD("Rollback", NULL, CCONNECTION_rollback, NULL),
  
  GB_METHOD("Quote", "s", CCONNECTION_quote, "(Name)s"),

  GB_PROPERTY("Tables", ".ConnectionTables", CCONNECTION_tables),
  GB_PROPERTY("Databases", ".ConnectionDatabases", CCONNECTION_databases),
  GB_PROPERTY("Users", ".ConnectionUsers", CCONNECTION_users),

  GB_END_DECLARE
};


GB_DESC CDBDesc[] =
{
  GB_DECLARE("DB", 0), GB_VIRTUAL_CLASS(),

  GB_STATIC_PROPERTY("Current", "Connection", CCONNECTION_current),

  GB_STATIC_METHOD("Open", NULL, CCONNECTION_open, NULL),
  GB_STATIC_METHOD("Close", NULL, CCONNECTION_close, NULL),

  GB_STATIC_PROPERTY_READ("Charset", "s", CCONNECTION_charset),
  GB_STATIC_PROPERTY_READ("Version", "i", CCONNECTION_version),
  
  GB_STATIC_PROPERTY("Debug", "b", CCONNECTION_debug),

  GB_STATIC_METHOD("Exec", "Result", CCONNECTION_exec, "(Request)s(Arguments)."),
  GB_STATIC_METHOD("Create", "Result", CCONNECTION_create, "(Table)s"),
  GB_STATIC_METHOD("Find", "Result", CCONNECTION_find, "(Table)s[(Request)s(Arguments).]"),
  GB_STATIC_METHOD("Edit", "Result", CCONNECTION_edit, "(Table)s[(Request)s(Arguments).]"),

  GB_STATIC_METHOD("Begin", NULL, CCONNECTION_begin, NULL),
  GB_STATIC_METHOD("Commit", NULL, CCONNECTION_commit, NULL),
  GB_STATIC_METHOD("Rollback", NULL, CCONNECTION_rollback, NULL),

  GB_STATIC_METHOD("Quote", "s", CCONNECTION_quote, "(Name)s"),
  
  GB_STATIC_PROPERTY("Tables", ".ConnectionTables", CCONNECTION_tables),
  GB_STATIC_PROPERTY("Databases", ".ConnectionDatabases", CCONNECTION_databases),
  GB_STATIC_PROPERTY("Users", ".ConnectionUsers", CCONNECTION_users),

  GB_END_DECLARE
};



Generated by  Doxygen 1.6.0   Back to index