mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
Sql: SqlMassInsert (using 'union all' trick)
git-svn-id: svn://ultimatepp.org/upp/trunk@2597 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
9216fdd6b3
commit
a50feb3f05
4 changed files with 119 additions and 0 deletions
87
uppsrc/Sql/MassInsert.cpp
Normal file
87
uppsrc/Sql/MassInsert.cpp
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
#include "Sql.h"
|
||||
|
||||
namespace Upp {
|
||||
|
||||
SqlMassInsert::~SqlMassInsert()
|
||||
{
|
||||
Flush();
|
||||
}
|
||||
|
||||
SqlMassInsert& SqlMassInsert::operator()(SqlId col, const Value& val)
|
||||
{
|
||||
if(pos == 0) {
|
||||
cache.Add().nulls = 0;
|
||||
cache.Top();
|
||||
}
|
||||
if(cache.GetCount() == 1)
|
||||
column.Add(~col);
|
||||
else
|
||||
ASSERT(column[pos] == ~col);
|
||||
Row& r = cache.Top();
|
||||
r.value.Add(val);
|
||||
if(IsNull(val))
|
||||
r.nulls |= (1 << pos);
|
||||
pos++;
|
||||
ASSERT(pos < 30);
|
||||
return *this;
|
||||
}
|
||||
|
||||
SqlMassInsert& SqlMassInsert::EndRow()
|
||||
{
|
||||
if(cache.GetCount() && cache[0].value.GetCount() * cache.GetCount() > 5000)
|
||||
Flush();
|
||||
ASSERT(column.GetCount() == pos);
|
||||
pos = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SqlMassInsert::Flush()
|
||||
{
|
||||
const dword DONE = 0xffffffff;
|
||||
if(cache.GetCount() == 0)
|
||||
return;
|
||||
for(int ii = 0; ii < cache.GetCount(); ii++) {
|
||||
dword nulls = cache[ii].nulls;
|
||||
if(nulls != DONE) {
|
||||
String insert;
|
||||
insert << "insert into " + table + '(';
|
||||
bool nextcol = false;
|
||||
for(int i = 0; i < column.GetCount(); i++) {
|
||||
if(!(nulls & (1 << i))) {
|
||||
if(nextcol)
|
||||
insert << ", ";
|
||||
nextcol = true;
|
||||
insert << column[i];
|
||||
}
|
||||
}
|
||||
insert << ')';
|
||||
bool nextsel = false;
|
||||
for(int i = ii; i < cache.GetCount(); i++) {
|
||||
Row& r = cache[i];
|
||||
if(r.nulls == nulls) {
|
||||
r.nulls = DONE;
|
||||
if(nextsel)
|
||||
insert << " union all";
|
||||
nextsel = true;
|
||||
insert << " select ";
|
||||
bool nextval = false;
|
||||
for(int i = 0; i < r.value.GetCount(); i++)
|
||||
if(!(nulls & (1 << i))) {
|
||||
if(nextval)
|
||||
insert << ", ";
|
||||
nextval = true;
|
||||
insert << SqlCompile(sql.GetDialect(), SqlFormat(r.value[i]));
|
||||
}
|
||||
if(sql.GetDialect() == ORACLE)
|
||||
insert << " from dual";
|
||||
}
|
||||
}
|
||||
sql.Execute(insert);
|
||||
}
|
||||
}
|
||||
cache.Clear();
|
||||
column.Clear();
|
||||
pos = 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
@ -18,6 +18,7 @@ file
|
|||
SqlStatement.cpp,
|
||||
Sqls.h,
|
||||
Sql.cpp,
|
||||
MassInsert.cpp,
|
||||
Schema readonly separator,
|
||||
SqlSchema.h,
|
||||
SqlSchema.cpp,
|
||||
|
|
|
|||
|
|
@ -94,6 +94,8 @@ void SqlCompile(const char *&s, StringBuffer *r, byte dialect)
|
|||
case ORACLE:
|
||||
*r << Format("to_date('%d/%d/%d', 'SYYYY/MM/DD')", x.year, x.month, x.day);
|
||||
break;
|
||||
case PGSQL:
|
||||
*r << "date ";
|
||||
default:
|
||||
*r << Format("\'%04d-%02d-%02d\'", x.year, x.month, x.day);
|
||||
}
|
||||
|
|
@ -119,6 +121,8 @@ void SqlCompile(const char *&s, StringBuffer *r, byte dialect)
|
|||
*r << Format("to_date('%d/%d/%d/%d', 'SYYYY/MM/DD/SSSSS')",
|
||||
x.year, x.month, x.day, x.second + 60 * (x.minute + 60 * x.hour));
|
||||
break;
|
||||
case PGSQL:
|
||||
*r << "timestamp ";
|
||||
default:
|
||||
*r << Format("\'%04d-%02d-%02d %02d:%02d:%02d\'",
|
||||
x.year, x.month, x.day, x.hour, x.minute, x.second);
|
||||
|
|
|
|||
|
|
@ -389,3 +389,30 @@ StatementExecutor& SQLStatementExecutor();
|
|||
typedef Sql QSql;
|
||||
typedef SqlSession QSession;
|
||||
#endif
|
||||
|
||||
class SqlMassInsert {
|
||||
struct Row : Moveable<Row> {
|
||||
dword nulls;
|
||||
Vector <Value> value;
|
||||
};
|
||||
|
||||
Sql& sql;
|
||||
String table;
|
||||
Vector<String> column;
|
||||
Vector<Row> cache;
|
||||
int pos;
|
||||
|
||||
void NewRow();
|
||||
|
||||
|
||||
public:
|
||||
SqlMassInsert& operator()(SqlId col, const Value& val);
|
||||
SqlMassInsert& EndRow();
|
||||
void Flush();
|
||||
|
||||
SqlMassInsert(Sql& sql, SqlId table) : sql(sql), table(~table) { pos = 0; }
|
||||
#ifndef NOAPPSQL
|
||||
SqlMassInsert(SqlId table) : sql(SQL), table(~table) { pos = 0; }
|
||||
#endif
|
||||
~SqlMassInsert();
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue