ultimatepp/uppsrc/Sql/SqlStatement.cpp
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

685 lines
14 KiB
C++

#include "Sql.h"
namespace Upp {
String SqlStatement::Get(int dialect) const {
ASSERT(dialect == ORACLE || dialect == SQLITE3 || dialect == MY_SQL || dialect == MSSQL ||
dialect == PGSQL || dialect == FIREBIRD || dialect == DB2);
return SqlCompile(dialect, text);
}
#ifndef flagNOAPPSQL
String SqlStatement::Get() const
{
return Get(SQL.GetDialect());
}
#endif
SqlSelect& SqlSelect::SetOp(const SqlSelect& s2, const char *op)
{
String q;
q << SqlCode(SQLITE3, "")("((")
<< text
<< SqlCode(SQLITE3, "")(")")
<< op
<< SqlCode(SQLITE3, "")("(")
<< s2.text
<< SqlCode(SQLITE3, "")("))")
;
text = q;
return *this;
}
SqlSelect& SqlSelect::operator|=(const SqlSelect& s2) {
return SetOp(s2, " union ");
}
SqlSelect& SqlSelect::operator+=(const SqlSelect& s2)
{
return SetOp(s2, " union all ");
}
SqlSelect& SqlSelect::operator&=(const SqlSelect& s2) {
return SetOp(s2, " intersect ");
}
SqlSelect& SqlSelect::operator-=(const SqlSelect& s2) {
return SetOp(s2, SqlCode(MSSQL|PGSQL|SQLITE3," except ")(" minus "));
}
SqlSelect operator|(const SqlSelect& s1, const SqlSelect& s2) {
SqlSelect s = s1;
s |= s2;
return s;
}
SqlSelect operator&(const SqlSelect& s1, const SqlSelect& s2) {
SqlSelect s = s1;
s &= s2;
return s;
}
SqlSelect operator-(const SqlSelect& s1, const SqlSelect& s2) {
SqlSelect s = s1;
s -= s2;
return s;
}
SqlSelect operator+(const SqlSelect& s1, const SqlSelect& s2)
{
SqlSelect s = s1;
s += s2;
return s;
}
SqlSelect& SqlSelect::Where(const SqlBool& exp) {
if(!exp.IsTrue() && !exp.IsEmpty())
text << " where " << ~exp;
return *this;
}
SqlSelect& SqlSelect::StartWith(const SqlBool& exp) {
text << " start with " << ~exp;
return *this;
}
SqlSelect& SqlSelect::ConnectBy(const SqlBool& exp) {
text << " connect by " << ~exp;
return *this;
}
SqlSelect& SqlSelect::GroupBy(const SqlSet& set) {
text << " group by " << ~set;
return *this;
}
SqlSelect& SqlSelect::Having(const SqlBool& exp) {
text << " having " << ~exp;
return *this;
}
SqlSelect& SqlSelect::OrderBy(const SqlSet& set) {
if(!set.IsEmpty())
text << " order by " << ~set;
return *this;
}
SqlSelect& SqlSelect::ForUpdate() {
text << SqlCode(SQLITE3, "")(" for update");
return *this;
}
SqlSelect& SqlSelect::NoWait() {
text << " nowait";
return *this;
}
SqlSelect& SqlSelect::Limit(int limit) {
ASSERT(text.StartsWith("select "));
String s = AsString(limit);
text.Insert(6, SqlCode(MSSQL, " top " + s)());
text << SqlCode(MSSQL, "")(" limit " + s);
return *this;
}
SqlSelect& SqlSelect::Limit(int64 offset, int limit) {
text << " limit " << offset << ", " << limit;
return *this;
}
SqlSelect& SqlSelect::Offset(int64 offset) {
text << " offset " << offset;
return *this;
}
SqlSelect& SqlSelect::operator()(const SqlVal& val)
{
if(text.GetCount())
text << ", ";
text << ~val;
return *this;
}
SqlSelect& SqlSelect::Hint(const char *hint)
{
text = "/*+ " + String(hint) + " */ " + text;
return *this;
}
SqlSelect& SqlSelect::Get() {
text = "select " + text + SqlCode(ORACLE, " from DUAL")("");
valid = true;
return *this;
}
SqlSelect& SqlSelect::From(const SqlSet& table) {
if(table.IsEmpty())
return Get();
String ts = table(SqlSet::SETOP + 1);
text = "select " + text + " from " + ts;
valid = true;
tables << ',' << Filter(ts, CharFilterNotWhitespace);
on = false;
return *this;
}
SqlSelect& SqlSelect::From(const SqlId& table) {
const String& t1 = table.ToString();
text = String().Cat() << "select " << text << " from \t" << t1 << '\t';
valid = true;
tables << ',' << t1;
on = false;
return *this;
}
SqlSelect& SqlSelect::From(const SqlId& table1, const SqlId& table2) {
const String& t1 = table1.ToString();
const String& t2 = table2.ToString();
text = String().Cat() << "select " << text << " from \t" << t1 << "\t, \t" << t2 << '\t';
valid = true;
tables << ',' << t1 << ',' << t2;
on = false;
return *this;
}
SqlSelect& SqlSelect::From(const SqlId& table1, const SqlId& table2, const SqlId& table3) {
const String& t1 = table1.ToString();
const String& t2 = table2.ToString();
const String& t3 = table3.ToString();
text = String().Cat() << "select " << text << " from \t" << t1 << "\t, \t" << t2 << "\t, \t" << t3 << '\t';
valid = true;
tables << ',' << t1 << ',' << t2 << ',' << t3;
on = false;
return *this;
}
SqlSelect& SqlSelect::InnerJoin0(const String& table) {
text << " inner join " << table;
tables << ',' << table;
on = false;
return *this;
}
SqlSelect& SqlSelect::LeftJoin0(const String& table) {
text << " left outer join " << table;
tables << ',' << table;
on = false;
return *this;
}
SqlSelect& SqlSelect::RightJoin0(const String& table) {
text << " right outer join " << table;
tables << ',' << table;
on = false;
return *this;
}
SqlSelect& SqlSelect::FullJoin0(const String& table) {
text << " full outer join " << table;
tables << ',' << table;
on = false;
return *this;
}
SqlSelect& SqlSelect::InnerJoinRef(const SqlId& table)
{
InnerJoin(table);
On(FindSchJoin(tables));
on = true;
return *this;
}
SqlSelect& SqlSelect::LeftJoinRef(const SqlId& table)
{
LeftJoin(table);
On(FindSchJoin(tables));
on = true;
return *this;
}
SqlSelect& SqlSelect::RightJoinRef(const SqlId& table)
{
RightJoin(table);
On(FindSchJoin(tables));
on = true;
return *this;
}
SqlSelect& SqlSelect::FullJoinRef(const 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;
}
SqlVal SqlSelect::AsValue() const
{
return SqlVal(String("(").Cat() << text << ")", SqlVal::LOW);
}
SqlSet SqlSelect::AsTable(const SqlId& tab) const
{
StringBuffer t;
t << SqlCode(MSSQL|PGSQL, "")("(")
<< "(" << text << ")" << SqlCode(ORACLE,"")(" as") << " \t" << tab.ToString() << '\t'
<< SqlCode(MSSQL|PGSQL, "")(")");
return SqlSet(String(t), SqlSet::HIGH);
}
SqlSelect::SqlSelect(Fields f)
{
valid = on = false;
SqlSet set(f);
text = ~set;
}
//$-
#define E__SCat(I) set.Cat(p##I)
#define E__QSqlSelectF(I) \
SqlSelect::SqlSelect(__List##I(E__SqlVal)) { \
valid = on = false; \
SqlSet set; \
__List##I(E__SCat); \
text = ~set; \
}
__Expand(E__QSqlSelectF);
#define E__QSelectF(I) \
SqlSelect Select(__List##I(E__SqlVal)) { \
SqlSet set; \
__List##I(E__SCat); \
return Select(set); \
}
__Expand(E__QSelectF);
//$+
// -------------------------------
SqlWith& SqlWith::With(SqlId table)
{
text << (text.GetCount() ? ", " : "with ") << table.Quoted();
args = false;
return *this;
}
SqlWith& SqlWith::WithRecursive(SqlId table)
{
text << (text.GetCount() ? ", " : "with ")
<< SqlCode(MSSQL, "")("recursive ")
<< table.Quoted();
args = false;
return *this;
}
SqlWith& SqlWith::Arg(SqlId arg)
{
text << (args ? ", " : "(") << arg.Quoted();
args = true;
return *this;
}
SqlWith& SqlWith::As(const SqlSelect& select)
{
if(args)
text << ')';
text << " as (" + SqlStatement(select).GetText() + ")";
args = false;
return *this;
}
SqlSelect SqlWith::operator()(const SqlSelect& select)
{
SqlSet set;
set.SetRaw(text + " " + SqlStatement(select).GetText());
return set;
}
SqlStatement SqlWith::operator()(const SqlInsert& insert)
{
return SqlStatement(text + " " + SqlStatement(insert).GetText());
}
SqlStatement SqlWith::operator()(const SqlUpdate& update)
{
return SqlStatement(text + " " + SqlStatement(update).GetText());
}
SqlStatement SqlWith::operator()(const SqlDelete& deletes)
{
return SqlStatement(text + " " + SqlStatement(deletes).GetText());
}
// -------------------------------
SqlStatement SqlCreateTable::As(const SqlSelect& select)
{
String text = "create ";
if(!permanent)
text << SqlCode(ORACLE, "global temporary ")("temporary ");
text << "table " << table.Quoted();
if(!permanent){
if(transaction)
text << SqlCode(ORACLE, " on commit delete rows")("");
else
text << SqlCode(ORACLE, " on commit preserve rows")("");
}
text << " as (" + SqlStatement(select).GetText() + ")";
return SqlStatement(text);
}
// -------------------------------
SqlDelete::SqlDelete(SqlVal table) {
text = "delete from " + ~table;
}
SqlDelete& SqlDelete::Where(const SqlBool& b) {
text << " where " << ~b;
return *this;
}
// -------------------------------
#ifdef NEWINSERTUPDATE
void SqlInsert::Column(const SqlId& column, SqlVal val) {
set1.Cat(column);
set2.Cat(val);
if(keycolumn.IsNull()) keycolumn = column;
if(keyvalue.IsEmpty()) keyvalue =val;
sel.Set(set2);
}
SqlInsert::operator SqlStatement() const {
String s = "insert into " + table.Quoted();
if(!set1.IsEmpty()) {
s << set1();
if(sel.IsValid())
s << ' ' << SqlStatement(sel).GetText();
else
if(!set2.IsEmpty())
s << " values " << set2();
}
return SqlStatement(s);
}
struct InsertFieldOperator : public FieldOperator {
SqlInsert *insert;
bool nokey;
virtual void Field(const char *name, Ref f) {
if(!nokey)
insert->Column(name, (Value)f);
nokey = false;
}
InsertFieldOperator() { nokey = false; }
};
SqlInsert::SqlInsert(Fields f, bool nokey) {
InsertFieldOperator ifo;
ifo.insert = this;
ifo.nokey = nokey;
f(ifo);
table = ifo.table;
}
SqlInsert& SqlInsert::operator()(Fields f, bool nokey)
{
InsertFieldOperator ifo;
ifo.insert = this;
ifo.nokey = nokey;
f(ifo);
return *this;
}
SqlInsert& SqlInsert::Where(const SqlBool& w)
{
if(!sel.IsValid())
From();
sel.Where(w);
return *this;
}
SqlInsert& SqlInsert::operator()(const ValueMap& data)
{
for(int i = 0; i < data.GetCount(); i++)
operator()((String)data.GetKey(i), data.GetValue(i));
return *this;
}
#else
void SqlInsert::Column(const SqlId& column, SqlVal val) {
set1.Cat(column);
set2.Cat(val);
if(keycolumn.IsNull()) keycolumn = column;
if(keyvalue.IsEmpty()) keyvalue =val;
}
SqlInsert::operator SqlStatement() const {
String s = "insert into " + table.Quoted();
if(!set1.IsEmpty()) {
s << set1();
if(from.IsEmpty() && where.IsEmpty() && groupby.IsEmpty()) {
if(!set2.IsEmpty())
s << " values " << set2();
}
else {
SqlSelect sel;
sel = Select(set2).From(from).Where(where);
if(!groupby.IsEmpty())
sel.GroupBy(groupby);
if(!having.IsEmpty())
sel.Having(having);
s << ' ' + SqlStatement(sel).GetText();
}
}
return SqlStatement(s);
}
SqlInsert& SqlInsert::From(const SqlId& from) {
return From(SqlSet(from));
}
struct InsertFieldOperator : public FieldOperator {
SqlInsert *insert;
bool nokey;
virtual void Field(const char *name, Ref f) {
if(!nokey)
insert->Column(name, (Value)f);
nokey = false;
}
InsertFieldOperator() { nokey = false; }
};
SqlInsert::SqlInsert(Fields f, bool nokey) {
InsertFieldOperator ifo;
ifo.insert = this;
ifo.nokey = nokey;
f(ifo);
table = ifo.table;
}
SqlInsert& SqlInsert::operator()(Fields f, bool nokey)
{
InsertFieldOperator ifo;
ifo.insert = this;
ifo.nokey = nokey;
f(ifo);
return *this;
}
SqlInsert& SqlInsert::operator()(const ValueMap& data)
{
for(int i = 0; i < data.GetCount(); i++)
operator()((String)data.GetKey(i), data.GetValue(i));
return *this;
}
#endif
/////////////////////////////////
#ifdef NEWINSERTUPDATE
struct UpdateFieldOperator : public FieldOperator {
SqlUpdate *update;
virtual void Field(const char *name, Ref f) {
update->Column(name, (Value)f);
}
};
SqlUpdate::SqlUpdate(Fields f) {
UpdateFieldOperator ufo;
ufo.update = this;
f(ufo);
table = ufo.table;
sel.Set(SqlSet(SqlId("X")));
}
SqlUpdate::SqlUpdate(const SqlId& table)
: table(table)
{
sel.Set(SqlSet(SqlId("X")));
}
SqlUpdate& SqlUpdate::operator()(Fields f) {
UpdateFieldOperator ufo;
ufo.update = this;
f(ufo);
return *this;
}
SqlUpdate& SqlUpdate::operator()(const ValueMap& data)
{
for(int i = 0; i < data.GetCount(); i++)
operator()((String)data.GetKey(i), data.GetValue(i));
return *this;
}
SqlUpdate& SqlUpdate::Where(SqlBool w)
{
if(sel.IsValid())
sel.Where(w);
else
where = w;
return *this;
}
SqlUpdate::operator SqlStatement() const {
StringBuffer stmt;
stmt << "update " << table.Quoted() << " set " << ~set;
if(sel.IsValid())
stmt << SqlStatement(sel).GetText().Mid(9 + 2 * SqlId::IsUseQuotes());
else
if(!where.IsEmpty())
stmt << " where " << ~where;
return SqlStatement(stmt);
}
void SqlUpdate::Column(const SqlId& column, SqlVal val) {
set.Cat(SqlVal(SqlVal(column), " = ", val, SqlS::COMP));
}
void SqlUpdate::Column(const SqlSet& cols, const SqlSet& val)
{
set.Cat(SqlVal(SqlS(cols(), SqlS::HIGH), " = ", SqlS(val(), SqlS::HIGH), SqlS::COMP));
}
#else
struct UpdateFieldOperator : public FieldOperator {
SqlUpdate *update;
virtual void Field(const char *name, Ref f) {
update->Column(name, (Value)f);
}
};
SqlUpdate::SqlUpdate(Fields f) {
UpdateFieldOperator ufo;
ufo.update = this;
f(ufo);
table = ufo.table;
}
SqlUpdate& SqlUpdate::operator()(Fields f) {
UpdateFieldOperator ufo;
ufo.update = this;
f(ufo);
return *this;
}
SqlUpdate& SqlUpdate::operator()(const ValueMap& data)
{
for(int i = 0; i < data.GetCount(); i++)
operator()((String)data.GetKey(i), data.GetValue(i));
return *this;
}
SqlUpdate::operator SqlStatement() const {
StringBuffer stmt;
stmt << "update " << table.Quoted() << " set " << ~set;
if(!where.IsEmpty())
stmt << " where " << ~where;
return SqlStatement(stmt);
}
void SqlUpdate::Column(const SqlId& column, SqlVal val) {
set.Cat(SqlVal(SqlVal(column), " = ", val, SqlS::COMP));
}
void SqlUpdate::Column(const SqlSet& cols, const SqlSet& val)
{
set.Cat(SqlVal(SqlS(cols(), SqlS::HIGH), " = ", SqlS(val(), SqlS::HIGH), SqlS::COMP));
}
#endif
// ------------------------------------
// deprecated
bool SqlStatement::Execute(Sql& cursor) const {
ASSERT(text.GetCount());
return cursor.Execute(*this);
}
void SqlStatement::Force(Sql& cursor) const {
ASSERT(text.GetCount());
if(!cursor.Execute(*this))
throw SqlExc(cursor.GetSession());
}
Value SqlStatement::Fetch(Sql& cursor) const {
ASSERT(text.GetCount());
if(!Execute(cursor))
return ErrorValue(SqlExc(cursor.GetSession()));
if(!cursor.Fetch())
return Null;
return cursor[0];
}
#ifndef NOAPPSQL
bool SqlStatement::Execute() const {
return Execute(SQL);
}
void SqlStatement::Force() const {
Force(SQL);
}
Value SqlStatement::Fetch() const {
return Fetch(SQL);
}
#endif
}