mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-07-11 22:03:01 -06:00
.Core: fixed recent omission in ArrayMap - added using clause to include AMap's Insert variants previously hidden by Insert(int index, const K& key, T *newt)
+Oracle: implemented one of the ugliest interfaces I've ever seen - OracleClob to read/write Oracle CLOB's both in single-character and UTF8 mode git-svn-id: svn://ultimatepp.org/upp/trunk@3499 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
parent
76c9546784
commit
529afaf310
3 changed files with 225 additions and 9 deletions
|
|
@ -159,6 +159,7 @@ public:
|
|||
T& Add(const K& k) { return B::Add(k); }
|
||||
T& Add(const K& k, T *newt) { B::key.Add(k); return B::value.Add(newt); }
|
||||
T& Insert(int i, const K& k, T *newt) { B::key.Insert(i, k); return B::value.Insert(i, newt); }
|
||||
using B::Insert;
|
||||
template <class TT> TT& Create(const K& k) { TT *q = new TT; B::key.Add(k); return B::value.Add(q); }
|
||||
|
||||
T& Set(int i, T *ptr) { return B::value.Set(i, ptr); }
|
||||
|
|
|
|||
|
|
@ -791,10 +791,14 @@ void OCI8Connection::GetColumn(int i, String& s) const {
|
|||
int handle;
|
||||
GetColumn(i, handle);
|
||||
if(!IsNull(handle)) {
|
||||
OracleBlob blob(*session, handle);
|
||||
s = LoadStream(blob);
|
||||
if(session->utf8_session && c.type == SQLT_CLOB)
|
||||
s = ToCharset(CHARSET_DEFAULT, s, CHARSET_UTF8);
|
||||
if(c.type == SQLT_CLOB && session->utf8_session) {
|
||||
OracleClob clob(*session, handle);
|
||||
s = FromUnicode(clob.Read());
|
||||
}
|
||||
else {
|
||||
OracleBlob blob(*session, handle);
|
||||
s = LoadStream(blob);
|
||||
}
|
||||
}
|
||||
else
|
||||
s = Null;
|
||||
|
|
@ -820,12 +824,15 @@ void OCI8Connection::GetColumn(int i, WString& ws) const {
|
|||
int handle;
|
||||
GetColumn(i, handle);
|
||||
if(!IsNull(handle)) {
|
||||
OracleBlob blob(*session, handle);
|
||||
String s = LoadStream(blob);
|
||||
if(session->utf8_session && c.type == SQLT_CLOB)
|
||||
ws = FromUtf8(s);
|
||||
else
|
||||
if(session->utf8_session && c.type == SQLT_CLOB) {
|
||||
OracleClob clob(*session, handle);
|
||||
ws = clob.Read();
|
||||
}
|
||||
else {
|
||||
OracleBlob blob(*session, handle);
|
||||
String s = LoadStream(blob);
|
||||
ws = s.ToWString();
|
||||
}
|
||||
}
|
||||
else
|
||||
ws = Null;
|
||||
|
|
@ -1435,4 +1442,179 @@ OracleBlob::~OracleBlob() {
|
|||
Close();
|
||||
}
|
||||
|
||||
void OracleClob::SetLength(int sz)
|
||||
{
|
||||
SetStreamSize(sz << 1);
|
||||
}
|
||||
|
||||
void OracleClob::SetStreamSize(int64 pos) {
|
||||
ASSERT(pos <= GetStreamSize());
|
||||
if(pos < (int)GetStreamSize())
|
||||
session->oci8.OCILobTrim(session->svchp, session->errhp, locp, (int)(pos >> 1));
|
||||
}
|
||||
|
||||
dword OracleClob::Read(int64 at, void *ptr, dword size) {
|
||||
ASSERT(IsOpen() && (style & STRM_READ) && session);
|
||||
ASSERT(at == (dword)at);
|
||||
int full_bytes = 0;
|
||||
bool utf8 = session->IsUtf8Session();
|
||||
ub4 readpos = (ub4)(at >> 1);
|
||||
ub4 readsize = (ub4)(((at + size + 1) & ~1) - (readpos << 1));
|
||||
ub4 read16 = (readsize + 1) >> 1;
|
||||
ub4 bufsize = min(utf8 ? 4 * (int)read16 : (int)read16, 16384);
|
||||
Buffer<char> charbuf(bufsize);
|
||||
while(read16 > 0) {
|
||||
ub4 nchars = read16;
|
||||
sword res = session->oci8.OCILobRead(session->svchp, session->errhp, locp,
|
||||
&nchars, readpos + 1, charbuf, bufsize,
|
||||
NULL, NULL, 0, SQLCS_IMPLICIT);
|
||||
if(res != OCI_SUCCESS && res != OCI_NEED_DATA)
|
||||
return full_bytes;
|
||||
WString unibuf;
|
||||
if(utf8)
|
||||
unibuf = FromUtf8(charbuf, nchars);
|
||||
else {
|
||||
WStringBuffer tmp;
|
||||
tmp.SetLength(nchars);
|
||||
ToUnicode(tmp, charbuf, nchars, CHARSET_DEFAULT);
|
||||
unibuf = tmp;
|
||||
}
|
||||
int ulen = unibuf.GetLength();
|
||||
int uoff = (int)(at & 1);
|
||||
int upart = min((int)size, 2 * ulen - uoff);
|
||||
memcpy(ptr, (const byte *)~unibuf + uoff, upart);
|
||||
ptr = (byte *)ptr + upart;
|
||||
at += upart;
|
||||
size -= upart;
|
||||
read16 -= ulen;
|
||||
full_bytes += upart;
|
||||
if(res != OCI_NEED_DATA)
|
||||
break;
|
||||
}
|
||||
return full_bytes;
|
||||
}
|
||||
|
||||
void OracleClob::Write(int64 at, const void *ptr, dword size) {
|
||||
ASSERT(IsOpen() && (style & STRM_WRITE) && session);
|
||||
ASSERT(at == (dword)at);
|
||||
bool utf8 = session->IsUtf8Session();
|
||||
if(at & 1) {
|
||||
char auxbuf[2];
|
||||
Read(at - 1, auxbuf, 1);
|
||||
auxbuf[1] = *(byte *)ptr;
|
||||
word wch = Peek16le(auxbuf);
|
||||
String chrbuf = (utf8 ? ToUtf8(wch) : String(FromUnicode(wch, CHARSET_DEFAULT), 1));
|
||||
ub4 n = chrbuf.GetLength();
|
||||
sword res = session->oci8.OCILobWrite(session->svchp, session->errhp, locp,
|
||||
&n, (dword)(at >> 1) + 1, (dvoid *)chrbuf.Begin(), chrbuf.GetLength(),
|
||||
OCI_ONE_PIECE, NULL, NULL, 0, SQLCS_IMPLICIT);
|
||||
if(res != OCI_SUCCESS || n != 1) {
|
||||
SetError();
|
||||
return;
|
||||
}
|
||||
|
||||
ptr = (byte *)ptr + 1;
|
||||
size--;
|
||||
at++;
|
||||
}
|
||||
|
||||
if(size >> 1) {
|
||||
ub4 nchars = size >> 1;
|
||||
String chrbuf;
|
||||
if(utf8)
|
||||
chrbuf = ToUtf8((const wchar *)ptr, nchars);
|
||||
else {
|
||||
StringBuffer tmp;
|
||||
tmp.SetLength(nchars);
|
||||
FromUnicode(tmp, (const wchar *)ptr, nchars, CHARSET_DEFAULT);
|
||||
chrbuf = tmp;
|
||||
}
|
||||
ub4 n = chrbuf.GetLength();
|
||||
sword res = session->oci8.OCILobWrite(session->svchp, session->errhp, locp,
|
||||
&n, (dword)(at >> 1) + 1, (dvoid *)chrbuf.Begin(), chrbuf.GetLength(),
|
||||
OCI_ONE_PIECE, NULL, NULL, 0, SQLCS_IMPLICIT);
|
||||
if(res != OCI_SUCCESS || n != nchars) {
|
||||
SetError();
|
||||
return;
|
||||
}
|
||||
ptr = (byte *)ptr + (nchars << 1);
|
||||
at += (nchars << 1);
|
||||
size -= (nchars << 1);
|
||||
}
|
||||
|
||||
if(size & 1) {
|
||||
char auxbuf[2];
|
||||
ub4 pos16 = (ub4)(at >> 1);
|
||||
Read(at, auxbuf + 1, 1);
|
||||
auxbuf[0] = *((byte *)ptr + size - 1);
|
||||
word wch = Peek16le(auxbuf);
|
||||
String chrbuf = (utf8 ? ToUtf8(wch) : String(FromUnicode(wch, CHARSET_DEFAULT), 1));
|
||||
ub4 n = chrbuf.GetLength();
|
||||
sword res = session->oci8.OCILobWrite(session->svchp, session->errhp, locp,
|
||||
&n, pos16 + 1, (dvoid *)chrbuf.Begin(), chrbuf.GetLength(),
|
||||
OCI_ONE_PIECE, NULL, NULL, 0, SQLCS_IMPLICIT);
|
||||
if(res != OCI_SUCCESS || n != 1) {
|
||||
SetError();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WString OracleClob::Read()
|
||||
{
|
||||
WStringBuffer out;
|
||||
int nchars = (int)(GetLeft() >> 1);
|
||||
out.SetCount(nchars);
|
||||
Seek(0);
|
||||
Stream::Get(out, 2 * nchars);
|
||||
return out;
|
||||
}
|
||||
|
||||
void OracleClob::Write(const WString& w)
|
||||
{
|
||||
Put(w, 2 * w.GetLength());
|
||||
}
|
||||
|
||||
void OracleClob::Assign(Oracle8& s, int blob) {
|
||||
session = &s;
|
||||
locp = (OCILobLocator *)blob;
|
||||
ub4 n;
|
||||
OpenInit(READWRITE,
|
||||
session->oci8.OCILobGetLength(session->svchp, session->errhp, locp, &n) == OCI_SUCCESS
|
||||
? 2 * n : 0);
|
||||
}
|
||||
|
||||
|
||||
void OracleClob::Assign(const Sql& sql, int blob) {
|
||||
Oracle8 *session = dynamic_cast<Oracle8 *>(&sql.GetSession());
|
||||
ASSERT(session);
|
||||
Assign(*session, blob);
|
||||
}
|
||||
|
||||
bool OracleClob::IsOpen() const {
|
||||
return locp;
|
||||
}
|
||||
|
||||
void OracleClob::Close() {
|
||||
if(locp) Flush();
|
||||
locp = NULL;
|
||||
}
|
||||
|
||||
OracleClob::OracleClob(const Sql& sql, int blob) {
|
||||
Assign(sql, blob);
|
||||
}
|
||||
|
||||
OracleClob::OracleClob(Oracle8& session, int blob) {
|
||||
Assign(session, blob);
|
||||
}
|
||||
|
||||
OracleClob::OracleClob() {
|
||||
locp = NULL;
|
||||
session = NULL;
|
||||
}
|
||||
|
||||
OracleClob::~OracleClob() {
|
||||
Close();
|
||||
}
|
||||
|
||||
END_UPP_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ private:
|
|||
private:
|
||||
friend class OCI8Connection;
|
||||
friend class OracleBlob;
|
||||
friend class OracleClob;
|
||||
|
||||
OCIEnv *envhp;
|
||||
OCIError *errhp;
|
||||
|
|
@ -137,6 +138,38 @@ public:
|
|||
~OracleBlob();
|
||||
};
|
||||
|
||||
class OracleClob : public BlockStream {
|
||||
protected:
|
||||
virtual void SetStreamSize(int64 size);
|
||||
virtual dword Read(int64 at, void *ptr, dword size);
|
||||
virtual void Write(int64 at, const void *data, dword size);
|
||||
|
||||
public:
|
||||
virtual bool IsOpen() const;
|
||||
virtual void Close();
|
||||
|
||||
protected:
|
||||
OCILobLocator *locp;
|
||||
Oracle8 *session;
|
||||
|
||||
void Init(dword size);
|
||||
|
||||
public:
|
||||
operator bool() const { return IsOpen(); }
|
||||
|
||||
void Assign(const Sql& sql, int blob);
|
||||
void Assign(Oracle8& session, int blob);
|
||||
|
||||
WString Read();
|
||||
void Write(const WString& w);
|
||||
void SetLength(int sz);
|
||||
|
||||
OracleClob();
|
||||
OracleClob(const Sql& sql, int blob);
|
||||
OracleClob(Oracle8& session, int blob);
|
||||
~OracleClob();
|
||||
};
|
||||
|
||||
#ifdef text
|
||||
#undef text
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue