ultimatepp/uppsrc/TCore/database.h
cxl 8ebdcbb0d5 uppsrc: NAMESPACE_UPP / END_UPP_NAMESPACE removed
git-svn-id: svn://ultimatepp.org/upp/trunk@10186 f0d560ea-af0d-0410-9eb7-867de7ffcac7
2016-08-26 17:15:30 +00:00

970 lines
30 KiB
C++
Raw Blame History

namespace Upp {
#define CHECK_CACHE() // CheckCache()
#define CHECK_BLOCK(block, index) // CheckBlock(block, index)
#ifdef _DEBUG
//#define CHECK_INDEX // comment this line to turn index checking off
#endif
class DataClient
{
public:
enum { DEFAULT_CACHE_SIZE = 100000 };
DataClient();
virtual ~DataClient();
virtual void Serialize(Stream& stream);
void StreamMaster(Stream& stream, DataFile& df, dfid_t id);
void Open(DataFile& datafile, int index, dfid_t id);
int Create(DataFile& datafile, dfid_t id);
void Close();
virtual void Unlink();
bool IsOpen() const { return datafile; }
DataFile& GetDataFile() const { return *datafile; }
int GetMasterIndex() const { return master_index; }
bool IsReadOnly() const { return datafile -> IsReadOnly(); }
dfid_t GetID() const { return id; }
virtual void SetCacheSize(int size);
int GetCacheSize() const { return cache_size; }
virtual int GetUsedCacheSize() const;
virtual void ShrinkCache();
virtual void Commit() = 0;
virtual void Rollback();
static void GetIndex(int *dest, int count, Stream& src);
static void SetIndex(Stream& dest, const int *src, int count);
static void GetIndex(Vector<int>& dest, Stream& src) { GetIndex(dest.Begin(), dest.GetCount(), src); }
static void SetIndex(Stream& dest, const Vector<int>& src) { SetIndex(dest, src.Begin(), src.GetCount()); }
protected:
enum
{
LOG2_INDEX_BYTES = 2,
INDEX_BYTES = 1 << LOG2_INDEX_BYTES,
};
void FlushMaster();
virtual void DoOpen();
virtual void DoCreate();
virtual void DoClose(); // NO-OP by default
protected:
DataFile *datafile;
dfid_t id;
int master_index;
int cache_size;
int commit_index;
mutable bool master_dirty;
};
class DataColumn : public DataClient
{
public:
DataColumn();
virtual ~DataColumn();
int GetCount() const { return row_count; }
virtual void SetCount(int count) = 0;
protected:
int row_count;
};
class DataColumnFix : public DataColumn
{
public:
DataColumnFix(int item_width);
virtual ~DataColumnFix();
virtual void Unlink();
virtual void Serialize(Stream& stream);
virtual void Commit();
virtual void SetCount(int count);
virtual int GetUsedCacheSize() const;
virtual void ShrinkCache();
protected:
const byte *GetRaw(int index);
void SetRaw(int index, const void *value);
private:
virtual void DoClose();
void FlushCache();
void ClearCache();
void FetchCache(int block);
private:
enum
{
ADD_STEP = 10,
};
struct Block
{
Block() : dirty(false), index(-1) {}
int index;
bool dirty;
byte buffer[DataFile::BLOCK_BYTES];
};
int item_width;
unsigned per_block;
Vector<int> block_index;
ArrayMap<int, Block> cache;
int last_index;
int last_index1;
int last_index2;
int last_index3;
Block *last_block;
Block *last_block1;
Block *last_block2;
Block *last_block3;
};
class DataColumnVar : public DataColumn
{
public:
DataColumnVar();
virtual ~DataColumnVar();
virtual void Unlink();
virtual void Serialize(Stream& stream);
virtual void Commit();
virtual void SetCount(int count);
virtual int GetUsedCacheSize() const;
virtual void ShrinkCache();
public:
enum
{
SHORT_BYTES = 2,
MAX_BYTES = DataFile::BLOCK_BYTES,
INIT_BYTES = MAX_BYTES / 2,
JOIN_BYTES = MAX_BYTES / 4,
SINGLE_BYTES = MAX_BYTES / 4,
ADD_STEP = 100,
};
protected:
String GetRaw(int index);
void SetRaw(int index, String value);
private:
struct Block
{
Block() : raw_dirty(false), total(SHORT_BYTES), offsets(SHORT_BYTES) {}
int offsets;
int total;
bool raw_dirty;
VectorMap<int, String> dirty;
String buffer;
};
virtual void DoClose();
int FindBlock(int index) const;
void FlushCache();
void FlushCache(int index, int set_span = -1);
void ClearCache();
int FetchCache(int block);
int GetDataLength(int index) const;
bool CanJoin(int index, int length) const;
void JoinBlock(int index, char *buffer, int offset, int count);
int AddBlock(int index, char *buffer, int offset, int count);
void AdjustLastIndex(int i)
{
if(last_index < 0 || i < index_index[last_index] || i >= index_index[last_index + 1])
last_index = FindBlock(i);
}
void CheckCache() const;
void CheckBlock(const Block& b, int index) const;
private:
Vector<int> index_index;
Vector<int> block_index;
Index<int> cache_index;
Array<Block> cache;
int last_index;
int current_size; // size of all cached objects
};
class DataRowIndex : public DataClient
{
public:
DataRowIndex();
virtual void Unlink();
virtual void Serialize(Stream& stream);
virtual void Commit();
virtual int GetUsedCacheSize() const;
virtual void ShrinkCache();
int GetCount() const { return exact_count; }
int GetFirstEmpty() const { return first_empty; }
int GetEndIndex() const { return end_index; }
int Add();
Vector<int> Add(int count);
void AddAt(int index);
void Remove(int index);
void Remove(const Vector<int>& index);
Vector<int> GetIndex();
bool IsEmpty(int index);
private:
struct Block
{
Block() : dirty(false) {}
bool dirty;
Vector<int> data;
int FindIndex(int offset) const;
};
virtual void DoClose();
void FlushCache();
void ClearCache();
int FetchCache(int block);
void CalcFirstEmpty();
void CalcEndIndex();
void CalcExactCount();
void CheckBlock(const Block& block);
void UnCollapse();
private:
enum
{
LOG2_BLOCK_ITEMS = DataFile::LOG2_BLOCK_BYTES - LOG2_INDEX_BYTES - 1,
BLOCK_ITEMS = 1 << LOG2_BLOCK_ITEMS,
};
Vector<int> block_index;
ArrayMap<int, Block> cache;
int exact_count;
int end_index;
int first_empty;
int current_size;
bool collapsed;
};
class DataSource
{
public:
DataSource() {}
virtual ~DataSource() {}
virtual void SetRowIndex(DataRowIndex *index) {}
virtual Value Get(int index) = 0;
Value operator [] (int index) { return Get(index); }
virtual void Add(int index, Value value) { Set(index, value); }
virtual void Set(int index, Value value) = 0;
virtual void Remove(int index) { Set(index, Value()); }
virtual void CheckAdd(int index, Value value) { CheckSet(index, value); }
virtual void CheckSet(int index, Value value) {}
virtual void Commit() {}
virtual void Rollback() {}
virtual int GetUsedCacheSize() const { return 0; }
virtual void ShrinkCache() {}
virtual String Describe() const = 0;
};
template <class C>
C& DataFetch(C& container, DataSource& source, const Vector<int>& index)
{
typedef typename C::ValueType CVT;
for(const int *p = index.Begin(), *e = index.End(); p != e; ++p)
container.Add(CalcType<CVT>::ValueTo(source.Get(*p)));
return container;
}
template <class C>
C DataFetch(DataSource& source, const Vector<int>& index, C * = 0)
{
C container;
return DataFetch(container, source, index);
}
template <class C, class L>
C& DataFetchSorted(C& container, DataSource& source, const Vector<int>& index, const L& sort, C * = 0)
{
DataFetch(container, source, index);
Sort(container, sort);
return container;
}
template <class C, class L>
C DataFetchSorted(DataSource& source, const Vector<int>& index, const L& sort, C * = 0)
{
C container;
return DataFetchSorted(container, source, index);
}
class DataFilter : public DataSource
{
public:
DataFilter() : source(0) {}
void SetSource(DataSource *_source) { source = _source; }
DataSource *GetSource() const { return source; }
virtual void SetRowIndex(DataRowIndex *index) { source -> SetRowIndex(index); }
virtual Value Get(int index) { ASSERT(source); return source -> Get(index); }
virtual void Add(int index, Value value) { ASSERT(source); source -> Add(index, value); }
virtual void Set(int index, Value value) { ASSERT(source); source -> Set(index, value); }
virtual void Remove(int index) { ASSERT(source); source -> Remove(index); }
virtual void CheckAdd(int index, Value value) { ASSERT(source); source -> CheckAdd(index, value); }
virtual void CheckSet(int index, Value value) { ASSERT(source); source -> CheckSet(index, value); }
virtual void Commit() { ASSERT(source); source -> Commit(); }
virtual void Rollback() { ASSERT(source); source -> Rollback(); }
virtual int GetUsedCacheSize() const { ASSERT(source); return source->GetUsedCacheSize(); }
virtual void ShrinkCache() { ASSERT(source); source->ShrinkCache(); }
protected:
DataSource *source;
};
class DataConvertFilter : public DataFilter
{
public:
DataConvertFilter(const Convert& convert = NoConvert()) : convert(&convert) {}
void SetConvert(const Convert& _convert) { convert = &_convert; }
const Convert& operator <<= (const Convert& _convert) { convert = &_convert; return _convert; }
virtual Value Get(int index);
virtual void Set(int index, Value value);
virtual void CheckSet(int index, Value value);
protected:
const Convert *convert;
};
class DataMapFilter : public DataFilter
{
public:
DataMapFilter() {}
void SetMap(const Index<Value>& _map) { map <<= _map; }
const Index<Value>& operator <<= (const Index<Value>& _map) { return map <<= _map; }
void PickMap(Index<Value>& _map) { map = _map; }
void operator |= (Index<Value>& _map) { map = _map; }
virtual void CheckSet(int index, Value value);
protected:
Index<Value> map;
};
class DataMinMaxFilter : public DataFilter
{
public:
DataMinMaxFilter(double min = Null, double max = Null, bool not_null = false)
: min(min), max(max), not_null(not_null) {}
void MinMax(double _min, double _max) { min = _min; max = _max; }
double GetMin() const { return min; }
double GetMax() const { return max; }
void NotNull(bool _nn = true) { not_null = true; }
void NoNotNull() { not_null = false; }
bool IsNotNull() const { return not_null; }
virtual void CheckSet(int index, Value value);
protected:
double min, max;
bool not_null;
};
class DataOrderedIndexBase : public DataFilter, public DataClient
{
public:
DataOrderedIndexBase(bool lazy);
virtual void Serialize(Stream& stream);
virtual void Add(int index, Value value);
virtual void Set(int index, Value value);
virtual void Remove(int index);
virtual int GetUsedCacheSize() const;
virtual void ShrinkCache();
#ifdef CHECK_INDEX
virtual void CheckIndex() = 0;
#endif
virtual void SetRowIndex(DataRowIndex *ri) { dirty = true; row_index = ri; DataFilter::SetRowIndex(ri); }
virtual void Commit();
virtual void Rollback();
Vector<int> GetRange(Value min, Value max);
Vector<int> GetEqual(const Index<Value>& values);
void GetMinMax(Ref min, Ref max);
int GetFirstEqual(Value value, int exclude_row = -1);
bool IsEnabled() const { return !disabled; }
void Disable();
void Enable();
virtual String Describe() const;
protected:
virtual void DoClose();
virtual void RefreshIndex() = 0;
virtual int FindIndex(int index, Value value) = 0;
protected:
DataRowIndex *row_index;
bool disabled;
bool lazy;
bool dirty;
Vector<int> ordered_index;
};
template <class T>
class DataOrderedIndex : public DataOrderedIndexBase
{
public:
DataOrderedIndex(bool lazy) : DataOrderedIndexBase(lazy) {}
#ifdef CHECK_INDEX
virtual void CheckIndex();
#endif
private:
virtual void RefreshIndex();
virtual int FindIndex(int index, Value value);
private:
struct LessSort
{
LessSort(const Vector<T>& values) : values(values) {}
bool operator () (int i, int j) const
{
return values[i] < values[j] || values[i] == values[j] && i < j;
}
const Vector<T>& values;
};
struct LessFind
{
LessFind(DataSource *source, int rindex) : source(source), rindex(rindex) {}
bool operator () (int index, const T& value) const
{
T t = CalcType<T>::ValueTo(source -> Get(index));
return t < value || t == value && index < rindex;
}
DataSource *source;
int rindex;
};
};
template <class T>
void DataOrderedIndex<T>::RefreshIndex()
{
if(!disabled && dirty) {
CDB_TIMING("DataOrderedIndex::RefreshIndex");
int start = msecs();
ASSERT(row_index);
if(!lazy)
master_dirty = !datafile -> IsReadOnly();
Vector<int> all = row_index->GetIndex();
Vector<T> values;
ordered_index.SetCount(all.GetCount());
values.SetCount(all.GetCount());
for(int i = 0; i < ordered_index.GetCount(); i++) {
ordered_index[i] = i;
values[i] = CalcType<T>::ValueTo(source->Get(all[i]));
}
Sort(ordered_index, LessSort(values));
for(int i = 0; i < ordered_index.GetCount(); i++)
ordered_index[i] = all[ordered_index[i]];
dirty = false;
RLOG(msecs(start) << " msec / DataOrderedIndex<" << typeid(T).name() << ">::RefreshIndex(" << source->Describe() << ")");
}
}
#ifdef CHECK_INDEX
template <class T>
void DataOrderedIndex<T>::CheckIndex()
{
if(disabled)
return;
for(int i = 1; i < ordered_index.GetCount(); i++)
if(LessFind(source, ordered_index[i - 1])(ordered_index[i], CalcType<T>::ValueTo(source->Get(ordered_index[i - 1]))))
{
String s;
s << "CheckIndex error at " << i << "\n"
"[" << (i - 1) << "] = " << StdFormat(Get(ordered_index[i - 1]))
<< " (" << ordered_index[i - 1] << "), [" << i << "] = "
<< StdFormat(Get(ordered_index[i])) << " (" << ordered_index[i] << ")\n";
RLOG(s);
NEVER();
}
}
#endif
template <class T>
int DataOrderedIndex<T>::FindIndex(int index, Value value)
{
return BinFindIndex(ordered_index, CalcType<T>::ValueTo(value), LessFind(source, index));
}
template <class T, int item_size, class C = T>
class DataColumnFixSimple : public DataColumnFix, public DataSource
{
public:
typedef T ValueType;
DataColumnFixSimple() : DataColumnFix(item_size) {}
virtual void Commit() { DataColumnFix::Commit(); }
virtual void Rollback() { DataColumnFix::Rollback(); }
virtual int GetUsedCacheSize() const { return DataColumnFix::GetUsedCacheSize(); }
virtual void ShrinkCache() { DataColumnFix::ShrinkCache(); }
virtual void CheckSet(int index, Value v);
virtual String Describe() const { return GetTypeName(typeid(T).name()); }
};
template <class T, int item_size, class C>
void DataColumnFixSimple<T, item_size, C>::CheckSet(int index, Value v)
{
if(!IsNull(v) && !CalcType<C>::IsType(v))
throw ObjectExc('<' + StdFormat(v) + ">: o<>ek<65>v<EFBFBD>na hodnota typu '" + CalcType<C>::Describe() + '\'');
}
template <class T, class C = T>
class DataColumnVarSimple : public DataColumnVar, public DataSource
{
public:
typedef T ValueType;
virtual void Commit() { DataColumnVar::Commit(); }
virtual void Rollback() { DataColumnVar::Rollback(); }
virtual int GetUsedCacheSize() const { return DataColumnVar::GetUsedCacheSize(); }
virtual void ShrinkCache() { DataColumnVar::ShrinkCache(); }
virtual void CheckSet(int index, Value v);
virtual String Describe() const { return GetTypeName(typeid(T).name()); }
};
template <class T, class C>
void DataColumnVarSimple<T, C>::CheckSet(int index, Value v)
{
if(!IsNull(v) && !CalcType<C>::IsType(v))
throw ObjectExc('<' + StdFormat(v) + ">: o<>ek<65>v<EFBFBD>na hodnota typu '" + CalcType<C>::Describe() + '\'');
}
template <class T, class C = T>
class DataColumnFixOf : public DataColumnFixSimple<T, sizeof(T)>
{
public:
virtual Value Get(int index) { return (C)*(const T *)this->GetRaw(index); }
virtual void Set(int index, Value value) { T t = (C)value; this->SetRaw(index, &t); }
};
template <class T>
class DataColumnOf;
enum
{
LOG2_BOOL_BLOCK_BITS = 5,
BOOL_BLOCK_BITS = 1 << LOG2_BOOL_BLOCK_BITS,
BOOL_BLOCK_BYTES = sizeof(int)
};
template <>
class DataColumnOf<bool> : public DataColumnFixSimple<bool, BOOL_BLOCK_BYTES>
{
public:
virtual Value Get(int index);
virtual void Set(int index, Value value);
virtual void SetCount(int count);
};
template <> class DataColumnOf<byte> : public DataColumnFixOf<byte, int> {};
template <> class DataColumnOf<short> : public DataColumnFixOf<short, int> {};
template <> class DataColumnOf<int> : public DataColumnFixOf<int> {};
template <> class DataColumnOf<double> : public DataColumnFixOf<double> {};
template <>
class DataColumnOf<String> : public DataColumnVarSimple<String>
{
public:
virtual Value Get(int index) { return GetRaw(index); }
virtual void Set(int index, Value value) { SetRaw(index, value); }
};
template <> class DataColumnOf<Date> : public DataColumnFixSimple<Date, 3>
{
public:
virtual Value Get(int index);
virtual void Set(int index, Value value);
};
template <>
class DataColumnOf<Time> : public DataColumnFixSimple<Time, 5>
{
public:
virtual Value Get(int index);
virtual void Set(int index, Value value);
};
template <>
class DataColumnOf<Value> : public DataColumnVarSimple<Value>
{
public:
virtual Value Get(int index);
virtual void Set(int index, Value value);
};
class DataTable;
class DataLinkFilter;
struct DataSet : DeepCopyOption<DataSet>
{
DataSet(String table = Null) : table(table) {}
DataSet(String table, int i) : table(table) { set.SetCount(1, i); }
DataSet(const DataSet& d, int deep) : table(d.table), set(d.set, deep) {}
DataSet(String table, pick_ Vector<int>& set) : table(table), set(set) { Sort(); }
DataSet(String table, pick_ Vector<int>& set, int deep) : table(table), set(set, deep) { Sort(); }
DataSet& Sort();
DataSet Copy() const { return DataSet(*this, 0); }
DataSet& operator &= (const DataSet& s);
DataSet& operator |= (const DataSet& s);
DataSet& operator -= (const DataSet& s);
bool IsEmpty() const { return set.IsEmpty(); }
int GetCount() const { return set.GetCount(); }
int operator [] (int index) const { return set[index]; }
String table;
Vector<int> set;
};
DataSet operator && (const DataSet& a, const DataSet& b);
DataSet operator || (const DataSet& a, const DataSet& b);
DataSet operator - (const DataSet& a, const DataSet& b);
class DataTableColumn : public DataClient
{
public:
DataTableColumn();
enum // special valuetypes
{
FIRST = -100,
SHORT_V,
BYTE_V,
BOOL_V,
};
enum // flags
{
NUMBER_INDEX = 0x0001,
DATETIME_INDEX = 0x0002,
STRING_INDEX = 0x0004,
INTEGER_INDEX = 0x0008,
// HASH_INDEX = 0x0008,
// ATOM_INDEX = 0x0010,
};
DataTableColumn& SetTable(DataTable *_owner) { owner = _owner; return *this; }
DataTable *GetTable() const { return owner; }
String GetTableName() const;
void SetStyle(int vtype, int flags);
int GetType() const { return vtype; }
int GetFlags() const { return flags; }
void ModifyFlags(int flags);
void Link(DataTable& table);
void NoLink();
DataTableColumn& SetRowIndex(DataRowIndex *_rx) { row_index = _rx; return *this; }
DataRowIndex *GetRowIndex() const { return row_index; }
DataSet GetIndex() const;
DataTableColumn& SetName(String _name) { column_name = _name; return *this; }
String GetName() const { return column_name; }
String GetDotName() const;
virtual void Unlink();
virtual void Commit();
void Serialize(Stream& stream);
virtual int GetUsedCacheSize() const;
virtual void ShrinkCache();
DataSource& GetSource() { ASSERT(source); return *source; }
DataSource& operator ~() { return GetSource(); }
void Set(int index, Value value);
Value Get(int index);
Value operator [] (int index);
Vector<Value> Get(const Vector<int>& rowset);
Vector<int> GetInt(const Vector<int>& rowset);
DataSet GetRange(Value min, Value max);
DataSet GetLike(WString mask);
DataSet GetEqual(Value value);
DataSet GetEqual(const Index<Value>& set);
DataSet GetEqual(const Vector<int>& set);
int GetFirstEqual(Value value, int exlude_row = -1);
bool Exists(Value value) { return GetFirstEqual(value) >= 0; }
void GetMinMax(double& min, double& max);
void GetMinMax(Time& min, Time& max);
DataSet operator == (Value v) { return GetEqual(v); }
DataSet operator == (const Index<Value>& v) { return GetEqual(v); }
DataSet operator == (const Vector<int>& v) { return GetEqual(v); }
DataSet operator != (Value v);
DataSet operator != (const Index<Value>& v);
DataSet operator != (const Vector<int>& v);
DataSet operator >= (Value v) { return GetRange(v, Null); }
DataSet operator <= (Value v) { return GetRange(Null, v); }
void Describe(Stream& stream, int flags = 0);
public:
DataTable *owner;
String column_name;
int vtype;
int flags;
DataRowIndex *row_index;
DataSource *source;
DataOrderedIndex<int> *iindex;
DataOrderedIndex<double> *nindex;
DataOrderedIndex<Time> *tindex;
DataOrderedIndex<String> *sindex;
// DataHashIndex *hindex;
// DataAtomIndex *aindex;
Array<DataFilter> filters;
Array<DataFilter> indexes;
One<DataLinkFilter> link;
One<DataClient> client;
DataSource *client_source;
protected:
void RefreshSource();
virtual void DoClose();
private:
template <class T>
void IndexHelper(bool create, T *& index)
{
if(create) {
if(!index) {
filters.Add(index = new T(true));
index->Create(*datafile, id);
index->SetSource(&GetSource());
index->SetRowIndex(row_index);
}
}
else {
if(index) {
index->Unlink();
int i = indexes.GetIndex(*index);
if(i >= 0)
indexes.Remove(i);
index = 0;
}
}
master_dirty = true;
}
};
inline dword ValueTypeNo(const byte&) { return DataTableColumn::BYTE_V; }
inline dword ValueTypeNo(const short&) { return DataTableColumn::SHORT_V; }
//inline dword ValueTypeNo(const bool&) { return DataTableColumn::BOOL_V; }
class DataTable : public DataClient
{
public:
DataTable();
virtual ~DataTable();
void Serialize(Stream& stream);
virtual void Unlink();
virtual void Commit();
virtual void Rollback();
virtual int GetUsedCacheSize() const;
virtual void ShrinkCache();
int Add(int index = -1);
int Add(const Vector<Value>& row, int index = -1);
void Set(int index, const Vector<Value>& row);
void Remove(int index);
void Remove(const DataSet& index);
Vector<Value> Get(int index);
Vector<Value> operator [] (int index) { return Get(index); }
Vector<Value> GetAlways(int index); // returns empty row when index is invalid
String GetUserInfo() const { return user_info; }
void SetUserInfo(String u) { user_info = u; master_dirty = true; }
Vector<Value> EmptyRow() const;
bool IsEmpty(int index) { return row_index.IsEmpty(index); }
DataRowIndex& GetRowIndex() { return row_index; }
DataSet GetIndex() { return DataSet(table_name, row_index.GetIndex()); }
DataSet operator ~ () { return DataSet(table_name, row_index.GetIndex()); }
int GetCount() const { return row_index.GetCount(); }
bool IsEmpty() const { return row_index.GetCount() == 0; }
DataTableColumn& Column(int index) { return columns[index]; }
DataTableColumn& Column(String name);
DataTableColumn& operator () (int index) { return Column(index); }
DataTableColumn& operator () (String name) { return Column(name); }
Value operator () (int index, int row) { return Column(index)[row]; }
Value operator () (String name, int row) { return Column(name)[row]; }
int GetColumns() const { return columns.GetCount(); }
String GetName(int i) const { return columns.GetKey(i); }
int FindColumn(String name) const { return columns.Find(name); }
int operator / (String name) const { return columns.Find(name); }
int AddColumn(String name, int vtype, int flags = 0);
void RemoveColumn(String name);
void AddLink(DataLinkFilter& link);
void RemoveLink(DataLinkFilter& link);
void SetName(String _name) { table_name = _name; }
String GetName() const { return table_name; }
enum
{
DUMP_ROWS = 0x00000001,
EXPORT_FORMAT = 0x00000002,
};
void Describe(Stream& stream, int flags = 0);
void Export(Stream& stream);
String Import(Stream& stream, bool import_id);
protected:
String table_name;
DataRowIndex row_index;
ArrayMap<String, DataTableColumn> columns;
Vector<DataLinkFilter *> links;
String user_info;
private:
virtual void DoClose();
};
class DataLinkFilter : public DataFilter
{
public:
DataLinkFilter(DataTableColumn& column, DataTable& table);
virtual ~DataLinkFilter();
void Kill() { table = 0; column = 0; }
bool Exists(int index) { ASSERT(column); return column -> Exists(index); }
String GetColumnName() const { ASSERT(column); return column -> GetDotName(); }
virtual void CheckSet(int index, Value value);
virtual String Describe() const;
protected:
DataTable *table;
DataTableColumn *column;
};
class DataBase : public DataClient
{
public:
DataBase();
virtual void Commit();
virtual void Rollback();
virtual int GetUsedCacheSize() const;
virtual void ShrinkCache();
void Serialize(Stream& stream);
int GetCount() const { return tables.GetCount(); }
String GetName(int i) const { return tables.GetKey(i); }
int Find(String name) const { return tables.Find(name); }
DataTable& Get(int i) { return tables[i]; }
DataTable& Get(String name);
DataTable& operator [] (int i) { return tables[i]; }
DataTable& operator [] (String name) { return Get(name); }
bool Exists(String tbl) const { return Find(tbl) >= 0; }
DataTable& GetAdd(String name);
DataTable& Add(String name);
void Remove(int i);
void Remove(String name);
bool TryRemove(String name);
void Describe(Stream& stream, int flags = 0);
void BeginBlock() { block_level++; }
void EndBlock() { ASSERT(block_level > 0); block_level--; }
bool InBlock() const { return block_level > 0; }
static void AllocTest();
static void ColumnTest();
static void StructuredTest();
static void FullTest();
protected:
virtual void DoClose();
protected:
ArrayMap<String, DataTable> tables;
int block_level;
};
}