mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-09-10 03:54:54 -06:00
Developing ODBC connector
git-svn-id: svn://ultimatepp.org/upp/trunk@907 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
ab65cba3d8
commit
f57fad159d
7 changed files with 430 additions and 2 deletions
337
uppsrc/ODBC/ODBC.cpp
Normal file
337
uppsrc/ODBC/ODBC.cpp
Normal file
|
|
@ -0,0 +1,337 @@
|
|||
#include "ODBC.h"
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
bool ODBCSession::Connect(const char *cs)
|
||||
{
|
||||
if(henv && IsOk(SQLAllocHandle(SQL_HANDLE_DBC, henv, &hdbc))) {
|
||||
if(IsOk(SQLDriverConnect(hdbc, NULL, (SQLCHAR *)cs, SQL_NTS, NULL, 0, NULL, SQL_DRIVER_NOPROMPT)))
|
||||
return true;
|
||||
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
|
||||
hdbc = SQL_NULL_HANDLE;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ODBCSession::IsOpen() const
|
||||
{
|
||||
return hdbc != SQL_NULL_HANDLE;
|
||||
}
|
||||
|
||||
void ODBCSession::Close()
|
||||
{
|
||||
if(hdbc != SQL_NULL_HANDLE) {
|
||||
SQLFreeHandle(SQL_HANDLE_DBC, hdbc);
|
||||
hdbc = SQL_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
ODBCSession::ODBCSession()
|
||||
{
|
||||
hdbc = SQL_NULL_HANDLE;
|
||||
SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE, &henv);
|
||||
if(henv)
|
||||
SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (void *) SQL_OV_ODBC3, 0);
|
||||
}
|
||||
|
||||
ODBCSession::~ODBCSession()
|
||||
{
|
||||
if(henv)
|
||||
SQLFreeHandle(SQL_HANDLE_ENV, henv);
|
||||
}
|
||||
|
||||
void ODBCSession::Begin()
|
||||
{
|
||||
}
|
||||
|
||||
void ODBCSession::Commit()
|
||||
{
|
||||
}
|
||||
|
||||
void ODBCSession::Rollback()
|
||||
{
|
||||
}
|
||||
|
||||
String ODBCSession::Savepoint()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
void ODBCSession::RollbackTo(const String& savepoint)
|
||||
{
|
||||
}
|
||||
|
||||
Vector<String> ODBCSession::EnumUsers()
|
||||
{
|
||||
return Vector<String>();
|
||||
}
|
||||
|
||||
Vector<String> ODBCSession::EnumDatabases()
|
||||
{
|
||||
return Vector<String>();
|
||||
}
|
||||
|
||||
Vector<String> ODBCSession::EnumTables(String database)
|
||||
{
|
||||
return Vector<String>();
|
||||
}
|
||||
|
||||
Vector<String> ODBCSession::EnumViews(String database)
|
||||
{
|
||||
return Vector<String>();
|
||||
}
|
||||
|
||||
Vector<String> ODBCSession::EnumSequences(String database)
|
||||
{
|
||||
return Vector<String>();
|
||||
}
|
||||
|
||||
Vector<String> ODBCSession::EnumPrimaryKeys(String database, String table)
|
||||
{
|
||||
return Vector<String>();
|
||||
}
|
||||
|
||||
String ODBCSession::EnumRowID(String database, String table)
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
bool ODBCPerformScript(const String& text, StatementExecutor& executor, Gate2<int, int> progress_canceled)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
class ODBCConnection : public Link<ODBCConnection>, public SqlConnection
|
||||
{
|
||||
public:
|
||||
ODBCConnection(ODBCSession *session);
|
||||
virtual ~ODBCConnection();
|
||||
|
||||
void Clear();
|
||||
|
||||
virtual void SetParam(int i, const Value& r);
|
||||
virtual bool Execute();
|
||||
virtual int GetRowsProcessed() const;
|
||||
virtual bool Fetch();
|
||||
virtual void GetColumn(int i, Ref r) const;
|
||||
virtual void Cancel();
|
||||
virtual SqlSession& GetSession() const { ASSERT(session); return *session; }
|
||||
virtual String GetUser() const { ASSERT(session); return session->user; }
|
||||
virtual String ToString() const;
|
||||
virtual Value GetInsertedId() const;
|
||||
|
||||
private:
|
||||
ODBCSession *session;
|
||||
HSTMT hstmt;
|
||||
struct Param {
|
||||
int ctype;
|
||||
int sqltype;
|
||||
String data;
|
||||
SQLLEN li;
|
||||
};
|
||||
Array<Param> param, bparam;
|
||||
|
||||
bool IsOk(SQLRETURN ret);
|
||||
};
|
||||
|
||||
SqlConnection *ODBCSession::CreateConnection()
|
||||
{
|
||||
return new ODBCConnection(this);
|
||||
}
|
||||
|
||||
ODBCConnection::ODBCConnection(ODBCSession *session_)
|
||||
: session(session_)
|
||||
{
|
||||
if(session)
|
||||
LinkAfter(&session->clink);
|
||||
hstmt = SQL_NULL_HANDLE;
|
||||
SQLAllocHandle(SQL_HANDLE_STMT, session->hdbc, &hstmt);
|
||||
}
|
||||
|
||||
ODBCConnection::~ODBCConnection()
|
||||
{
|
||||
if(hstmt != SQL_NULL_HANDLE)
|
||||
SQLFreeHandle(SQL_HANDLE_STMT, hstmt);
|
||||
if(session)
|
||||
Unlink();
|
||||
}
|
||||
|
||||
bool ODBCConnection::IsOk(SQLRETURN ret)
|
||||
{
|
||||
if(session->IsOk(ret))
|
||||
return true;
|
||||
param.Clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
void ODBCConnection::SetParam(int i, const Value& r)
|
||||
{
|
||||
Param& p = param.At(i);
|
||||
if(IsNumber(r)) {
|
||||
double x = r;
|
||||
p.ctype = SQL_C_DOUBLE;
|
||||
p.sqltype = SQL_DOUBLE;
|
||||
p.data = String((char *)&x, sizeof(x));
|
||||
p.li = sizeof(x);
|
||||
}
|
||||
if(IsString(r)) {
|
||||
p.ctype = SQL_C_CHAR;
|
||||
p.sqltype = SQL_LONGVARCHAR;
|
||||
p.data = r;
|
||||
p.li = p.data.GetLength();
|
||||
}
|
||||
if(IsDateTime(r)) {
|
||||
p.ctype = SQL_C_TYPE_TIMESTAMP;
|
||||
p.sqltype = SQL_TYPE_TIMESTAMP;
|
||||
Time t = r;
|
||||
SQL_TIMESTAMP_STRUCT tm;
|
||||
tm.year = t.year;
|
||||
tm.month = t.month;
|
||||
tm.day = t.day;
|
||||
tm.hour = t.hour;
|
||||
tm.minute = t.minute;
|
||||
tm.second = t.second;
|
||||
tm.fraction = 0;
|
||||
p.data = String((char *)&tm, sizeof(tm));
|
||||
p.li = sizeof(tm);
|
||||
}
|
||||
if(IsNull(r))
|
||||
p.li = SQL_NULL_DATA;
|
||||
}
|
||||
|
||||
bool ODBCConnection::Execute()
|
||||
{
|
||||
if(hstmt == SQL_NULL_HANDLE)
|
||||
return false;
|
||||
if(parse) {
|
||||
if(!IsOk(SQLPrepare(hstmt, (SQLCHAR *)~statement, statement.GetCount())))
|
||||
return false;
|
||||
parse = false;
|
||||
}
|
||||
bparam = param;
|
||||
param.Clear();
|
||||
for(int i = 0; i < bparam.GetCount(); i++) {
|
||||
Param& p = bparam[i];
|
||||
if(!IsOk(SQLBindParameter(hstmt, i + 1, SQL_PARAM_INPUT, p.ctype, p.sqltype,
|
||||
p.data.GetCount(), 0, (SQLPOINTER)~p.data, p.data.GetLength(),
|
||||
&p.li)))
|
||||
return false;
|
||||
}
|
||||
SQLSMALLINT ncol;
|
||||
if(!IsOk(SQLExecute(hstmt) || !IsOk(SQLNumResultCols(hstmt, &ncol))))
|
||||
return false;
|
||||
for(int i = 1; i <= ncol; i++) {
|
||||
SQLCHAR ColumnName[256];
|
||||
SQLSMALLINT NameLength;
|
||||
SQLSMALLINT DataType;
|
||||
SQLULEN ColumnSize;
|
||||
SQLSMALLINT DecimalDigits;
|
||||
SQLSMALLINT Nullable;
|
||||
if(!IsOk(SQLDescribeCol(hstmt, i, ColumnName, 255, &NameLength, &DataType, &ColumnSize,
|
||||
&DecimalDigits, &Nullable)))
|
||||
return false;
|
||||
SqlColumnInfo& f = info.Add();
|
||||
f.nullable = Nullable != SQL_NO_NULLS;
|
||||
f.precision = DecimalDigits;
|
||||
f.scale = 0; // ?!
|
||||
f.width = ColumnSize;
|
||||
f.name = (char *)ColumnName;
|
||||
switch(DataType) {
|
||||
case SQL_DECIMAL:
|
||||
case SQL_NUMERIC:
|
||||
case SQL_SMALLINT:
|
||||
case SQL_INTEGER:
|
||||
case SQL_REAL:
|
||||
case SQL_FLOAT:
|
||||
case SQL_DOUBLE:
|
||||
case SQL_BIT:
|
||||
case SQL_TINYINT:
|
||||
case SQL_BIGINT:
|
||||
f.type = DOUBLE_V;
|
||||
break;
|
||||
case SQL_TYPE_DATE:
|
||||
case SQL_TYPE_TIMESTAMP:
|
||||
f.type = TIME_V;
|
||||
break;
|
||||
default:
|
||||
f.type = STRING_V;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int ODBCConnection::GetRowsProcessed() const
|
||||
{
|
||||
SQLLEN rc;
|
||||
SQLRowCount(hstmt, &rc);
|
||||
return (int)rc;
|
||||
}
|
||||
|
||||
bool ODBCConnection::Fetch()
|
||||
{
|
||||
if(!hstmt)
|
||||
return false;
|
||||
int ret = SQLFetch(hstmt);
|
||||
return ret != SQL_NO_DATA && IsOk(ret);
|
||||
}
|
||||
|
||||
void ODBCConnection::GetColumn(int i, Ref r) const
|
||||
{
|
||||
SQLLEN li;
|
||||
double dbl;
|
||||
SQL_TIMESTAMP_STRUCT tm;
|
||||
Value v = Null;
|
||||
switch(info[i].type) {
|
||||
case DOUBLE_V:
|
||||
SQLGetData(hstmt, i + 1, SQL_C_DOUBLE, &dbl, sizeof(dbl), &li);
|
||||
if(li != SQL_NULL_DATA)
|
||||
v = dbl;
|
||||
break;
|
||||
case TIME_V:
|
||||
SQLGetData(hstmt, i + 1, SQL_C_TYPE_TIMESTAMP, &tm, sizeof(tm), &li);
|
||||
if(li != SQL_NULL_DATA) {
|
||||
Time m;
|
||||
m.year = tm.year;
|
||||
m.month = (byte)tm.month;
|
||||
m.day = (byte)tm.day;
|
||||
m.hour = (byte)tm.hour;
|
||||
m.minute = (byte)tm.minute;
|
||||
m.second = (byte)tm.second;
|
||||
v = m;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
StringBuffer sb;
|
||||
sb.SetLength(256);
|
||||
SQLGetData(hstmt, i + 1, SQL_C_CHAR, ~sb, 255, &li);
|
||||
if(li > 255) {
|
||||
sb.SetLength(li);
|
||||
SQLGetData(hstmt, i + 1, SQL_C_CHAR, ~sb, li, &li);
|
||||
}
|
||||
if(li != SQL_NULL_DATA) {
|
||||
sb.SetLength(li);
|
||||
v = String(sb);
|
||||
}
|
||||
break;
|
||||
}
|
||||
r.SetValue(v);
|
||||
}
|
||||
|
||||
void ODBCConnection::Cancel()
|
||||
{
|
||||
param.Clear();
|
||||
bparam.Clear();
|
||||
}
|
||||
|
||||
String ODBCConnection::ToString() const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
Value ODBCConnection::GetInsertedId() const
|
||||
{
|
||||
return Null;
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
55
uppsrc/ODBC/ODBC.h
Normal file
55
uppsrc/ODBC/ODBC.h
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
#ifndef _ODBC_ODBC_h
|
||||
#define _ODBC_ODBC_h
|
||||
|
||||
#include <Sql/Sql.h>
|
||||
#include <sql.h>
|
||||
#include <sqlext.h>
|
||||
|
||||
NAMESPACE_UPP
|
||||
|
||||
bool ODBCPerformScript(const String& text, StatementExecutor& executor, Gate2<int, int> progress_canceled = false);
|
||||
|
||||
class ODBCSession : public SqlSession {
|
||||
public:
|
||||
virtual void Begin();
|
||||
virtual void Commit();
|
||||
virtual void Rollback();
|
||||
|
||||
virtual String Savepoint();
|
||||
virtual void RollbackTo(const String& savepoint);
|
||||
|
||||
virtual bool IsOpen() const;
|
||||
|
||||
virtual Vector<String> EnumUsers();
|
||||
virtual Vector<String> EnumDatabases();
|
||||
virtual Vector<String> EnumTables(String database);
|
||||
virtual Vector<String> EnumViews(String database);
|
||||
virtual Vector<String> EnumSequences(String database);
|
||||
virtual Vector<String> EnumPrimaryKeys(String database, String table);
|
||||
virtual String EnumRowID(String database, String table);
|
||||
|
||||
virtual RunScript GetRunScript() const { return &ODBCPerformScript; }
|
||||
|
||||
protected:
|
||||
virtual SqlConnection *CreateConnection();
|
||||
|
||||
private:
|
||||
friend class ODBCConnection;
|
||||
HENV henv;
|
||||
HDBC hdbc;
|
||||
Link<ODBCConnection> clink;
|
||||
String user;
|
||||
|
||||
bool IsOk(SQLRETURN ret) { return SQL_SUCCEEDED(ret); }
|
||||
|
||||
public:
|
||||
bool Connect(const char *cs);
|
||||
void Close();
|
||||
|
||||
ODBCSession();
|
||||
~ODBCSession();
|
||||
};
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
||||
#endif
|
||||
9
uppsrc/ODBC/ODBC.upp
Normal file
9
uppsrc/ODBC/ODBC.upp
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
uses
|
||||
Sql;
|
||||
|
||||
library(WIN32) odbc32;
|
||||
|
||||
file
|
||||
ODBC.h,
|
||||
ODBC.cpp;
|
||||
|
||||
4
uppsrc/ODBC/init
Normal file
4
uppsrc/ODBC/init
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
#ifndef _ODBC_icpp_init_stub
|
||||
#define _ODBC_icpp_init_stub
|
||||
#include "Sql/init"
|
||||
#endif
|
||||
21
uppsrc/Painter/Copying
Normal file
21
uppsrc/Painter/Copying
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
Copyright 1998-2009 The U++ Project. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted
|
||||
provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of
|
||||
conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice, this list of
|
||||
conditions and the following disclaimer in the documentation and/or other materials
|
||||
provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE U++ PROJECT ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
|
@ -35,7 +35,9 @@ file
|
|||
Mask.cpp optimize_speed,
|
||||
Gradient.cpp optimize_speed,
|
||||
RadialGradient.cpp optimize_speed,
|
||||
srcimp.tpp;
|
||||
srcimp.tpp,
|
||||
Info readonly separator,
|
||||
Copying;
|
||||
|
||||
mainconfig
|
||||
"" = "GUI";
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#define _Painter_icpp_init_stub
|
||||
#include "Core/init"
|
||||
#include "CtrlLib/init"
|
||||
#define BLITZ_INDEX__ F1F279540D3FE6AF9024371A0E93C1FBB
|
||||
#define BLITZ_INDEX__ F18922416C44F220B741A74F8D9F1A79C
|
||||
#include "PaintPainting.icpp"
|
||||
#undef BLITZ_INDEX__
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue