83d84d7ee5
* NEW: Support for the Index class interface changes. * BUG: CSV import does not crash anymore when the imported file size is lower than 64K. * BUG: Do not crash if a component is not installed. [INTERPRETER] * BUG: Error.Text does not split the error message and its argument in debug mode. * BUG: Fix many breaks in strict aliasing rules. [SCRIPTER] * BUG: Do not crash if a component is not installed. [GB.DB] * NEW: Better support for postgresql schemas. * NEW: Connection.Quote() takes one more optional boolean argument that tells if we want to quote a table name. In that case, schemas are taken into account. * NEW: Connection.FormatBlob() is a new function that returns a string that can be used as a blob contents in a SQL expression. * NEW: Index.Fields now returns a string array of index fields. * NEW: Index.Add() second argument is now a string array of index fields. git-svn-id: svn://localhost/gambas/trunk@2442 867c0c6c-44f3-4631-809d-bfa615b0a4ec
268 lines
5.5 KiB
C
268 lines
5.5 KiB
C
/***************************************************************************
|
|
|
|
CIndex.c
|
|
|
|
(c) 2000-2009 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., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
***************************************************************************/
|
|
|
|
#define __CINDEX_C
|
|
|
|
#include "main.h"
|
|
|
|
#include "CIndex.h"
|
|
|
|
|
|
static int valid_index(CINDEX *_object)
|
|
{
|
|
return !THIS->table || !THIS->table->conn || !THIS->table->conn->db.handle;
|
|
}
|
|
|
|
|
|
static bool exist_index(CTABLE *table, const char *name)
|
|
{
|
|
if (!name || !*name)
|
|
return FALSE;
|
|
|
|
return table->driver->Index.Exist(&table->conn->db, table->name, (char *)name);
|
|
}
|
|
|
|
static bool check_index(CTABLE *table, const char *name, bool must_exist)
|
|
{
|
|
bool exist = exist_index(table, name);
|
|
|
|
if (must_exist)
|
|
{
|
|
if (!exist)
|
|
{
|
|
GB.Error("Unknown index: &1.&2", table->name, name);
|
|
return TRUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (exist)
|
|
{
|
|
GB.Error("Index already exists: &1.&2", table->name, name);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static CINDEX *make_index(CTABLE *table, const char *name, bool must_exist)
|
|
{
|
|
CINDEX *_object;
|
|
|
|
if (check_index(table, name, must_exist))
|
|
return NULL;
|
|
|
|
GB.New(POINTER(&_object), GB.FindClass("Index"), NULL, NULL);
|
|
THIS->table = table;
|
|
THIS->driver = table->conn->driver;
|
|
GB.NewString(&THIS->name, name, 0);
|
|
|
|
return _object;
|
|
}
|
|
|
|
|
|
void *CINDEX_get(CTABLE *table, const char *name)
|
|
{
|
|
CINDEX *index = make_index(table, name, TRUE);
|
|
table->driver->Index.Info(&table->conn->db, table->name, (char *)name, &index->info);
|
|
return index;
|
|
}
|
|
|
|
|
|
int CINDEX_exist(CTABLE *table, const char *name)
|
|
{
|
|
return exist_index(table, name);
|
|
}
|
|
|
|
|
|
void CINDEX_list(CTABLE *table, char ***list)
|
|
{
|
|
table->driver->Index.List(&table->conn->db, table->name, list);
|
|
}
|
|
|
|
void CINDEX_release(CTABLE *table, void *_object)
|
|
{
|
|
THIS->table = NULL;
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
Index
|
|
|
|
***************************************************************************/
|
|
|
|
BEGIN_METHOD_VOID(CINDEX_free)
|
|
|
|
if (!valid_index(THIS))
|
|
GB.SubCollection.Remove(THIS->table->indexes, THIS->name, 0);
|
|
|
|
GB.FreeString(&THIS->name);
|
|
|
|
GB.FreeString(&THIS->info.name);
|
|
GB.FreeString(&THIS->info.fields);
|
|
THIS->info.unique = FALSE;
|
|
|
|
END_METHOD
|
|
|
|
|
|
|
|
BEGIN_PROPERTY(CINDEX_name)
|
|
|
|
GB.ReturnString(THIS->name);
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
BEGIN_PROPERTY(CINDEX_fields)
|
|
|
|
GB_ARRAY array;
|
|
char *fields;
|
|
char *name;
|
|
|
|
GB.NewString(&fields, THIS->info.fields, 0);
|
|
GB.Array.New(&array, GB_T_STRING, 0);
|
|
|
|
name = strtok(fields, ",");
|
|
while (name)
|
|
{
|
|
GB.NewString((char **)GB.Array.Add(array), name, 0);
|
|
name = strtok(NULL, ",");
|
|
}
|
|
|
|
GB.FreeString(&fields);
|
|
GB.ReturnObject(array);
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
BEGIN_PROPERTY(CINDEX_unique)
|
|
|
|
GB.ReturnBoolean(THIS->info.unique);
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
BEGIN_PROPERTY(CINDEX_primary)
|
|
|
|
GB.ReturnBoolean(THIS->info.primary);
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
BEGIN_PROPERTY(CINDEX_table)
|
|
|
|
GB.ReturnObject(THIS->table);
|
|
|
|
END_PROPERTY
|
|
|
|
|
|
GB_DESC CIndexDesc[] =
|
|
{
|
|
GB_DECLARE("Index", sizeof(CINDEX)),
|
|
GB_NOT_CREATABLE(),
|
|
GB_HOOK_CHECK(valid_index),
|
|
|
|
GB_METHOD("_free", NULL, CINDEX_free, NULL),
|
|
|
|
GB_PROPERTY_READ("Name", "s", CINDEX_name),
|
|
GB_PROPERTY_READ("Unique", "b", CINDEX_unique),
|
|
GB_PROPERTY_READ("Primary", "b", CINDEX_primary),
|
|
GB_PROPERTY_READ("Fields", "String[]", CINDEX_fields),
|
|
|
|
GB_PROPERTY_READ("Table", "Table", CINDEX_table),
|
|
|
|
GB_END_DECLARE
|
|
};
|
|
|
|
|
|
/***************************************************************************
|
|
|
|
.TableIndexes
|
|
|
|
***************************************************************************/
|
|
|
|
#undef THIS
|
|
#define THIS ((GB_SUBCOLLECTION)_object)
|
|
|
|
BEGIN_METHOD(CINDEX_add, GB_STRING name; GB_OBJECT fields; GB_BOOLEAN unique)
|
|
|
|
CTABLE *table = GB.SubCollection.Container(THIS);
|
|
char *name = GB.ToZeroString(ARG(name));
|
|
DB_INDEX info;
|
|
int i;
|
|
GB_ARRAY fields;
|
|
|
|
if (DB_CheckNameWith(name, "index", "."))
|
|
return;
|
|
|
|
if (check_index(table, name, FALSE))
|
|
return;
|
|
|
|
info.name = name;
|
|
|
|
fields = (GB_ARRAY)VARG(fields);
|
|
q_init();
|
|
for (i = 0; i < GB.Array.Count(fields); i++)
|
|
{
|
|
if (i > 0)
|
|
q_add(",");
|
|
|
|
q_add(table->driver->GetQuote());
|
|
q_add(*(char **)GB.Array.Get(fields, i));
|
|
q_add(table->driver->GetQuote());
|
|
}
|
|
|
|
info.fields = q_get();
|
|
info.unique = VARGOPT(unique, FALSE);
|
|
|
|
table->driver->Index.Create(&table->conn->db, table->name, name, &info);
|
|
|
|
END_METHOD
|
|
|
|
|
|
BEGIN_METHOD(CINDEX_remove, GB_STRING name)
|
|
|
|
CTABLE *table = GB.SubCollection.Container(THIS);
|
|
char *name = GB.ToZeroString(ARG(name));
|
|
|
|
if (check_index(table, name, TRUE))
|
|
return;
|
|
|
|
table->driver->Index.Delete(&table->conn->db, table->name, name);
|
|
|
|
END_METHOD
|
|
|
|
|
|
GB_DESC CTableIndexesDesc[] =
|
|
{
|
|
GB_DECLARE(".TableIndexes", 0), GB_INHERITS(".SubCollection"),
|
|
|
|
GB_METHOD("Add", NULL, CINDEX_add, "(Name)s(Fields)String[];[(Unique)b]"),
|
|
GB_METHOD("Remove", NULL, CINDEX_remove, "(Name)s"),
|
|
|
|
GB_END_DECLARE
|
|
};
|
|
|
|
|