gambas-source-code/main/lib/db/CField.c
Benoît Minisini 9488c7aff7 [DEVELOPMENT ENVIRONMENT]
* NEW: Automatic completion now displays hidden symbols if the class is 
  part of the current project.
* NEW: Support for *.tar.xz source archives.
* NEW: Underscores are now allowed inside a class name.
* BUG: Enabling or disabling tooltips in the option dialog does not crash
  anymore.

[INTERPRETER]
* NEW: Rename many virtual classes everywhere so that the documentation can
  easily extract the property name of the parent class from the virtual
  class name. For example, ".ApplicationArgs" is now ".Application.Args".


git-svn-id: svn://localhost/gambas/trunk@4028 867c0c6c-44f3-4631-809d-bfa615b0a4ec
2011-08-21 21:46:20 +00:00

323 lines
6.4 KiB
C

/***************************************************************************
CField.c
(c) 2000-2011 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 2, 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., 51 Franklin Street, Fifth Floor, Boston,
MA 02110-1301, USA.
***************************************************************************/
#define __CFIELD_C
#include "main.h"
#include "CField.h"
static int valid_field(CFIELD *_object)
{
return !THIS->table || !THIS->table->conn || !THIS->table->conn->db.handle;
}
static bool exist_field(CTABLE *table, const char *name)
{
DB_FIELD *fp;
if (!name || !*name)
return FALSE;
if (table->create)
{
for (fp = table->new_fields; fp; fp = fp->next)
{
if (!strcmp(fp->name, name))
return TRUE;
}
return FALSE;
}
else
return table->driver->Field.Exist(&table->conn->db, table->name, (char *)name);
}
static bool check_field(CTABLE *table, char *name, bool must_exist)
{
bool exist = exist_field(table, name);
if (must_exist)
{
if (!exist)
{
GB.Error("Unknown field: &1.&2", table->name, name);
return TRUE;
}
}
else
{
if (exist)
{
GB.Error("Field already exists: &1.&2", table->name, name);
return TRUE;
}
}
return FALSE;
}
static bool check_type(int type)
{
if (type == GB_T_BOOLEAN
|| type == GB_T_INTEGER
|| type == GB_T_LONG
|| type == GB_T_FLOAT
|| type == GB_T_DATE
|| type == GB_T_STRING
|| type == DB_T_SERIAL
|| type == DB_T_BLOB)
return FALSE;
GB.Error("Bad field type");
return TRUE;
}
static CFIELD *make_field(CTABLE *table, const char *name, bool must_exist)
{
CFIELD *_object;
if (check_field(table, (char *)name, must_exist))
return NULL;
_object = GB.New(GB.FindClass("Field"), NULL, NULL);
THIS->table = table;
THIS->driver = table->conn->driver;
THIS->name = GB.NewZeroString(name);
return _object;
}
void CFIELD_free_info(DB_FIELD *info)
{
GB.FreeString(&info->name);
GB.StoreVariant(NULL, &info->def);
info->type = GB_T_NULL;
info->length = 0;
}
static void add_new_field(CTABLE *table, DB_FIELD *field)
{
DB_FIELD **fp;
fp = &table->new_fields;
for(;;)
{
if (!*fp)
{
*fp = field;
field->next = NULL;
return;
}
fp = &((*fp)->next);
}
}
void *CFIELD_get(CTABLE *table, const char *name)
{
CFIELD *field = make_field(table, name, TRUE);
table->driver->Field.Info(&table->conn->db, table->name, (char *)name, &field->info);
return field;
}
int CFIELD_exist(CTABLE *table, const char *name)
{
return exist_field(table, name);
}
void CFIELD_list(CTABLE *table, char ***list)
{
table->driver->Field.List(&table->conn->db, table->name, list);
}
void CFIELD_release(CTABLE *table, void *_object)
{
THIS->table = NULL;
}
/***************************************************************************
Field
***************************************************************************/
BEGIN_METHOD_VOID(CFIELD_free)
if (!valid_field(THIS))
GB.SubCollection.Remove(THIS->table->fields, THIS->name, 0);
GB.FreeString(&THIS->name);
CFIELD_free_info(&THIS->info);
END_METHOD
/*BEGIN_METHOD_VOID(CFIELD_delete)
THIS->table->conn->driver->User.Delete(THIS->conn->handle, THIS->name);
END_METHOD*/
BEGIN_PROPERTY(CFIELD_name)
GB.ReturnString(THIS->name);
END_PROPERTY
BEGIN_PROPERTY(CFIELD_type)
GB.ReturnInteger(THIS->info.type);
END_PROPERTY
BEGIN_PROPERTY(CFIELD_length)
GB.ReturnInteger(THIS->info.length);
END_PROPERTY
BEGIN_PROPERTY(CFIELD_default)
GB.ReturnPtr(GB_T_VARIANT, &THIS->info.def);
END_PROPERTY
BEGIN_PROPERTY(CFIELD_table)
GB.ReturnObject(THIS->table);
END_PROPERTY
GB_DESC CFieldDesc[] =
{
GB_DECLARE("Field", sizeof(CFIELD)),
GB_NOT_CREATABLE(),
GB_HOOK_CHECK(valid_field),
GB_METHOD("_free", NULL, CFIELD_free, NULL),
//GB_METHOD("Delete", NULL, CFIELD_delete, NULL),
GB_PROPERTY_READ("Name", "s", CFIELD_name),
GB_PROPERTY_READ("Type", "i", CFIELD_type),
GB_PROPERTY_READ("Length", "i", CFIELD_length),
GB_PROPERTY_READ("Default", "v", CFIELD_default),
GB_PROPERTY_READ("Table", "Table", CFIELD_table),
GB_END_DECLARE
};
/***************************************************************************
.Table.Fields
***************************************************************************/
#undef THIS
#define THIS ((GB_SUBCOLLECTION)_object)
BEGIN_METHOD(CFIELD_add, GB_STRING name; GB_INTEGER type; GB_INTEGER length; GB_VARIANT def)
CTABLE *table = GB.SubCollection.Container(THIS);
char *name = GB.ToZeroString(ARG(name));
DB_FIELD new_field, *info;
if (!table->create)
{
GB.Error("Table already exists");
return;
}
if (DB_CheckName(name, "field"))
return;
if (check_field(table, name, FALSE))
return;
/*field = make_field(table, name, FALSE);
if (!field)
return;
GB.SubCollection.Add(THIS, STRING(name), LENGTH(name), field);*/
new_field.next = NULL;
new_field.type = VARG(type);
if (check_type(new_field.type))
return;
new_field.length = VARGOPT(length, 0);
if (new_field.length < 0)
new_field.length = 0;
else if (new_field.length > 65535)
new_field.length = 65535;
/*field->info = new_field;*/
GB.Alloc(POINTER(&info), sizeof(DB_FIELD));
info->next = NULL;
info->type = new_field.type;
info->length = new_field.length;
info->def.type = GB_T_NULL;
if (!MISSING(def))
GB.StoreVariant(ARG(def), &info->def);
info->name = GB.NewString(STRING(name), LENGTH(name));
//DB_LowerString(info->name);
add_new_field(table, info);
END_METHOD
GB_DESC CTableFieldsDesc[] =
{
GB_DECLARE(".Table.Fields", 0), GB_INHERITS(".SubCollection"),
GB_METHOD("Add", NULL, CFIELD_add, "(Name)s(Type)i[(Length)i(Default)v]"),
//GB_METHOD("Remove", NULL, CFIELD_remove, "(Name)s"),
GB_END_DECLARE
};