My favorites | Sign in
Project Home Downloads Source
Checkout   Browse   Changes    
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#include "Sql.h"

NAMESPACE_UPP

struct SchTableInfo {
Vector<String> column;
Vector<String> ref_table;
Vector<String> ref_column;
String primary_key;
String prefix;
};

ArrayMap<String, SchTableInfo>& sSchTableInfo()
{
static ArrayMap<String, SchTableInfo> x;
return x;
}

void SchDbInfoTable(const char *table)
{
sSchTableInfo().GetAdd(table);
}

void SchDbInfoColumn(const char *name)
{
SchTableInfo& f = sSchTableInfo().Top();
f.column.Add(ToUpper(f.prefix + name));
f.ref_table.Add();
f.ref_column.Add();
if(IsNull(f.primary_key))
f.primary_key = name;
}

void SchDbInfoVar(void (*fn)(), const char *name)
{
SchTableInfo& f = sSchTableInfo().Top();
String h = f.prefix;
f.prefix << name << '$';
(*fn)();
f.prefix = h;
}

void SchDbInfoReferences(const char *table)
{
sSchTableInfo().Top().ref_table.Top() = table;
}

void SchDbInfoReferences(const char *table, const char *column)
{
SchDbInfoReferences(table);
sSchTableInfo().Top().ref_column.Top() = column;
}

void SchDbInfoPrimaryKey()
{
SchTableInfo& f = sSchTableInfo().Top();
f.primary_key = f.column.Top();
}

void SchDbInfoColumnArray(const char *name, int items)
{
for(int i = 0; i < items; i++)
SchDbInfoColumn(String().Cat() << name << i);
}

const SchTableInfo& GetSchTableInfo(const String& table)
{
static SchTableInfo sSchTableInfoZero;
return sSchTableInfo().Get(~table, sSchTableInfoZero);
}

bool MatchRefName(const String& fk, const String& pk, const String& tab, int phase)
{
return phase || fk == pk || tab + '_' + pk == fk;
}

SqlBool Join(const String& tab1, const String& as1, const String& tab2, const String& as2, int phase)
{
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 && MatchRefName(t1.column[i], t2.primary_key, tab2, phase))
return SqlId(t1.column[i]).Of(SqlId(as1)) == SqlId(t2.primary_key).Of(SqlId(as2));
for(int i = 0; i < t2.ref_table.GetCount(); i++)
if(t2.ref_table[i] == tab1 && MatchRefName(t2.column[i], t1.primary_key, tab1, phase))
return SqlId(t2.column[i]).Of(SqlId(as2)) == SqlId(t1.primary_key).Of(SqlId(as1));
return SqlBool::False();
}

int sChrf(int c)
{
return c < 32 ? ' ' : c;
}

StaticMutex sM;

Vector<String> GetSchColumns(const String& table)
{
Mutex::Lock __(sM);
return Vector<String>(GetSchTableInfo(table).column, 0);
}

SqlBool FindSchJoin(const String& tables)
{
Mutex::Lock __(sM);
static VectorMap<String, SqlBool> cache;
if(cache.GetCount() > 20000) // Defend against unlikely dynamic Join permutations
cache.Clear();
int q = cache.Find(tables);
if(q >= 0)
return cache[q];
Vector<String> s = Split(Filter(tables, sChrf), ',');
Vector<String> as;
Vector<String> table;
for(int i = 0; i < s.GetCount(); i++) {
Vector<String> ss = Split(s[i], ' ');
if(ss.GetCount()) {
table.Add(ss[0]);
as.Add(ss.Top());
}
}
if(table.GetCount() >= 2) {
String tab1 = table.Top();
String as1 = as.Top();
for(int phase = 0; phase < 2; phase++)
for(int i = 0; i < table.GetCount() - 1; i++) {
SqlBool b = Join(tab1, as1, table[i], as[i], phase);
if(!b.IsFalse()) {
cache.Add(tables, b);
return b;
}
}
}
NEVER_("Schema join not found");
return SqlBool::False();
}

END_UPP_NAMESPACE

Change log

r4571 by cxl on Feb 10, 2012   Diff
Sql: Added heuristics of *JoinRef (RM
#251)
Go to: 
Project members, sign in to write a code review

Older revisions

r4428 by cxl on Jan 16, 2012   Diff
*Sql: fixed ugly typo error in
*JoinRef
r4345 by cxl on Dec 26, 2011   Diff
Sql: GetSchColumn now guaranteed to be
uppercase
r4312 by cxl on Dec 16, 2011   Diff
SqlCtrl: SqlCtrls now support
automatic creation based on schema
introspection
All revisions of this file

File info

Size: 3479 bytes, 138 lines
Powered by Google Project Hosting