|
/****************************************************************************
|
|
* This file is part of the project AqDataBase.
|
|
* AqFinance (c) by 2015 Martin Preuss, all rights reserved.
|
|
*
|
|
* The license for this file can be found in the file COPYING which you
|
|
* should have received along with this file.
|
|
****************************************************************************/
|
|
|
|
|
|
|
|
|
|
|
|
int AQDB_DbFile_ReadTableAt(AQDB_DB *db, AQDB_DBFILE_TABLE *dbt, uint64_t offset) {
|
|
AQDB_DB_FILE *xdb;
|
|
int rv;
|
|
int64_t rd;
|
|
uint8_t *p=NULL;
|
|
|
|
assert(db);
|
|
xdb=GWEN_INHERIT_GETDATA(AQDB_DB, AQDB_DB_FILE, db);
|
|
assert(xdb);
|
|
|
|
/* read data */
|
|
rd=AQFS_File_ReadDataAt(xdb->file, offset, &p, 0);
|
|
if (rd<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", (int) rd);
|
|
return (int) rd;
|
|
}
|
|
|
|
/* parse it into table */
|
|
rv=AQDB_DbFile_Table_ReadFromBuffer(dbt, p, rd);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
free(p);
|
|
return rv;
|
|
}
|
|
|
|
/* done with data */
|
|
free(p);
|
|
|
|
/* done entirely */
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int AQDB_DbFile_ReadTableFields(AQDB_DB *db, AQDB_DBFILE_TABLE *dbt) {
|
|
AQDB_DB_FILE *xdb;
|
|
uint64_t offset;
|
|
int rv;
|
|
|
|
assert(db);
|
|
xdb=GWEN_INHERIT_GETDATA(AQDB_DB, AQDB_DB_FILE, db);
|
|
assert(xdb);
|
|
|
|
/* read object table */
|
|
offset=AQDB_DbFile_Table_GetOffsetObjectTable(dbt);
|
|
if (offset>0) {
|
|
AQFS_TABLE_LIST *ftl;
|
|
|
|
ftl=AQFS_Table_List_new();
|
|
rv=AQFS_File_ReadTableList(xdb->file, offset, ftl);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
AQFS_Table_List_free(ftl);
|
|
return rv;
|
|
}
|
|
AQDB_DbFile_Table_SetTableListObjects(dbt, ftl);
|
|
}
|
|
|
|
/* read column table */
|
|
offset=AQDB_DbFile_Table_GetOffsetColumnTable(dbt);
|
|
if (offset>0) {
|
|
AQFS_TABLE_LIST *ftl;
|
|
|
|
ftl=AQFS_Table_List_new();
|
|
rv=AQFS_File_ReadTableList(xdb->file, offset, ftl);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
AQFS_Table_List_free(ftl);
|
|
return rv;
|
|
}
|
|
AQDB_DbFile_Table_SetTableListColumns(dbt, ftl);
|
|
}
|
|
|
|
/* read column list */
|
|
if (1) {
|
|
AQFS_TABLE_LIST *ftl;
|
|
|
|
ftl=AQDB_DbFile_Table_GetTableListColumns(dbt);
|
|
if (ftl) {
|
|
AQDB_COLUMN_LIST *cl;
|
|
AQFS_TABLE *ft;
|
|
|
|
cl=AQDB_Column_List_new();
|
|
|
|
/* read columns from all tables */
|
|
ft=AQFS_Table_List_First(ftl);
|
|
while(ft) {
|
|
uint64_t maxEntries;
|
|
uint64_t idx;
|
|
uint64_t *ptr;
|
|
|
|
maxEntries=AQFS_Table_GetMaxEntries(ft);
|
|
DBG_VERBOUS(AQDB_LOGDOMAIN, "Reading entries from table (maxEntries=%d, free entries=%d)",
|
|
(int) maxEntries,
|
|
(int) AQFS_Table_GetFreeEntries(ft));
|
|
ptr=AQFS_Table_GetPtrEntries(ft);
|
|
for (idx=0; idx<maxEntries; idx++) {
|
|
uint64_t offset;
|
|
|
|
offset=*(ptr++);
|
|
if (offset>0) {
|
|
AQDB_OBJECT *o;
|
|
AQDB_COLUMN *col=NULL;
|
|
|
|
DBG_VERBOUS(AQDB_LOGDOMAIN, "Reading column entry at %llu (%16llx)",
|
|
(unsigned long long int) offset,
|
|
(unsigned long long int) offset);
|
|
/* read object from file */
|
|
o=AQDB_Object_new(AQDB_DbFile_Table_GetTableId(dbt), 1, AQDB_COLUMN_FIELD_COUNT);
|
|
rv=AQDB_DbFile_ReadObjectAt(db, o, offset, 0);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
AQDB_Object_free(o);
|
|
AQDB_Column_List_free(cl);
|
|
return rv;
|
|
}
|
|
|
|
/* create column from object */
|
|
rv=AQDB_Column_fromObject(o, &col);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
AQDB_Object_free(o);
|
|
AQDB_Column_List_free(cl);
|
|
return rv;
|
|
}
|
|
AQDB_Object_free(o);
|
|
|
|
DBG_VERBOUS(AQDB_LOGDOMAIN, "Column at %llu is [%s]",
|
|
(unsigned long long int) offset,
|
|
AQDB_Column_GetName(col));
|
|
/* add to column list */
|
|
AQDB_Column_List_Add(col, cl);
|
|
}
|
|
}
|
|
|
|
ft=AQFS_Table_List_Next(ft);
|
|
}
|
|
AQDB_DbFile_Table_SetColumnList(dbt, cl);
|
|
} /* if ftl */
|
|
}
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int AQDB_DbFile_ReallyCreateTable(AQDB_DB *db,
|
|
const char *name,
|
|
uint32_t flags,
|
|
const AQDB_COLUMN_LIST *columns) {
|
|
AQDB_DB_FILE *xdb;
|
|
AQDB_DBFILE_TABLE *dbt;
|
|
int64_t rd;
|
|
uint64_t offset;
|
|
int rv;
|
|
|
|
assert(db);
|
|
xdb=GWEN_INHERIT_GETDATA(AQDB_DB, AQDB_DB_FILE, db);
|
|
assert(xdb);
|
|
|
|
/* create table */
|
|
dbt=AQDB_DbFile_Table_new();
|
|
AQDB_DbFile_Table_SetName(dbt, name);
|
|
AQDB_DbFile_Table_SetFlags(dbt, flags);
|
|
AQDB_DbFile_Table_SetColumnList(dbt, AQDB_Column_List_dup(columns));
|
|
|
|
{
|
|
AQFS_TABLE *ft;
|
|
|
|
/* create table for columns */
|
|
DBG_INFO(AQDB_LOGDOMAIN, "Create Table [%s]: Creating table for columns", name);
|
|
ft=AQFS_Table_Create(AQDB_DBFILE_COLUMNTABLE_MAXENTRIES);
|
|
rd=AQFS_File_AppendTable(xdb->file, ft);
|
|
if (rd<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", (int) rd);
|
|
AQFS_Table_free(ft);
|
|
return (int) rd;
|
|
}
|
|
AQDB_DbFile_Table_SetOffsetColumnTable(dbt, rd);
|
|
AQFS_Table_List_Add(ft, AQDB_DbFile_Table_GetTableListColumns(dbt));
|
|
}
|
|
|
|
{
|
|
AQFS_TABLE *ft;
|
|
|
|
/* create table for objects */
|
|
DBG_INFO(AQDB_LOGDOMAIN, "Create Table [%s]: Creating table for objects", name);
|
|
ft=AQFS_Table_Create(AQDB_DBFILE_OBJECTTABLE_MAXENTRIES);
|
|
rd=AQFS_File_AppendTable(xdb->file, ft);
|
|
if (rd<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", (int) rd);
|
|
AQFS_Table_free(ft);
|
|
return (int) rd;
|
|
}
|
|
AQDB_DbFile_Table_SetOffsetObjectTable(dbt, rd);
|
|
AQFS_Table_List_Add(ft, AQDB_DbFile_Table_GetTableListObjects(dbt));
|
|
}
|
|
|
|
{
|
|
AQDB_COLUMN *col;
|
|
|
|
/* write columns */
|
|
DBG_INFO(AQDB_LOGDOMAIN, "Create Table [%s]: Writing columns", name);
|
|
col=AQDB_Column_List_First(columns);
|
|
while(col) {
|
|
AQDB_OBJECT *o;
|
|
|
|
/* create object with data from column */
|
|
DBG_INFO(AQDB_LOGDOMAIN, " Create Table [%s]: Column to object [%s]", name, AQDB_Column_GetName(col));
|
|
o=AQDB_Object_new(1, 1, AQDB_COLUMN_FIELD_COUNT);
|
|
rv=AQDB_Column_toObject(col, o);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
AQDB_Object_free(o);
|
|
return rv;
|
|
}
|
|
|
|
/* append object to file */
|
|
DBG_INFO(AQDB_LOGDOMAIN, " Create Table [%s]: Writing column [%s]", name, AQDB_Column_GetName(col));
|
|
rd=AQDB_DbFile_AppendObject(db, AQDB_DbFile_Table_GetTableListColumns(dbt), o);
|
|
if (rd<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", (int) rd);
|
|
AQDB_Object_free(o);
|
|
return (int) rd;
|
|
}
|
|
DBG_INFO(AQDB_LOGDOMAIN, "Added table object with id %llu", (unsigned long long int) rd);
|
|
|
|
/* object no longer needed */
|
|
AQDB_Object_free(o);
|
|
|
|
col=AQDB_Column_List_Next(col);
|
|
}
|
|
}
|
|
|
|
|
|
/* write table to a writable buffer */
|
|
{
|
|
uint8_t *ptr;
|
|
uint64_t len;
|
|
|
|
DBG_INFO(AQDB_LOGDOMAIN, " Create Table [%s]: Writing type table", name);
|
|
ptr=(uint8_t*) malloc(AQDB_DBFILE_TABLE_SIZE);
|
|
assert(ptr);
|
|
rd=AQDB_DbFile_Table_toBuffer(dbt, ptr, AQDB_DBFILE_TABLE_SIZE);
|
|
if (rd<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", (int) rv);
|
|
free(ptr);
|
|
return (int) rd;
|
|
}
|
|
len=rd;
|
|
|
|
/* write table data to file */
|
|
rd=AQFS_File_AppendData(xdb->file, AQFS_ITEMHEADER_TYPE_GENERIC_DATA, ptr, len);
|
|
if (rd<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rd);
|
|
free(ptr);
|
|
return rd;
|
|
}
|
|
offset=rd;
|
|
free(ptr);
|
|
}
|
|
|
|
{
|
|
/* append to list of types */
|
|
rd=AQFS_File_AddTableEntry(xdb->file, xdb->tableListTypes, offset);
|
|
if (rd<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", (int)rd);
|
|
return (int) rd;
|
|
}
|
|
AQDB_DbFile_Table_SetTableId(dbt, rd+1); /* id=index into type table */
|
|
AQDB_DbFile_Table_SetOpenFlags(dbt, flags);
|
|
}
|
|
|
|
/* done */
|
|
DBG_INFO(AQDB_LOGDOMAIN, "Created type \"%s\" with id %llu",
|
|
name, (long long unsigned) (rd+1));
|
|
AQDB_DbFile_Table_List_Add(dbt, xdb->tables);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int AQDB_DbFile_ReallyOpenTable(AQDB_DB *db,
|
|
uint32_t aflags,
|
|
const char *tname,
|
|
uint32_t flags,
|
|
AQDB_ID *pTableId) {
|
|
AQDB_DB_FILE *xdb;
|
|
AQDB_DBFILE_TABLE *dbt;
|
|
AQDB_COLUMN_LIST *cl;
|
|
int rv;
|
|
|
|
assert(db);
|
|
xdb=GWEN_INHERIT_GETDATA(AQDB_DB, AQDB_DB_FILE, db);
|
|
assert(xdb);
|
|
|
|
/* get table */
|
|
dbt=AQDB_DbFile_GetTableByName(db, tname);
|
|
if (dbt==NULL) {
|
|
DBG_ERROR(AQDB_LOGDOMAIN, "Table [%s] not found", tname);
|
|
return GWEN_ERROR_NOT_FOUND;
|
|
}
|
|
|
|
/* read table fields if not already done so */
|
|
cl=AQDB_DbFile_Table_GetColumnList(dbt);
|
|
if (AQDB_Column_List_GetCount(cl)==0) {
|
|
rv=AQDB_DbFile_ReadTableFields(db, dbt);
|
|
if (rv<0) {
|
|
DBG_INFO(AQDB_LOGDOMAIN, "here (%d)", rv);
|
|
return rv;
|
|
}
|
|
}
|
|
|
|
/* handle open flags */
|
|
AQDB_DbFile_Table_AddOpenFlags(dbt, flags);
|
|
*pTableId=AQDB_DbFile_Table_GetTableId(dbt);
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
int GWENHYWFAR_CB AQDB_DbFile_ReallyCloseTable(AQDB_DB *db,
|
|
AQDB_ID tableId,
|
|
uint32_t flags) {
|
|
AQDB_DB_FILE *xdb;
|
|
AQDB_DBFILE_TABLE *dbt;
|
|
|
|
assert(db);
|
|
xdb=GWEN_INHERIT_GETDATA(AQDB_DB, AQDB_DB_FILE, db);
|
|
assert(xdb);
|
|
|
|
dbt=AQDB_DbFile_GetTableById(db, tableId);
|
|
if (dbt==0) {
|
|
DBG_ERROR(AQDB_LOGDOMAIN, "Table with id %d not found.", tableId);
|
|
return GWEN_ERROR_INVALID;
|
|
}
|
|
|
|
DBG_INFO(AQDB_LOGDOMAIN, "Closing table [%s]", AQDB_DbFile_Table_GetName(dbt));
|
|
|
|
#if 0
|
|
AQDB_DbFile_Table_SetSavedTableListObjects(dbt, NULL);
|
|
AQDB_DbFile_Table_SetTableListObjects(dbt, NULL);
|
|
AQDB_DbFile_Table_SetTableListColumns(dbt, NULL);
|
|
AQDB_DbFile_Table_SetColumnList(dbt, NULL);
|
|
|
|
#endif
|
|
AQDB_DbFile_Table_SetOpenFlags(dbt, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
AQDB_DBFILE_TABLE *AQDB_DbFile_GetTableById(AQDB_DB *db, AQDB_ID id) {
|
|
AQDB_DB_FILE *xdb;
|
|
|
|
assert(db);
|
|
xdb=GWEN_INHERIT_GETDATA(AQDB_DB, AQDB_DB_FILE, db);
|
|
assert(xdb);
|
|
|
|
if (xdb->tables) {
|
|
AQDB_DBFILE_TABLE *dbt;
|
|
|
|
dbt=AQDB_DbFile_Table_List_First(xdb->tables);
|
|
while(dbt) {
|
|
if (AQDB_DbFile_Table_GetTableId(dbt)==id)
|
|
return dbt;
|
|
dbt=AQDB_DbFile_Table_List_Next(dbt);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
AQDB_DBFILE_TABLE *AQDB_DbFile_GetTableByName(AQDB_DB *db, const char *name) {
|
|
AQDB_DB_FILE *xdb;
|
|
|
|
assert(db);
|
|
xdb=GWEN_INHERIT_GETDATA(AQDB_DB, AQDB_DB_FILE, db);
|
|
assert(xdb);
|
|
|
|
if (xdb->tables) {
|
|
AQDB_DBFILE_TABLE *dbt;
|
|
|
|
dbt=AQDB_DbFile_Table_List_First(xdb->tables);
|
|
while(dbt) {
|
|
const char *s;
|
|
|
|
s=AQDB_DbFile_Table_GetName(dbt);
|
|
if (s && *s && strcasecmp(s, name)==0)
|
|
return dbt;
|
|
dbt=AQDB_DbFile_Table_List_Next(dbt);
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
/* end */
|
|
|
|
|
|
|
|
|
|
|
|
|