2007-12-30 17:41:49 +01:00
|
|
|
/***************************************************************************
|
|
|
|
|
|
|
|
CConnection.c
|
|
|
|
|
2011-12-31 03:39:20 +01:00
|
|
|
(c) 2000-2012 Benoît Minisini <gambas@users.sourceforge.net>
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
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
|
2009-08-17 12:41:51 +02:00
|
|
|
the Free Software Foundation; either version 2, or (at your option)
|
2007-12-30 17:41:49 +01:00
|
|
|
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
|
2011-06-03 02:51:09 +02:00
|
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
2011-12-31 03:39:20 +01:00
|
|
|
MA 02110-1301, USA.
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
#define __CCONNECTION_C
|
|
|
|
|
|
|
|
#include "main.h"
|
|
|
|
|
|
|
|
#include "CTable.h"
|
|
|
|
//#include "CView.h"
|
|
|
|
#include "CDatabase.h"
|
|
|
|
#include "CUser.h"
|
|
|
|
#include "CConnection.h"
|
|
|
|
|
|
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
|
|
|
|
Connection
|
|
|
|
|
|
|
|
***************************************************************************/
|
|
|
|
|
|
|
|
static CCONNECTION *_current = NULL;
|
|
|
|
|
|
|
|
static GB_SUBCOLLECTION_DESC _databases_desc =
|
|
|
|
{
|
2011-08-21 23:46:20 +02:00
|
|
|
".Connection.Databases",
|
2007-12-30 17:41:49 +01:00
|
|
|
(void *)CDATABASE_get,
|
|
|
|
(void *)CDATABASE_exist,
|
|
|
|
(void *)CDATABASE_list,
|
|
|
|
(void *)CDATABASE_release
|
|
|
|
};
|
|
|
|
|
|
|
|
static GB_SUBCOLLECTION_DESC _users_desc =
|
|
|
|
{
|
2011-08-21 23:46:20 +02:00
|
|
|
".Connection.Users",
|
2007-12-30 17:41:49 +01:00
|
|
|
(void *)CUSER_get,
|
|
|
|
(void *)CUSER_exist,
|
|
|
|
(void *)CUSER_list,
|
|
|
|
(void *)CUSER_release
|
|
|
|
};
|
|
|
|
|
|
|
|
static GB_SUBCOLLECTION_DESC _tables_desc =
|
|
|
|
{
|
2011-08-21 23:46:20 +02:00
|
|
|
".Connection.Tables",
|
2007-12-30 17:41:49 +01:00
|
|
|
(void *)CTABLE_get,
|
|
|
|
(void *)CTABLE_exist,
|
|
|
|
(void *)CTABLE_list,
|
|
|
|
(void *)CTABLE_release
|
|
|
|
};
|
|
|
|
|
|
|
|
/*static GB_SUBCOLLECTION_DESC _views_desc =
|
|
|
|
{
|
|
|
|
".ConnectionViews",
|
|
|
|
(void *)CVIEW_get,
|
|
|
|
(void *)CVIEW_exist,
|
|
|
|
(void *)CVIEW_list
|
|
|
|
};*/
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
static void open_connection(CCONNECTION *_object)
|
|
|
|
{
|
|
|
|
DB_Open(&THIS->desc, &THIS->driver, &THIS->db);
|
|
|
|
THIS->limit = 0;
|
|
|
|
THIS->trans = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool check_opened(CCONNECTION *_object)
|
|
|
|
{
|
2010-09-16 02:57:35 +02:00
|
|
|
DB_CurrentDatabase = &THIS->db;
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
if (!THIS->db.handle)
|
|
|
|
open_connection(THIS);
|
|
|
|
|
|
|
|
if (!THIS->db.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 **)(void *)&_object)) \
|
|
|
|
return;
|
|
|
|
|
|
|
|
static void close_connection(CCONNECTION *_object)
|
|
|
|
{
|
|
|
|
if (!THIS->db.handle)
|
|
|
|
return;
|
|
|
|
|
|
|
|
GB.Unref(POINTER(&THIS->databases));
|
|
|
|
THIS->databases = NULL;
|
|
|
|
GB.Unref(POINTER(&THIS->users));
|
|
|
|
THIS->users = NULL;
|
|
|
|
GB.Unref(POINTER(&THIS->tables));
|
|
|
|
THIS->tables = NULL;
|
|
|
|
|
|
|
|
THIS->driver->Close(&THIS->db);
|
|
|
|
GB.FreeString(&THIS->db.charset);
|
|
|
|
|
|
|
|
THIS->db.handle = NULL;
|
|
|
|
THIS->driver = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-07-17 03:29:39 +02:00
|
|
|
BEGIN_METHOD(CCONNECTION_new, GB_STRING url)
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2009-07-17 03:29:39 +02:00
|
|
|
char *url, *name, *p;
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
THIS->db.handle = NULL;
|
|
|
|
THIS->db.ignore_case = FALSE; // Now case is sensitive by default!
|
2011-12-22 01:31:57 +01:00
|
|
|
THIS->db.timeout = 20; // Connection timeout is 20 seconds by default
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
if (_current == NULL)
|
|
|
|
_current = THIS;
|
|
|
|
|
2009-07-17 03:29:39 +02:00
|
|
|
if (MISSING(url))
|
|
|
|
return;
|
|
|
|
|
|
|
|
url = GB.ToZeroString(ARG(url));
|
|
|
|
|
|
|
|
p = index(url, ':');
|
|
|
|
if (!p || p == url) goto __BAD_URL;
|
|
|
|
*p++ = 0;
|
|
|
|
if (p[0] != '/' || p[1] != '/') goto __BAD_URL;
|
|
|
|
p += 2;
|
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
THIS->desc.type = GB.NewZeroString(url);
|
2009-07-17 03:29:39 +02:00
|
|
|
url = p;
|
|
|
|
|
|
|
|
p = rindex(url, '/');
|
|
|
|
if (!p || p == url) goto __BAD_URL;
|
|
|
|
*p++ = 0;
|
|
|
|
|
|
|
|
name = p;
|
|
|
|
|
|
|
|
p = index(url, '@');
|
|
|
|
if (p)
|
|
|
|
{
|
|
|
|
if (p == url)
|
|
|
|
goto __BAD_URL;
|
|
|
|
*p = 0;
|
2010-06-05 01:48:53 +02:00
|
|
|
THIS->desc.user = GB.NewZeroString(url);
|
2009-07-17 03:29:39 +02:00
|
|
|
url = p + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
p = index(url, ':');
|
|
|
|
if (p)
|
|
|
|
{
|
|
|
|
*p = 0;
|
2010-06-05 01:48:53 +02:00
|
|
|
THIS->desc.port = GB.NewZeroString(p + 1);
|
2009-07-17 03:29:39 +02:00
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2010-06-05 01:48:53 +02:00
|
|
|
THIS->desc.host = GB.NewZeroString(url);
|
|
|
|
THIS->desc.name = GB.NewZeroString(name);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2009-07-17 03:29:39 +02:00
|
|
|
__BAD_URL:
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
GB.Error("Malformed URL");
|
2009-07-17 03:29:39 +02:00
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD_VOID(CCONNECTION_free)
|
|
|
|
|
|
|
|
close_connection(THIS);
|
|
|
|
|
|
|
|
if (_current == THIS)
|
|
|
|
_current = NULL;
|
|
|
|
|
|
|
|
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->db.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)
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
CHECK_OPEN();
|
|
|
|
|
|
|
|
GB.ReturnInteger(THIS->db.version);
|
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
|
|
|
2011-12-22 01:31:57 +01:00
|
|
|
BEGIN_PROPERTY(Connection_Timeout)
|
|
|
|
|
|
|
|
if (READ_PROPERTY)
|
|
|
|
GB.ReturnInteger(THIS->db.timeout);
|
|
|
|
else
|
|
|
|
THIS->db.timeout = VPROP(GB_INTEGER);
|
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
BEGIN_PROPERTY(CCONNECTION_opened)
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
|
|
|
|
GB.ReturnBoolean(THIS->db.handle != NULL);
|
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_PROPERTY(CCONNECTION_error)
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
|
|
|
|
GB.ReturnInteger(THIS->db.error);
|
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD_VOID(CCONNECTION_open)
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
|
|
|
|
if (THIS->db.handle)
|
|
|
|
{
|
|
|
|
GB.Error("Connection already opened");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
open_connection(THIS);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD_VOID(CCONNECTION_close)
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
|
|
|
|
close_connection(THIS);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
2009-07-17 03:29:39 +02:00
|
|
|
#if 0
|
2007-12-30 17:41:49 +01:00
|
|
|
BEGIN_PROPERTY(CCONNECTION_ignore_case)
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
CHECK_OPEN();
|
|
|
|
|
|
|
|
if (READ_PROPERTY)
|
|
|
|
GB.ReturnBoolean(THIS->db.ignore_case);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (THIS->db.flags.no_case)
|
|
|
|
{
|
|
|
|
if (THIS->db.ignore_case)
|
|
|
|
GB.Error("This database driver cannot be case sensitive");
|
|
|
|
else
|
|
|
|
GB.Error("This database driver is always case sensitive");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
THIS->db.ignore_case = VPROP(GB_BOOLEAN);
|
|
|
|
}
|
|
|
|
|
|
|
|
END_PROPERTY
|
2009-07-17 03:29:39 +02:00
|
|
|
#endif
|
|
|
|
|
|
|
|
BEGIN_PROPERTY(CCONNECTION_ignore_charset)
|
|
|
|
|
|
|
|
CHECK_DB();
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2009-07-17 03:29:39 +02:00
|
|
|
if (READ_PROPERTY)
|
|
|
|
GB.ReturnBoolean(THIS->ignore_charset);
|
|
|
|
else
|
|
|
|
THIS->ignore_charset = VPROP(GB_BOOLEAN);
|
|
|
|
|
|
|
|
END_PROPERTY
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
BEGIN_METHOD_VOID(CCONNECTION_begin)
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
CHECK_OPEN();
|
|
|
|
|
|
|
|
if (!THIS->db.flags.no_nest || THIS->trans == 0)
|
|
|
|
THIS->driver->Begin(&THIS->db);
|
|
|
|
THIS->trans++;
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD_VOID(CCONNECTION_commit)
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
CHECK_OPEN();
|
|
|
|
|
|
|
|
if (THIS->trans == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
THIS->trans--;
|
|
|
|
if (!THIS->db.flags.no_nest || THIS->trans == 0)
|
|
|
|
THIS->driver->Commit(&THIS->db);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD_VOID(CCONNECTION_rollback)
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
CHECK_OPEN();
|
|
|
|
|
|
|
|
if (THIS->trans == 0)
|
|
|
|
return;
|
|
|
|
|
|
|
|
THIS->trans--;
|
|
|
|
if (!THIS->db.flags.no_nest || THIS->trans == 0)
|
|
|
|
THIS->driver->Rollback(&THIS->db);
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD(CCONNECTION_limit, GB_INTEGER limit)
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
CHECK_OPEN();
|
|
|
|
|
|
|
|
THIS->limit = VARG(limit);
|
|
|
|
GB.ReturnObject(THIS);
|
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
|
|
static char *_make_query_buffer;
|
|
|
|
static char *_make_query_original;
|
|
|
|
|
|
|
|
static void make_query_get_param(int index, char **str, int *len)
|
|
|
|
{
|
|
|
|
if (index == 1)
|
|
|
|
*str = _make_query_buffer;
|
|
|
|
else if (index == 2)
|
|
|
|
*str = _make_query_original;
|
|
|
|
|
|
|
|
*len = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *make_query(CCONNECTION *_object, char *pattern, int len, int narg, GB_VALUE *arg)
|
|
|
|
{
|
|
|
|
char *query;
|
2008-02-02 11:54:13 +01:00
|
|
|
const char *keyword;
|
2007-12-30 17:41:49 +01:00
|
|
|
char buffer[32];
|
|
|
|
|
|
|
|
query = DB_MakeQuery(THIS->driver, pattern, len, narg, arg);
|
|
|
|
|
|
|
|
if (query && THIS->limit > 0 && strncasecmp(query, "SELECT ", 7) == 0)
|
|
|
|
{
|
|
|
|
keyword = THIS->db.limit.keyword;
|
|
|
|
if (!keyword)
|
|
|
|
keyword = "LIMIT";
|
|
|
|
|
2008-01-06 21:06:44 +01:00
|
|
|
snprintf(buffer, sizeof(buffer), "%s %d", keyword, THIS->limit);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
_make_query_buffer = buffer;
|
|
|
|
_make_query_original = &query[7];
|
|
|
|
|
|
|
|
switch (THIS->db.limit.pos)
|
|
|
|
{
|
|
|
|
case DB_LIMIT_AT_BEGIN:
|
|
|
|
query = GB.SubstString("SELECT &1 &2", 0, make_query_get_param);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case DB_LIMIT_AT_END:
|
|
|
|
default:
|
|
|
|
query = GB.SubstString("SELECT &2 &1", 0, make_query_get_param);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
THIS->limit = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return query;
|
|
|
|
}
|
|
|
|
|
|
|
|
BEGIN_METHOD(CCONNECTION_exec, GB_STRING query; GB_VALUE param[0])
|
|
|
|
|
|
|
|
char *query;
|
|
|
|
CRESULT *result;
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
|
|
|
|
CHECK_OPEN();
|
|
|
|
|
|
|
|
query = make_query(THIS, 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();
|
|
|
|
|
2008-12-31 16:55:40 +01:00
|
|
|
if (!table || !*table)
|
|
|
|
{
|
|
|
|
GB.Error("Void table name");
|
|
|
|
return;
|
|
|
|
}
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
result = DB_MakeResult(THIS, RESULT_CREATE, table, NULL);
|
|
|
|
|
|
|
|
if (result)
|
|
|
|
GB.ReturnObject(result);
|
|
|
|
else
|
|
|
|
GB.ReturnNull();
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
static char *get_query(char *prefix, CCONNECTION *_object, char *table, int len_table, char *query, int len_query, GB_VALUE *arg)
|
|
|
|
{
|
2008-12-31 16:55:40 +01:00
|
|
|
if (!len_table)
|
|
|
|
{
|
|
|
|
GB.Error("Void table name");
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
q_init();
|
|
|
|
|
|
|
|
q_add(prefix);
|
|
|
|
q_add(" ");
|
|
|
|
q_add(THIS->driver->GetQuote());
|
|
|
|
q_add_length(table, len_table);
|
|
|
|
q_add(THIS->driver->GetQuote());
|
|
|
|
|
|
|
|
if (query && len_query > 0)
|
|
|
|
{
|
|
|
|
q_add(" ");
|
2010-02-10 02:58:50 +01:00
|
|
|
if (strncasecmp(query, "WHERE ", 6) && strncasecmp(query, "ORDER BY ", 9))
|
2007-12-30 17:41:49 +01:00
|
|
|
q_add("WHERE ");
|
|
|
|
q_add_length(query, len_query);
|
|
|
|
}
|
|
|
|
|
|
|
|
query = make_query(THIS, q_get(), q_length(), GB.NParam(), arg);
|
|
|
|
|
|
|
|
return query;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD(CCONNECTION_find, GB_STRING table; GB_STRING query; GB_VALUE param[0])
|
|
|
|
|
|
|
|
char *query;
|
|
|
|
CRESULT *result;
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
CHECK_OPEN();
|
|
|
|
|
|
|
|
query = get_query("SELECT * FROM", 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_delete, GB_STRING table; GB_STRING query; GB_VALUE param[0])
|
|
|
|
|
|
|
|
char *query;
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
CHECK_OPEN();
|
|
|
|
|
|
|
|
query = get_query("DELETE FROM", THIS, STRING(table), LENGTH(table),
|
|
|
|
MISSING(query) ? NULL : STRING(query),
|
|
|
|
MISSING(query) ? 0 : LENGTH(query),
|
|
|
|
ARG(param[0]));
|
|
|
|
|
|
|
|
if (!query)
|
|
|
|
return;
|
|
|
|
|
|
|
|
DB_MakeResult(THIS, RESULT_DELETE, NULL, query);
|
|
|
|
|
|
|
|
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("SELECT * FROM", 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
|
|
|
|
|
|
|
|
|
2009-11-28 02:22:00 +01:00
|
|
|
BEGIN_METHOD(CCONNECTION_quote, GB_STRING name; GB_BOOLEAN is_table)
|
|
|
|
|
|
|
|
char *name = STRING(name);
|
|
|
|
int len = LENGTH(name);
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
CHECK_OPEN();
|
|
|
|
|
2012-10-23 13:21:43 +02:00
|
|
|
if (VARGOPT(is_table, FALSE)) // && THIS->db.flags.schema)
|
2009-11-28 02:22:00 +01:00
|
|
|
GB.ReturnNewZeroString(DB_GetQuotedTable(THIS->driver, &THIS->db, GB.ToZeroString(ARG(name))));
|
|
|
|
else
|
|
|
|
{
|
|
|
|
q_init();
|
|
|
|
q_add(THIS->driver->GetQuote());
|
|
|
|
q_add_length(name, len);
|
|
|
|
q_add(THIS->driver->GetQuote());
|
|
|
|
GB.ReturnString(q_get());
|
|
|
|
}
|
|
|
|
|
|
|
|
END_METHOD
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2009-11-28 02:22:00 +01:00
|
|
|
|
|
|
|
BEGIN_METHOD(CCONNECTION_format_blob, GB_STRING data)
|
|
|
|
|
|
|
|
DB_BLOB blob;
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
CHECK_OPEN();
|
|
|
|
|
|
|
|
blob.data = STRING(data);
|
|
|
|
blob.length = LENGTH(data);
|
|
|
|
|
|
|
|
q_init();
|
|
|
|
DB_CurrentDatabase = &THIS->db;
|
|
|
|
(*THIS->driver->FormatBlob)(&blob, q_add_length);
|
2007-12-30 17:41:49 +01:00
|
|
|
GB.ReturnString(q_get());
|
|
|
|
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_METHOD(CCONNECTION_subst, GB_STRING query; GB_VALUE param[0])
|
|
|
|
|
|
|
|
char *query;
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
|
|
|
|
CHECK_OPEN();
|
|
|
|
|
|
|
|
query = make_query(THIS, STRING(query), LENGTH(query), GB.NParam(), ARG(param[0]));
|
|
|
|
|
|
|
|
if (!query)
|
|
|
|
return;
|
|
|
|
|
|
|
|
GB.ReturnString(query);
|
|
|
|
|
|
|
|
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->db.charset)
|
|
|
|
GB.ReturnString(THIS->db.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_views)
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
CHECK_OPEN();
|
|
|
|
|
|
|
|
GB.SubCollection.New(&THIS->views, &_views_desc, THIS);
|
|
|
|
GB.ReturnObject(THIS->views);
|
|
|
|
|
|
|
|
END_PROPERTY*/
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_PROPERTY(CCONNECTION_debug)
|
|
|
|
|
|
|
|
if (READ_PROPERTY)
|
|
|
|
GB.ReturnBoolean(DB_IsDebug());
|
|
|
|
else
|
|
|
|
DB_SetDebug(VPROP(GB_BOOLEAN));
|
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
|
|
|
2012-04-03 02:21:32 +02:00
|
|
|
BEGIN_PROPERTY(Connection_Handle)
|
|
|
|
|
|
|
|
CHECK_DB();
|
|
|
|
CHECK_OPEN();
|
|
|
|
GB.ReturnPointer(THIS->db.handle);
|
|
|
|
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
|
|
|
2007-12-30 17:41:49 +01:00
|
|
|
GB_DESC CConnectionDesc[] =
|
|
|
|
{
|
|
|
|
GB_DECLARE("Connection", sizeof(CCONNECTION)),
|
|
|
|
|
2009-07-17 03:29:39 +02:00
|
|
|
GB_METHOD("_new", NULL, CCONNECTION_new, "[(DatabaseURL)s]"),
|
2007-12-30 17:41:49 +01:00
|
|
|
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("User", "s", CCONNECTION_user),
|
|
|
|
GB_PROPERTY("Password", "s", CCONNECTION_password),
|
|
|
|
GB_PROPERTY("Name", "s", CCONNECTION_name),
|
|
|
|
GB_PROPERTY("Port", "s", CCONNECTION_port),
|
2011-12-22 01:31:57 +01:00
|
|
|
GB_PROPERTY("Timeout", "i", Connection_Timeout),
|
2007-12-30 17:41:49 +01:00
|
|
|
GB_PROPERTY_READ("Charset", "s", CCONNECTION_charset),
|
|
|
|
GB_PROPERTY_READ("Version", "i", CCONNECTION_version),
|
|
|
|
GB_PROPERTY_READ("Opened", "b", CCONNECTION_opened),
|
|
|
|
GB_PROPERTY_READ("Error", "i", CCONNECTION_error),
|
2009-07-17 03:29:39 +02:00
|
|
|
GB_PROPERTY("IgnoreCharset", "b", CCONNECTION_ignore_charset),
|
2012-04-03 02:21:32 +02:00
|
|
|
GB_STATIC_PROPERTY_READ("Handle", "p", Connection_Handle),
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
GB_METHOD("Open", NULL, CCONNECTION_open, NULL),
|
|
|
|
GB_METHOD("Close", NULL, CCONNECTION_close, NULL),
|
|
|
|
|
|
|
|
GB_METHOD("Limit", "Connection", CCONNECTION_limit, "(Limit)i"),
|
|
|
|
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("Delete", NULL, CCONNECTION_delete, "(Table)s[(Request)s(Arguments).]"),
|
|
|
|
GB_METHOD("Subst", "s", CCONNECTION_subst, "(Format)s(Arguments)."),
|
|
|
|
|
|
|
|
GB_METHOD("Begin", NULL, CCONNECTION_begin, NULL),
|
|
|
|
GB_METHOD("Commit", NULL, CCONNECTION_commit, NULL),
|
|
|
|
GB_METHOD("Rollback", NULL, CCONNECTION_rollback, NULL),
|
|
|
|
|
2009-11-28 02:22:00 +01:00
|
|
|
GB_METHOD("Quote", "s", CCONNECTION_quote, "(Name)s[(Table)b]"),
|
|
|
|
GB_METHOD("FormatBlob", "s", CCONNECTION_format_blob, "(Data)s"),
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-08-21 23:46:20 +02:00
|
|
|
GB_PROPERTY("Tables", ".Connection.Tables", CCONNECTION_tables),
|
|
|
|
GB_PROPERTY("Databases", ".Connection.Databases", CCONNECTION_databases),
|
|
|
|
GB_PROPERTY("Users", ".Connection.Users", CCONNECTION_users),
|
2007-12-30 17:41:49 +01:00
|
|
|
//GB_PROPERTY("Views", ".ConnectionViews", CCONNECTION_views),
|
|
|
|
|
|
|
|
GB_CONSTANT("_Properties", "s", "Type,Host,Login,Password,Name,Port"),
|
|
|
|
|
|
|
|
GB_END_DECLARE
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
GB_DESC CDBDesc[] =
|
|
|
|
{
|
|
|
|
GB_DECLARE("DB", 0), GB_VIRTUAL_CLASS(),
|
|
|
|
|
|
|
|
GB_CONSTANT("Boolean", "i", GB_T_BOOLEAN),
|
|
|
|
GB_CONSTANT("Integer", "i", GB_T_INTEGER),
|
|
|
|
GB_CONSTANT("Long", "i", GB_T_LONG),
|
|
|
|
GB_CONSTANT("Float", "i", GB_T_FLOAT),
|
|
|
|
GB_CONSTANT("Date", "i", GB_T_DATE),
|
|
|
|
GB_CONSTANT("String", "i", GB_T_STRING),
|
|
|
|
GB_CONSTANT("Serial", "i", DB_T_SERIAL),
|
|
|
|
GB_CONSTANT("Blob", "i", DB_T_BLOB),
|
|
|
|
|
|
|
|
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_READ("Opened", "b", CCONNECTION_opened),
|
|
|
|
GB_STATIC_PROPERTY_READ("Error", "i", CCONNECTION_error),
|
2009-07-17 03:29:39 +02:00
|
|
|
GB_STATIC_PROPERTY("IgnoreCharset", "b", CCONNECTION_ignore_charset),
|
2012-04-03 02:21:32 +02:00
|
|
|
GB_STATIC_PROPERTY_READ("Handle", "p", Connection_Handle),
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
GB_STATIC_PROPERTY("Debug", "b", CCONNECTION_debug),
|
|
|
|
|
|
|
|
GB_STATIC_METHOD("Limit", "Connection", CCONNECTION_limit, "(Limit)i"),
|
|
|
|
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("Delete", NULL, CCONNECTION_delete, "(Table)s[(Request)s(Arguments).]"),
|
|
|
|
GB_STATIC_METHOD("Subst", "s", CCONNECTION_subst, "(Format)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),
|
|
|
|
|
2009-11-28 02:22:00 +01:00
|
|
|
GB_STATIC_METHOD("Quote", "s", CCONNECTION_quote, "(Name)s[(Table)b]"),
|
|
|
|
GB_STATIC_METHOD("FormatBlob", "s", CCONNECTION_format_blob, "(Data)s"),
|
2007-12-30 17:41:49 +01:00
|
|
|
|
2011-08-21 23:46:20 +02:00
|
|
|
GB_STATIC_PROPERTY("Tables", ".Connection.Tables", CCONNECTION_tables),
|
2007-12-30 17:41:49 +01:00
|
|
|
//GB_STATIC_PROPERTY("Views", ".ConnectionViews", CCONNECTION_views),
|
2011-08-21 23:46:20 +02:00
|
|
|
GB_STATIC_PROPERTY("Databases", ".Connection.Databases", CCONNECTION_databases),
|
|
|
|
GB_STATIC_PROPERTY("Users", ".Connection.Users", CCONNECTION_users),
|
2007-12-30 17:41:49 +01:00
|
|
|
|
|
|
|
GB_END_DECLARE
|
|
|
|
};
|
|
|
|
|
|
|
|
|