mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-09-05 17:44:55 -06:00
Sql: JoinRef (first iteration)
git-svn-id: svn://ultimatepp.org/upp/trunk@4264 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
52ba5d1aaa
commit
cebc2c14a2
6 changed files with 193 additions and 16 deletions
81
uppsrc/Sql/IntroSch.cpp
Normal file
81
uppsrc/Sql/IntroSch.cpp
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
#include "Sql.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
ArrayMap<String, SchTableInfo>& sSchTableInfo()
|
||||
{
|
||||
static ArrayMap<String, SchTableInfo> x;
|
||||
return x;
|
||||
}
|
||||
|
||||
SchTableInfo& SchTableInfo::Column(const char *name)
|
||||
{
|
||||
column.Add(name);
|
||||
ref_table.Add();
|
||||
ref_column.Add();
|
||||
return *this;
|
||||
}
|
||||
|
||||
SchTableInfo& SchTableInfo::References(const char *table)
|
||||
{
|
||||
ref_table.Top() = table;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SchTableInfo& SchTableInfo::References(const char *table, const char *column)
|
||||
{
|
||||
References(table);
|
||||
ref_column.Top() = column;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SchTableInfo& SchDbInfo(const char *table)
|
||||
{
|
||||
return sSchTableInfo().GetAdd(table);
|
||||
}
|
||||
|
||||
const SchTableInfo& GetSchTableInfo(const String& table)
|
||||
{
|
||||
static SchTableInfo sSchTableInfoZero;
|
||||
return sSchTableInfo().Get(~table, sSchTableInfoZero);
|
||||
}
|
||||
|
||||
SqlBool Join(const String& tab1, const String& tab2)
|
||||
{
|
||||
const SchTableInfo& t1 = GetSchTableInfo(tab1);
|
||||
const SchTableInfo& t2 = GetSchTableInfo(tab2);
|
||||
for(int i = 0; i < t1.ref_table.GetCount(); i++)
|
||||
if(t1.ref_table[i] == tab2)
|
||||
return SqlId(t1.column[i]).Of(SqlId(tab1)) == SqlId(t2.column[0]).Of(SqlId(tab2));
|
||||
for(int i = 0; i < t2.ref_table.GetCount(); i++)
|
||||
if(t2.ref_table[i] == tab1)
|
||||
return SqlId(t2.column[i]).Of(SqlId(tab2)) == SqlId(t1.column[0]).Of(SqlId(tab1));
|
||||
return SqlBool::False();
|
||||
}
|
||||
|
||||
SqlBool FindSchJoin(const String& tables)
|
||||
{
|
||||
INTERLOCKED {
|
||||
static VectorMap<String, SqlBool> cache;
|
||||
if(cache.GetCount() > 20000)
|
||||
cache.Clear();
|
||||
int q = cache.Find(tables);
|
||||
if(q >= 0)
|
||||
return cache[q];
|
||||
Vector<String> s = Split(tables, ',');
|
||||
if(s.GetCount() >= 2) {
|
||||
String tab1 = s.Top();
|
||||
for(int i = 0; i < s.GetCount() - 1; i++) {
|
||||
SqlBool b = Join(tab1, s[i]);
|
||||
if(!b.IsFalse()) {
|
||||
cache.Add(tables, b);
|
||||
return b;
|
||||
}
|
||||
}
|
||||
}
|
||||
NEVER();
|
||||
return SqlBool::False();
|
||||
}
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
@ -27,6 +27,7 @@ file
|
|||
sch_source.h,
|
||||
sch_schema.h,
|
||||
util_td.cpp,
|
||||
IntroSch.cpp,
|
||||
ExportSch.cpp,
|
||||
Info readonly separator,
|
||||
src.tpp,
|
||||
|
|
|
|||
|
|
@ -108,6 +108,21 @@ inline void SqlSchemaClear(T *a, int n) {
|
|||
SqlSchemaClear(*a++);
|
||||
}
|
||||
|
||||
|
||||
struct SchTableInfo {
|
||||
Vector<String> column;
|
||||
Vector<String> ref_table;
|
||||
Vector<String> ref_column;
|
||||
|
||||
SchTableInfo& Column(const char *name);
|
||||
SchTableInfo& References(const char *table);
|
||||
SchTableInfo& References(const char *table, const char *column);
|
||||
};
|
||||
|
||||
SchTableInfo& SchDbInfo(const char *table);
|
||||
|
||||
SqlBool FindSchJoin(const String& tables);
|
||||
|
||||
String ExportSch(SqlSession& session, const String& database);
|
||||
String ExportIds(SqlSession& session, const String& database);
|
||||
|
||||
|
|
|
|||
|
|
@ -66,12 +66,6 @@ SqlSelect& SqlSelect::Where(const SqlBool& exp) {
|
|||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::On(const SqlBool& exp) {
|
||||
if(!exp.IsTrue() && !exp.IsEmpty())
|
||||
text << " on " << ~exp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::StartWith(const SqlBool& exp) {
|
||||
text << " start with " << ~exp;
|
||||
return *this;
|
||||
|
|
@ -143,42 +137,103 @@ SqlSelect& SqlSelect::Get() {
|
|||
}
|
||||
|
||||
SqlSelect& SqlSelect::From(const SqlSet& table) {
|
||||
text = "select " + text + " from " + table(SqlSet::SETOP + 1);
|
||||
String ts = table(SqlSet::SETOP + 1);
|
||||
text = "select " + text + " from " + ts;
|
||||
tables << ',' << Filter(ts, CharFilterNotWhitespace);
|
||||
on = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::From(SqlId table) {
|
||||
text = "select " + text + " from " + ~table;
|
||||
String t1 = ~table;
|
||||
text = "select " + text + " from " + t1;
|
||||
tables << ',' << t1;
|
||||
on = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::From(SqlId table1, SqlId table2) {
|
||||
text = "select " + text + " from " + ~table1 + ", " + ~table2;
|
||||
String t1 = ~table1;
|
||||
String t2 = ~table2;
|
||||
text = "select " + text + " from " + t1 + ", " + t2;
|
||||
tables << ',' << t1 << ',' << t2;
|
||||
on = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::From(SqlId table1, SqlId table2, SqlId table3) {
|
||||
text = "select " + text + " from " + ~table1 + ", " + ~table2 + ", " + ~table3;
|
||||
String t1 = ~table1;
|
||||
String t2 = ~table2;
|
||||
String t3 = ~table3;
|
||||
text = "select " + text + " from " + t1 + ", " + t2 + ", " + t3;
|
||||
tables << ',' << t1 << ',' << t2 << ',' << t3;
|
||||
on = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::InnerJoin0(const String& table) {
|
||||
text << " inner join " << ~table;
|
||||
text << " inner join " << table;
|
||||
tables << ',' << table;
|
||||
on = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::LeftJoin0(const String& table) {
|
||||
text << " left outer join " << ~table;
|
||||
text << " left outer join " << table;
|
||||
tables << ',' << table;
|
||||
on = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::RightJoin0(const String& table) {
|
||||
text << " right outer join " << ~table;
|
||||
text << " right outer join " << table;
|
||||
tables << ',' << table;
|
||||
on = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::FullJoin0(const String& table) {
|
||||
text << " full outer join " << ~table;
|
||||
text << " full outer join " << table;
|
||||
tables << ',' << table;
|
||||
on = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::InnerJoinRef(SqlId table)
|
||||
{
|
||||
InnerJoin(table);
|
||||
On(FindSchJoin(tables));
|
||||
on = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::LeftJoinRef(SqlId table)
|
||||
{
|
||||
LeftJoin(table);
|
||||
On(FindSchJoin(tables));
|
||||
on = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::RightJoinRef(SqlId table)
|
||||
{
|
||||
RightJoin(table);
|
||||
On(FindSchJoin(tables));
|
||||
on = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::FullJoinRef(SqlId table)
|
||||
{
|
||||
FullJoin(table);
|
||||
On(FindSchJoin(tables));
|
||||
on = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlSelect& SqlSelect::On(const SqlBool& exp) {
|
||||
if(!exp.IsTrue() && !exp.IsEmpty())
|
||||
text << (on ? " and " : " on ") << ~exp;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
@ -196,6 +251,7 @@ SqlSelect SqlSelect::AsTable(SqlId tab) const
|
|||
|
||||
SqlSelect::SqlSelect(Fields f)
|
||||
{
|
||||
on = false;
|
||||
SqlSet set(f);
|
||||
text = ~set;
|
||||
}
|
||||
|
|
@ -204,6 +260,7 @@ SqlSelect::SqlSelect(Fields f)
|
|||
|
||||
#define E__QSqlSelectF(I) \
|
||||
SqlSelect::SqlSelect(__List##I(E__SqlVal)) { \
|
||||
on = false; \
|
||||
SqlSet set; \
|
||||
__List##I(E__SCat); \
|
||||
text = ~set; \
|
||||
|
|
|
|||
|
|
@ -484,6 +484,8 @@ public:
|
|||
|
||||
class SqlSelect {
|
||||
String text;
|
||||
String tables;
|
||||
bool on;
|
||||
|
||||
SqlSelect& InnerJoin0(const String& table);
|
||||
SqlSelect& LeftJoin0(const String& table);
|
||||
|
|
@ -515,6 +517,11 @@ public:
|
|||
SqlSelect& RightJoin(const SqlSet& set) { return RightJoin0(~set(SqlSet::SET)); }
|
||||
SqlSelect& FullJoin(const SqlSet& set) { return FullJoin0(~set(SqlSet::SET)); }
|
||||
|
||||
SqlSelect& InnerJoinRef(SqlId table);
|
||||
SqlSelect& LeftJoinRef(SqlId table);
|
||||
SqlSelect& RightJoinRef(SqlId table);
|
||||
SqlSelect& FullJoinRef(SqlId table);
|
||||
|
||||
SqlSelect& Where(const SqlBool& exp);
|
||||
SqlSelect& On(const SqlBool& exp);
|
||||
SqlSelect& StartWith(const SqlBool& exp);
|
||||
|
|
@ -541,8 +548,8 @@ public:
|
|||
SqlSelect AsTable(SqlId tab) const;
|
||||
|
||||
SqlSelect(Fields f);
|
||||
SqlSelect(const SqlSet& s) { text = ~s; }
|
||||
SqlSelect() {}
|
||||
SqlSelect(const SqlSet& s) { text = ~s; on = false; }
|
||||
SqlSelect() { on = false; }
|
||||
#define E__QSelect(I) SqlSelect(__List##I(E__SqlVal));
|
||||
__Expand(E__QSelect);
|
||||
#undef E__QSelect
|
||||
|
|
|
|||
|
|
@ -125,3 +125,19 @@ void S_##x::FieldLayoutRaw(FieldOperator& fo, const String& prefix) {\
|
|||
#define END_TYPE }
|
||||
|
||||
#include SCHEMADIALECT
|
||||
|
||||
// Introspection
|
||||
|
||||
#define TYPE(x) struct SINS_##x##_ { SINS_##x##_(); } SINS_##x##__; SINS_##x##_::SINS_##x##_() { SchDbInfo(#x)
|
||||
#define TYPE_I(x, b) struct SINS_##x##_ { SINS_##x##_(); } SINS_##x##__; SINS_##x##_::SINS_##x##_() { SchDbInfo(#x)
|
||||
#define TYPE_II(x, b1, b2) struct SINS_##x##_ { SINS_##x##_(); } SINS_##x##__; SINS_##x##_::SINS_##x##_() { SchDbInfo(#x)
|
||||
#define TYPE_III(x, b1, b2, b3) struct SINS_##x##_ { SINS_##x##_(); } SINS_##x##__; SINS_##x##_::SINS_##x##_() { SchDbInfo(#x)
|
||||
#define COLUMN(type, ctype, name, width, prec) .Column(#name)
|
||||
#define REFERENCES(table) .References(#table)
|
||||
#define REFERENCES_CASCADE(table) .References(#table)
|
||||
#define REFERENCES_(table, column) .References(#table, #column)
|
||||
#define REFERENCES_CASCADE_(table, column) .References(#table, #column)
|
||||
#define COLUMN_ARRAY(type, ctype, name, width, prec, items) .ColumnArray(#name, items);
|
||||
#define END_TABLE ; }
|
||||
|
||||
#include SCHEMADIALECT
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue