Sql: JoinRef (first iteration)

git-svn-id: svn://ultimatepp.org/upp/trunk@4264 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2011-12-07 07:38:09 +00:00
parent 52ba5d1aaa
commit cebc2c14a2
6 changed files with 193 additions and 16 deletions

81
uppsrc/Sql/IntroSch.cpp Normal file
View 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

View file

@ -27,6 +27,7 @@ file
sch_source.h,
sch_schema.h,
util_td.cpp,
IntroSch.cpp,
ExportSch.cpp,
Info readonly separator,
src.tpp,

View file

@ -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);

View file

@ -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; \

View file

@ -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

View file

@ -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