Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
M
MariaDB
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nexedi
MariaDB
Commits
e38792a6
Commit
e38792a6
authored
Jul 22, 2004
by
pekka@mysql.com
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
ha_ndb blobs
parent
ce96f0e4
Changes
19
Show whitespace changes
Inline
Side-by-side
Showing
19 changed files
with
850 additions
and
418 deletions
+850
-418
mysql-test/r/ndb_blob.result
mysql-test/r/ndb_blob.result
+0
-0
mysql-test/t/ndb_blob.test
mysql-test/t/ndb_blob.test
+0
-0
ndb/include/kernel/signaldata/DictTabInfo.hpp
ndb/include/kernel/signaldata/DictTabInfo.hpp
+2
-2
ndb/include/ndbapi/NdbBlob.hpp
ndb/include/ndbapi/NdbBlob.hpp
+64
-18
ndb/include/ndbapi/NdbConnection.hpp
ndb/include/ndbapi/NdbConnection.hpp
+25
-2
ndb/include/ndbapi/NdbDictionary.hpp
ndb/include/ndbapi/NdbDictionary.hpp
+4
-3
ndb/include/util/NdbSqlUtil.hpp
ndb/include/util/NdbSqlUtil.hpp
+5
-7
ndb/src/common/util/NdbSqlUtil.cpp
ndb/src/common/util/NdbSqlUtil.cpp
+4
-4
ndb/src/ndbapi/NdbBlob.cpp
ndb/src/ndbapi/NdbBlob.cpp
+176
-76
ndb/src/ndbapi/NdbConnection.cpp
ndb/src/ndbapi/NdbConnection.cpp
+41
-26
ndb/src/ndbapi/NdbDictionary.cpp
ndb/src/ndbapi/NdbDictionary.cpp
+54
-37
ndb/src/ndbapi/NdbDictionaryImpl.cpp
ndb/src/ndbapi/NdbDictionaryImpl.cpp
+4
-4
ndb/src/ndbapi/NdbDictionaryImpl.hpp
ndb/src/ndbapi/NdbDictionaryImpl.hpp
+1
-1
ndb/src/ndbapi/NdbRecAttr.cpp
ndb/src/ndbapi/NdbRecAttr.cpp
+44
-21
ndb/src/ndbapi/NdbResultSet.cpp
ndb/src/ndbapi/NdbResultSet.cpp
+7
-0
ndb/test/include/NDBT_Table.hpp
ndb/test/include/NDBT_Table.hpp
+0
-1
ndb/test/ndbapi/testBlobs.cpp
ndb/test/ndbapi/testBlobs.cpp
+417
-186
ndb/test/src/NDBT_Table.cpp
ndb/test/src/NDBT_Table.cpp
+0
-29
ndb/test/src/NDBT_Test.cpp
ndb/test/src/NDBT_Test.cpp
+2
-1
No files found.
mysql-test/r/ndb_blob.result
0 → 100644
View file @
e38792a6
mysql-test/t/ndb_blob.test
0 → 100644
View file @
e38792a6
ndb/include/kernel/signaldata/DictTabInfo.hpp
View file @
e38792a6
...
...
@@ -311,7 +311,7 @@ public:
ExtDatetime
=
NdbSqlUtil
::
Type
::
Datetime
,
ExtTimespec
=
NdbSqlUtil
::
Type
::
Timespec
,
ExtBlob
=
NdbSqlUtil
::
Type
::
Blob
,
Ext
Clob
=
NdbSqlUtil
::
Type
::
Clob
Ext
Text
=
NdbSqlUtil
::
Type
::
Text
};
// Attribute data interpretation
...
...
@@ -435,7 +435,7 @@ public:
AttributeArraySize
=
12
*
AttributeExtLength
;
return
true
;
case
DictTabInfo
:
:
ExtBlob
:
case
DictTabInfo
:
:
Ext
Clob
:
case
DictTabInfo
:
:
Ext
Text
:
AttributeType
=
DictTabInfo
::
StringType
;
AttributeSize
=
DictTabInfo
::
an8Bit
;
// head + inline part [ attr precision ]
...
...
ndb/include/ndbapi/NdbBlob.hpp
View file @
e38792a6
...
...
@@ -50,24 +50,33 @@ class NdbColumnImpl;
* - closed: after transaction commit
* - invalid: after rollback or transaction close
*
* NdbBlob supports
2
styles of data access:
* NdbBlob supports
3
styles of data access:
*
* - in prepare phase, NdbBlob methods getValue and setValue are used to
* prepare a read or write of a
single
blob value of known size
* prepare a read or write of a blob value of known size
*
* - in active phase, NdbBlob methods readData and writeData are used to
* read or write blob data of undetermined size
* - in prepare phase, setActiveHook is used to define a routine which
* is invoked as soon as the handle becomes active
*
* - in active phase, readData and writeData are used to read or write
* blob data of arbitrary size
*
* The styles can be applied in combination (in above order).
*
* Blob operations take effect at next transaction execute. In some
* cases NdbBlob is forced to do implicit executes. To avoid this,
* operate on complete blob parts.
*
* Use NdbConnection::executePendingBlobOps to flush your reads and
* writes. It avoids execute penalty if nothing is pending. It is not
* needed after execute (obviously) or after next scan result.
*
* NdbBlob methods return -1 on error and 0 on success, and use output
* parameters when necessary.
*
* Notes:
* - table and its blob part tables are not created atomically
* - blob data operations take effect at next transaction execute
* - NdbBlob may need to do implicit executes on the transaction
* - read and write of complete parts is much more efficient
* - scan must use the "new" interface NdbScanOperation
* - scan with blobs applies hold-read-lock (at minimum)
* - to update a blob in a read op requires exclusive tuple lock
* - update op in scan must do its own getBlobHandle
* - delete creates implicit, not-accessible blob handles
...
...
@@ -78,12 +87,16 @@ class NdbColumnImpl;
* - scan must use exclusive locking for now
*
* Todo:
* - add scan method hold-read-lock-until-next + return-keyinfo
* - better check of keyinfo length when setting keys
* - better check of allowed blob op vs locking mode
* - add scan method hold-read-lock + return-keyinfo
* - check keyinfo length when setting keys
* - check allowed blob ops vs locking mode
* - overload control (too many pending ops)
*/
class
NdbBlob
{
public:
/**
* State.
*/
enum
State
{
Idle
=
0
,
Prepared
=
1
,
...
...
@@ -92,9 +105,15 @@ public:
Invalid
=
9
};
State
getState
();
/**
* Inline blob header.
*/
struct
Head
{
Uint64
length
;
};
/**
* Prepare to read blob value. The value is available after execute.
* Use
is
Null to check for NULL and getLength to get the real length
* Use
get
Null to check for NULL and getLength to get the real length
* and to check for truncation. Sets current read/write position to
* after the data read.
*/
...
...
@@ -106,6 +125,20 @@ public:
* data to null pointer (0) to create a NULL value.
*/
int
setValue
(
const
void
*
data
,
Uint32
bytes
);
/**
* Callback for setActiveHook. Invoked immediately when the prepared
* operation has been executed (but not committed). Any getValue or
* setValue is done first. The blob handle is active so readData or
* writeData etc can be used to manipulate blob value. A user-defined
* argument is passed along. Returns non-zero on error.
*/
typedef
int
ActiveHook
(
NdbBlob
*
me
,
void
*
arg
);
/**
* Define callback for blob handle activation. The queue of prepared
* operations will be executed in no commit mode up to this point and
* then the callback is invoked.
*/
int
setActiveHook
(
ActiveHook
*
activeHook
,
void
*
arg
);
/**
* Check if blob is null.
*/
...
...
@@ -115,7 +148,7 @@ public:
*/
int
setNull
();
/**
* Get current length in bytes. Use
is
Null to distinguish between
* Get current length in bytes. Use
get
Null to distinguish between
* length 0 blob and NULL blob.
*/
int
getLength
(
Uint64
&
length
);
...
...
@@ -180,6 +213,13 @@ public:
static
const
int
ErrAbort
=
4268
;
// "Unknown blob error"
static
const
int
ErrUnknown
=
4269
;
/**
* Return info about all blobs in this operation.
*/
// Get first blob in list
NdbBlob
*
blobsFirstBlob
();
// Get next blob in list after this one
NdbBlob
*
blobsNextBlob
();
private:
friend
class
Ndb
;
...
...
@@ -214,10 +254,11 @@ private:
bool
theSetFlag
;
const
char
*
theSetBuf
;
Uint32
theGetSetBytes
;
// head
struct
Head
{
Uint64
length
;
};
// pending ops
Uint8
thePendingBlobOps
;
// activation callback
ActiveHook
*
theActiveHook
;
void
*
theActiveHookArg
;
// buffers
struct
Buf
{
char
*
data
;
...
...
@@ -235,7 +276,6 @@ private:
char
*
theInlineData
;
NdbRecAttr
*
theHeadInlineRecAttr
;
bool
theHeadInlineUpdateFlag
;
bool
theNewPartFlag
;
// length and read/write position
int
theNullFlag
;
Uint64
theLength
;
...
...
@@ -276,6 +316,11 @@ private:
int
insertParts
(
const
char
*
buf
,
Uint32
part
,
Uint32
count
);
int
updateParts
(
const
char
*
buf
,
Uint32
part
,
Uint32
count
);
int
deleteParts
(
Uint32
part
,
Uint32
count
);
// pending ops
int
executePendingBlobReads
();
int
executePendingBlobWrites
();
// callbacks
int
invokeActiveHook
();
// blob handle maintenance
int
atPrepare
(
NdbConnection
*
aCon
,
NdbOperation
*
anOp
,
const
NdbColumnImpl
*
aColumn
);
int
preExecute
(
ExecType
anExecType
,
bool
&
batch
);
...
...
@@ -287,6 +332,7 @@ private:
void
setErrorCode
(
NdbOperation
*
anOp
,
bool
invalidFlag
=
true
);
void
setErrorCode
(
NdbConnection
*
aCon
,
bool
invalidFlag
=
true
);
#ifdef VM_TRACE
int
getOperationType
()
const
;
friend
class
NdbOut
&
operator
<<
(
NdbOut
&
,
const
NdbBlob
&
);
#endif
};
...
...
ndb/include/ndbapi/NdbConnection.hpp
View file @
e38792a6
...
...
@@ -431,6 +431,15 @@ public:
/** @} *********************************************************************/
/**
* Execute the transaction in NoCommit mode if there are any not-yet
* executed blob part operations of given types. Otherwise do
* nothing. The flags argument is bitwise OR of (1 << optype) where
* optype comes from NdbOperation::OperationType. Only the basic PK
* ops are used (read, insert, update, delete).
*/
int
executePendingBlobOps
(
Uint8
flags
=
0xFF
);
private:
/**
* Release completed operations
...
...
@@ -642,6 +651,7 @@ private:
Uint32
theBuddyConPtr
;
// optim: any blobs
bool
theBlobFlag
;
Uint8
thePendingBlobOps
;
static
void
sendTC_COMMIT_ACK
(
NdbApiSignal
*
,
Uint32
transId1
,
Uint32
transId2
,
...
...
@@ -869,6 +879,21 @@ NdbConnection::OpSent()
theNoOfOpSent
++
;
}
/******************************************************************************
void executePendingBlobOps();
******************************************************************************/
#include <stdlib.h>
inline
int
NdbConnection
::
executePendingBlobOps
(
Uint8
flags
)
{
if
(
thePendingBlobOps
&
flags
)
{
// not executeNoBlobs because there can be new ops with blobs
return
execute
(
NoCommit
);
}
return
0
;
}
inline
Uint32
NdbConnection
::
ptr2int
(){
...
...
@@ -876,5 +901,3 @@ NdbConnection::ptr2int(){
}
#endif
ndb/include/ndbapi/NdbDictionary.hpp
View file @
e38792a6
...
...
@@ -183,7 +183,7 @@ public:
Datetime
,
///< Precision down to 1 sec (sizeof(Datetime) == 8 bytes )
Timespec
,
///< Precision down to 1 nsec(sizeof(Datetime) == 12 bytes )
Blob
,
///< Binary large object (see NdbBlob)
Clob
///< Text blob
Text
///< Text blob
};
/**
...
...
@@ -309,7 +309,8 @@ public:
/**
* For blob, set or get "part size" i.e. number of bytes to store in
* each tuple of the "blob table". Must be less than 64k.
* each tuple of the "blob table". Can be set to zero to omit parts
* and to allow only inline bytes ("tinyblob").
*/
void
setPartSize
(
int
size
)
{
setScale
(
size
);
}
int
getPartSize
()
const
{
return
getScale
();
}
...
...
@@ -1060,6 +1061,6 @@ public:
};
};
class
NdbOut
&
operator
<<
(
class
NdbOut
&
ndbout
,
const
NdbDictionary
::
Column
::
Type
type
);
class
NdbOut
&
operator
<<
(
class
NdbOut
&
out
,
const
NdbDictionary
::
Column
&
col
);
#endif
ndb/include/util/NdbSqlUtil.hpp
View file @
e38792a6
...
...
@@ -80,7 +80,7 @@ public:
Datetime
,
// Precision down to 1 sec (size 8 bytes)
Timespec
,
// Precision down to 1 nsec (size 12 bytes)
Blob
,
// Blob
Clob
// Text blob
Text
// Text blob
};
Enum
m_typeId
;
Cmp
*
m_cmp
;
// set to NULL if cmp not implemented
...
...
@@ -125,7 +125,7 @@ private:
static
Cmp
cmpDatetime
;
static
Cmp
cmpTimespec
;
static
Cmp
cmpBlob
;
static
Cmp
cmp
Clob
;
static
Cmp
cmp
Text
;
};
inline
int
...
...
@@ -344,17 +344,15 @@ NdbSqlUtil::cmp(Uint32 typeId, const Uint32* p1, const Uint32* p2, Uint32 full,
break
;
case
Type
:
:
Blob
:
// XXX fix
break
;
case
Type
:
:
Clob
:
case
Type
:
:
Text
:
{
// skip blob head, the rest is
var
char
// skip blob head, the rest is char
const
unsigned
skip
=
NDB_BLOB_HEAD_SIZE
;
if
(
size
>=
skip
+
1
)
{
union
{
const
Uint32
*
p
;
const
char
*
v
;
}
u1
,
u2
;
u1
.
p
=
p1
+
skip
;
u2
.
p
=
p2
+
skip
;
// length in first 2 bytes
int
k
=
strncmp
(
u1
.
v
+
2
,
u2
.
v
+
2
,
((
size
-
skip
)
<<
2
)
-
2
);
return
k
<
0
?
-
1
:
k
>
0
?
+
1
:
full
==
size
?
0
:
CmpUnknown
;
// TODO
}
return
CmpUnknown
;
}
...
...
ndb/src/common/util/NdbSqlUtil.cpp
View file @
e38792a6
...
...
@@ -161,8 +161,8 @@ NdbSqlUtil::m_typeList[] = {
NULL
// cmpDatetime
},
{
Type
::
Clob
,
cmp
Clob
Type
::
Text
,
cmp
Text
}
};
...
...
@@ -299,9 +299,9 @@ NdbSqlUtil::cmpBlob(const Uint32* p1, const Uint32* p2, Uint32 full, Uint32 size
}
int
NdbSqlUtil
::
cmp
Clob
(
const
Uint32
*
p1
,
const
Uint32
*
p2
,
Uint32
full
,
Uint32
size
)
NdbSqlUtil
::
cmp
Text
(
const
Uint32
*
p1
,
const
Uint32
*
p2
,
Uint32
full
,
Uint32
size
)
{
return
cmp
(
Type
::
Clob
,
p1
,
p2
,
full
,
size
);
return
cmp
(
Type
::
Text
,
p1
,
p2
,
full
,
size
);
}
#ifdef NDB_SQL_UTIL_TEST
...
...
ndb/src/ndbapi/NdbBlob.cpp
View file @
e38792a6
...
...
@@ -28,10 +28,11 @@
do { \
static const char* p = getenv("NDB_BLOB_DEBUG"); \
if (p == 0 || *p == 0 || *p == '0') break; \
const char* cname = theColumn == NULL ? "BLOB" : theColumn->m_name.c_str(); \
ndbout << cname << " " << __LINE__ << " " << x << " " << *this << endl; \
static char* prefix = "BLOB"; \
const char* cname = theColumn == NULL ? "-" : theColumn->m_name.c_str(); \
ndbout << prefix << " " << hex << (void*)this << " " << cname; \
ndbout << " " << dec << __LINE__ << " " << x << " " << *this << endl; \
} while (0)
#define EXE() assert(theNdbCon->executeNoBlobs(NoCommit) == 0)
#else
#define DBG(x)
#endif
...
...
@@ -49,7 +50,7 @@ ndb_blob_debug(const Uint32* data, unsigned size)
/*
* Reading index table directly (as a table) is faster but there are
* bugs or limitations. Keep the code
but
make possible to choose.
* bugs or limitations. Keep the code
and
make possible to choose.
*/
static
const
bool
g_ndb_blob_ok_to_read_index_table
=
false
;
...
...
@@ -116,7 +117,7 @@ NdbBlob::getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnIm
case
NdbDictionary
:
:
Column
::
Blob
:
bc
.
setType
(
NdbDictionary
::
Column
::
Binary
);
break
;
case
NdbDictionary
:
:
Column
::
Clob
:
case
NdbDictionary
:
:
Column
::
Text
:
bc
.
setType
(
NdbDictionary
::
Column
::
Char
);
break
;
default:
...
...
@@ -155,11 +156,13 @@ NdbBlob::init()
theSetFlag
=
false
;
theSetBuf
=
NULL
;
theGetSetBytes
=
0
;
thePendingBlobOps
=
0
;
theActiveHook
=
NULL
;
theActiveHookArg
=
NULL
;
theHead
=
NULL
;
theInlineData
=
NULL
;
theHeadInlineRecAttr
=
NULL
;
theHeadInlineUpdateFlag
=
false
;
theNewPartFlag
=
false
;
theNullFlag
=
-
1
;
theLength
=
0
;
thePos
=
0
;
...
...
@@ -270,7 +273,7 @@ NdbBlob::isScanOp()
inline
Uint32
NdbBlob
::
getPartNumber
(
Uint64
pos
)
{
assert
(
pos
>=
theInlineSize
);
assert
(
thePartSize
!=
0
&&
pos
>=
theInlineSize
);
return
(
pos
-
theInlineSize
)
/
thePartSize
;
}
...
...
@@ -322,10 +325,10 @@ int
NdbBlob
::
setTableKeyValue
(
NdbOperation
*
anOp
)
{
const
Uint32
*
data
=
(
const
Uint32
*
)
theKeyBuf
.
data
;
DBG
(
"setTableKeyValue key="
<<
ndb_blob_debug
(
data
,
theTable
->
m_sizeOfKeysInWords
));
const
unsigned
columns
=
theTable
->
m_columns
.
size
();
unsigned
pos
=
0
;
const
unsigned
size
=
theTable
->
m_columns
.
size
();
DBG
(
"setTableKeyValue key="
<<
ndb_blob_debug
(
data
,
size
));
for
(
unsigned
i
=
0
;
i
<
size
;
i
++
)
{
for
(
unsigned
i
=
0
;
i
<
columns
;
i
++
)
{
NdbColumnImpl
*
c
=
theTable
->
m_columns
[
i
];
assert
(
c
!=
NULL
);
if
(
c
->
m_pk
)
{
...
...
@@ -345,10 +348,10 @@ int
NdbBlob
::
setAccessKeyValue
(
NdbOperation
*
anOp
)
{
const
Uint32
*
data
=
(
const
Uint32
*
)
theAccessKeyBuf
.
data
;
DBG
(
"setAccessKeyValue key="
<<
ndb_blob_debug
(
data
,
theAccessTable
->
m_sizeOfKeysInWords
));
const
unsigned
columns
=
theAccessTable
->
m_columns
.
size
();
unsigned
pos
=
0
;
const
unsigned
size
=
theAccessTable
->
m_columns
.
size
();
DBG
(
"setAccessKeyValue key="
<<
ndb_blob_debug
(
data
,
size
));
for
(
unsigned
i
=
0
;
i
<
size
;
i
++
)
{
for
(
unsigned
i
=
0
;
i
<
columns
;
i
++
)
{
NdbColumnImpl
*
c
=
theAccessTable
->
m_columns
[
i
];
assert
(
c
!=
NULL
);
if
(
c
->
m_pk
)
{
...
...
@@ -479,11 +482,27 @@ NdbBlob::setValue(const void* data, Uint32 bytes)
return
0
;
}
// activation hook
int
NdbBlob
::
setActiveHook
(
ActiveHook
activeHook
,
void
*
arg
)
{
DBG
(
"setActiveHook hook="
<<
hex
<<
(
void
*
)
activeHook
<<
" arg="
<<
hex
<<
arg
);
if
(
theState
!=
Prepared
)
{
setErrorCode
(
ErrState
);
return
-
1
;
}
theActiveHook
=
activeHook
;
theActiveHookArg
=
arg
;
return
0
;
}
// misc operations
int
NdbBlob
::
getNull
(
bool
&
isNull
)
{
DBG
(
"getNull"
);
if
(
theState
==
Prepared
&&
theSetFlag
)
{
isNull
=
(
theSetBuf
==
NULL
);
return
0
;
...
...
@@ -520,6 +539,7 @@ NdbBlob::setNull()
int
NdbBlob
::
getLength
(
Uint64
&
len
)
{
DBG
(
"getLength"
);
if
(
theState
==
Prepared
&&
theSetFlag
)
{
len
=
theGetSetBytes
;
return
0
;
...
...
@@ -535,17 +555,17 @@ NdbBlob::getLength(Uint64& len)
int
NdbBlob
::
truncate
(
Uint64
length
)
{
DBG
(
"truncate
k
ength="
<<
length
);
DBG
(
"truncate
l
ength="
<<
length
);
if
(
theNullFlag
==
-
1
)
{
setErrorCode
(
ErrState
);
return
-
1
;
}
if
(
theLength
>
length
)
{
if
(
length
>
=
theInlineSize
)
{
Uint32
part1
=
getPartNumber
(
length
);
if
(
length
>
theInlineSize
)
{
Uint32
part1
=
getPartNumber
(
length
-
1
);
Uint32
part2
=
getPartNumber
(
theLength
-
1
);
assert
(
part2
>=
part1
);
if
(
deleteParts
(
part
1
,
part2
-
part1
)
==
-
1
)
if
(
part2
>
part1
&&
deleteParts
(
part1
+
1
,
part2
-
part1
)
==
-
1
)
return
-
1
;
}
else
{
if
(
deleteParts
(
0
,
getPartCount
())
==
-
1
)
...
...
@@ -560,6 +580,7 @@ NdbBlob::truncate(Uint64 length)
int
NdbBlob
::
getPos
(
Uint64
&
pos
)
{
DBG
(
"getPos"
);
if
(
theNullFlag
==
-
1
)
{
setErrorCode
(
ErrState
);
return
-
1
;
...
...
@@ -571,6 +592,7 @@ NdbBlob::getPos(Uint64& pos)
int
NdbBlob
::
setPos
(
Uint64
pos
)
{
DBG
(
"setPos pos="
<<
pos
);
if
(
theNullFlag
==
-
1
)
{
setErrorCode
(
ErrState
);
return
-
1
;
...
...
@@ -629,6 +651,10 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes)
len
-=
n
;
}
}
if
(
len
>
0
&&
thePartSize
==
0
)
{
setErrorCode
(
ErrSeek
);
return
-
1
;
}
if
(
len
>
0
)
{
assert
(
pos
>=
theInlineSize
);
Uint32
off
=
(
pos
-
theInlineSize
)
%
thePartSize
;
...
...
@@ -638,11 +664,10 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes)
Uint32
part
=
(
pos
-
theInlineSize
)
/
thePartSize
;
if
(
readParts
(
thePartBuf
.
data
,
part
,
1
)
==
-
1
)
return
-
1
;
DBG
(
"force execute"
);
if
(
theNdbCon
->
executeNoBlobs
(
NoCommit
)
==
-
1
)
{
setErrorCode
(
theNdbOp
);
// need result now
DBG
(
"execute pending part reads"
);
if
(
executePendingBlobReads
()
==
-
1
)
return
-
1
;
}
Uint32
n
=
thePartSize
-
off
;
if
(
n
>
len
)
n
=
len
;
...
...
@@ -673,11 +698,10 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes)
Uint32
part
=
(
pos
-
theInlineSize
)
/
thePartSize
;
if
(
readParts
(
thePartBuf
.
data
,
part
,
1
)
==
-
1
)
return
-
1
;
DBG
(
"force execute"
);
if
(
theNdbCon
->
executeNoBlobs
(
NoCommit
)
==
-
1
)
{
setErrorCode
(
theNdbOp
);
// need result now
DBG
(
"execute pending part reads"
);
if
(
executePendingBlobReads
()
==
-
1
)
return
-
1
;
}
memcpy
(
buf
,
thePartBuf
.
data
,
len
);
Uint32
n
=
len
;
pos
+=
n
;
...
...
@@ -736,29 +760,27 @@ NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes)
len
-=
n
;
}
}
if
(
len
>
0
&&
thePartSize
==
0
)
{
setErrorCode
(
ErrSeek
);
return
-
1
;
}
if
(
len
>
0
)
{
assert
(
pos
>=
theInlineSize
);
Uint32
off
=
(
pos
-
theInlineSize
)
%
thePartSize
;
// partial first block
if
(
off
!=
0
)
{
DBG
(
"partial first block pos="
<<
pos
<<
" len="
<<
len
);
if
(
theNewPartFlag
)
{
// must flush insert to guarantee read
DBG
(
"force execute"
);
if
(
theNdbCon
->
executeNoBlobs
(
NoCommit
)
==
-
1
)
{
setErrorCode
(
theNdbOp
);
// flush writes to guarantee correct read
DBG
(
"execute pending part writes"
);
if
(
executePendingBlobWrites
()
==
-
1
)
return
-
1
;
}
theNewPartFlag
=
false
;
}
Uint32
part
=
(
pos
-
theInlineSize
)
/
thePartSize
;
if
(
readParts
(
thePartBuf
.
data
,
part
,
1
)
==
-
1
)
return
-
1
;
DBG
(
"force execute"
);
if
(
theNdbCon
->
executeNoBlobs
(
NoCommit
)
==
-
1
)
{
setErrorCode
(
theNdbOp
);
// need result now
DBG
(
"execute pending part reafs"
);
if
(
executePendingBlobReads
()
==
-
1
)
return
-
1
;
}
Uint32
n
=
thePartSize
-
off
;
if
(
n
>
len
)
{
memset
(
thePartBuf
.
data
+
off
+
len
,
theFillChar
,
n
-
len
);
...
...
@@ -799,22 +821,16 @@ NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes)
assert
((
pos
-
theInlineSize
)
%
thePartSize
==
0
&&
len
<
thePartSize
);
Uint32
part
=
(
pos
-
theInlineSize
)
/
thePartSize
;
if
(
theLength
>
pos
+
len
)
{
if
(
theNewPartFlag
)
{
// must flush insert to guarantee read
DBG
(
"force execute"
);
if
(
theNdbCon
->
executeNoBlobs
(
NoCommit
)
==
-
1
)
{
setErrorCode
(
theNdbOp
);
// flush writes to guarantee correct read
DBG
(
"execute pending part writes"
);
if
(
executePendingBlobWrites
()
==
-
1
)
return
-
1
;
}
theNewPartFlag
=
false
;
}
if
(
readParts
(
thePartBuf
.
data
,
part
,
1
)
==
-
1
)
return
-
1
;
DBG
(
"force execute"
);
if
(
theNdbCon
->
executeNoBlobs
(
NoCommit
)
==
-
1
)
{
setErrorCode
(
theNdbOp
);
// need result now
DBG
(
"execute pending part reads"
);
if
(
executePendingBlobReads
()
==
-
1
)
return
-
1
;
}
memcpy
(
thePartBuf
.
data
,
buf
,
len
);
if
(
updateParts
(
thePartBuf
.
data
,
part
,
1
)
==
-
1
)
return
-
1
;
...
...
@@ -859,6 +875,8 @@ NdbBlob::readParts(char* buf, Uint32 part, Uint32 count)
}
buf
+=
thePartSize
;
n
++
;
thePendingBlobOps
|=
(
1
<<
NdbOperation
::
ReadRequest
);
theNdbCon
->
thePendingBlobOps
|=
(
1
<<
NdbOperation
::
ReadRequest
);
}
return
0
;
}
...
...
@@ -879,7 +897,8 @@ NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count)
}
buf
+=
thePartSize
;
n
++
;
theNewPartFlag
=
true
;
thePendingBlobOps
|=
(
1
<<
NdbOperation
::
InsertRequest
);
theNdbCon
->
thePendingBlobOps
|=
(
1
<<
NdbOperation
::
InsertRequest
);
}
return
0
;
}
...
...
@@ -900,7 +919,8 @@ NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count)
}
buf
+=
thePartSize
;
n
++
;
theNewPartFlag
=
true
;
thePendingBlobOps
|=
(
1
<<
NdbOperation
::
UpdateRequest
);
theNdbCon
->
thePendingBlobOps
|=
(
1
<<
NdbOperation
::
UpdateRequest
);
}
return
0
;
}
...
...
@@ -919,6 +939,52 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count)
return
-
1
;
}
n
++
;
thePendingBlobOps
|=
(
1
<<
NdbOperation
::
DeleteRequest
);
theNdbCon
->
thePendingBlobOps
|=
(
1
<<
NdbOperation
::
DeleteRequest
);
}
return
0
;
}
// pending ops
int
NdbBlob
::
executePendingBlobReads
()
{
Uint8
flags
=
(
1
<<
NdbOperation
::
ReadRequest
);
if
(
thePendingBlobOps
&
flags
)
{
if
(
theNdbCon
->
executeNoBlobs
(
NoCommit
)
==
-
1
)
return
-
1
;
thePendingBlobOps
=
0
;
theNdbCon
->
thePendingBlobOps
=
0
;
}
return
0
;
}
int
NdbBlob
::
executePendingBlobWrites
()
{
Uint8
flags
=
0xFF
&
~
(
1
<<
NdbOperation
::
ReadRequest
);
if
(
thePendingBlobOps
&
flags
)
{
if
(
theNdbCon
->
executeNoBlobs
(
NoCommit
)
==
-
1
)
return
-
1
;
thePendingBlobOps
=
0
;
theNdbCon
->
thePendingBlobOps
=
0
;
}
return
0
;
}
// callbacks
int
NdbBlob
::
invokeActiveHook
()
{
DBG
(
"invokeActiveHook"
);
assert
(
theState
==
Active
&&
theActiveHook
!=
NULL
);
int
ret
=
(
*
theActiveHook
)(
this
,
theActiveHookArg
);
DBG
(
"invokeActiveHook ret="
<<
ret
);
if
(
ret
!=
0
)
{
// no error is set on blob level
return
-
1
;
}
return
0
;
}
...
...
@@ -948,7 +1014,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
partType
=
NdbDictionary
::
Column
::
Binary
;
theFillChar
=
0x0
;
break
;
case
NdbDictionary
:
:
Column
::
Clob
:
case
NdbDictionary
:
:
Column
::
Text
:
partType
=
NdbDictionary
::
Column
::
Char
;
theFillChar
=
0x20
;
break
;
...
...
@@ -960,16 +1026,14 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
theInlineSize
=
theColumn
->
getInlineSize
();
thePartSize
=
theColumn
->
getPartSize
();
theStripeSize
=
theColumn
->
getStripeSize
();
//
blob table
sanity check
// sanity check
assert
((
NDB_BLOB_HEAD_SIZE
<<
2
)
==
sizeof
(
Head
));
assert
(
theColumn
->
m_attrSize
*
theColumn
->
m_arraySize
==
sizeof
(
Head
)
+
theInlineSize
);
getBlobTableName
(
theBlobTableName
,
theTable
,
theColumn
);
const
NdbDictionary
::
Table
*
bt
;
const
NdbDictionary
::
Column
*
bc
;
if
(
theInlineSize
>=
(
1
<<
16
)
||
thePartSize
==
0
||
thePartSize
>=
(
1
<<
16
)
||
theStripeSize
==
0
||
if
(
thePartSize
>
0
)
{
if
(
theStripeSize
==
0
||
(
bt
=
theNdb
->
theDictionary
->
getTable
(
theBlobTableName
))
==
NULL
||
(
bc
=
bt
->
getColumn
(
"DATA"
))
==
NULL
||
bc
->
getType
()
!=
partType
||
...
...
@@ -977,6 +1041,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
setErrorCode
(
ErrTable
);
return
-
1
;
}
}
// buffers
theKeyBuf
.
alloc
(
theTable
->
m_sizeOfKeysInWords
<<
2
);
theAccessKeyBuf
.
alloc
(
theAccessTable
->
m_sizeOfKeysInWords
<<
2
);
...
...
@@ -1061,7 +1126,7 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
Uint32
bytes
=
theGetSetBytes
-
theInlineSize
;
if
(
writeDataPrivate
(
pos
,
buf
,
bytes
)
==
-
1
)
return
-
1
;
if
(
anExecType
==
Commit
&&
theHeadInlineUpdateFlag
)
{
if
(
theHeadInlineUpdateFlag
)
{
// add an operation to update head+inline
NdbOperation
*
tOp
=
theNdbCon
->
getNdbOperation
(
theTable
);
if
(
tOp
==
NULL
||
...
...
@@ -1129,6 +1194,10 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
batch
=
true
;
}
}
if
(
theActiveHook
!=
NULL
)
{
// need blob head for callback
batch
=
true
;
}
DBG
(
"preExecute out batch="
<<
batch
);
return
0
;
}
...
...
@@ -1145,8 +1214,11 @@ NdbBlob::postExecute(ExecType anExecType)
DBG
(
"postExecute type="
<<
anExecType
);
if
(
theState
==
Invalid
)
return
-
1
;
if
(
theState
==
Active
)
if
(
theState
==
Active
)
{
setState
(
anExecType
==
NoCommit
?
Active
:
Closed
);
DBG
(
"postExecute skip"
);
return
0
;
}
assert
(
theState
==
Prepared
);
assert
(
isKeyOp
());
if
(
isIndexOp
())
{
...
...
@@ -1200,8 +1272,12 @@ NdbBlob::postExecute(ExecType anExecType)
if
(
deleteParts
(
0
,
getPartCount
())
==
-
1
)
return
-
1
;
}
theNewPartFlag
=
false
;
setState
(
anExecType
==
NoCommit
?
Active
:
Closed
);
// activation callback
if
(
theActiveHook
!=
NULL
)
{
if
(
invokeActiveHook
()
==
-
1
)
return
-
1
;
}
DBG
(
"postExecute out"
);
return
0
;
}
...
...
@@ -1275,20 +1351,18 @@ NdbBlob::atNextResult()
Uint32
bytes
=
theGetSetBytes
-
theInlineSize
;
if
(
readDataPrivate
(
pos
,
buf
,
bytes
)
==
-
1
)
return
-
1
;
// must also execute them
DBG
(
"force execute"
);
if
(
theNdbCon
->
executeNoBlobs
(
NoCommit
)
==
-
1
)
{
setErrorCode
((
NdbOperation
*
)
0
);
return
-
1
;
}
}
}
setState
(
Active
);
// activation callback
if
(
theActiveHook
!=
NULL
)
{
if
(
invokeActiveHook
()
==
-
1
)
return
-
1
;
}
DBG
(
"atNextResult out"
);
return
0
;
}
// misc
const
NdbDictionary
::
Column
*
...
...
@@ -1304,6 +1378,9 @@ NdbBlob::setErrorCode(int anErrorCode, bool invalidFlag)
{
DBG
(
"setErrorCode code="
<<
anErrorCode
);
theError
.
code
=
anErrorCode
;
// conditionally copy error to operation level
if
(
theNdbOp
!=
NULL
&&
theNdbOp
->
theError
.
code
==
0
)
theNdbOp
->
setErrorCode
(
theError
.
code
);
if
(
invalidFlag
)
setState
(
Invalid
);
}
...
...
@@ -1336,11 +1413,34 @@ NdbBlob::setErrorCode(NdbConnection* aCon, bool invalidFlag)
setErrorCode
(
code
,
invalidFlag
);
}
// info about all blobs in this operation
NdbBlob
*
NdbBlob
::
blobsFirstBlob
()
{
return
theNdbOp
->
theBlobList
;
}
NdbBlob
*
NdbBlob
::
blobsNextBlob
()
{
return
theNext
;
}
// debug
#ifdef VM_TRACE
inline
int
NdbBlob
::
getOperationType
()
const
{
return
theNdbOp
!=
NULL
?
theNdbOp
->
theOperationType
:
-
1
;
}
NdbOut
&
operator
<<
(
NdbOut
&
out
,
const
NdbBlob
&
blob
)
{
ndbout
<<
dec
<<
"s="
<<
blob
.
theState
;
ndbout
<<
dec
<<
"o="
<<
blob
.
getOperationType
();
ndbout
<<
dec
<<
" s="
<<
blob
.
theState
;
ndbout
<<
dec
<<
" n="
<<
blob
.
theNullFlag
;;
ndbout
<<
dec
<<
" l="
<<
blob
.
theLength
;
ndbout
<<
dec
<<
" p="
<<
blob
.
thePos
;
...
...
ndb/src/ndbapi/NdbConnection.cpp
View file @
e38792a6
...
...
@@ -89,7 +89,8 @@ NdbConnection::NdbConnection( Ndb* aNdb ) :
// Scan operations
theScanningOp
(
NULL
),
theBuddyConPtr
(
0xFFFFFFFF
),
theBlobFlag
(
false
)
theBlobFlag
(
false
),
thePendingBlobOps
(
0
)
{
theListState
=
NotInList
;
theError
.
code
=
0
;
...
...
@@ -150,6 +151,7 @@ NdbConnection::init()
theBuddyConPtr
=
0xFFFFFFFF
;
//
theBlobFlag
=
false
;
thePendingBlobOps
=
0
;
}
//NdbConnection::init()
/*****************************************************************************
...
...
@@ -269,20 +271,27 @@ NdbConnection::execute(ExecType aTypeOfExec,
if
(
!
theBlobFlag
)
return
executeNoBlobs
(
aTypeOfExec
,
abortOption
,
forceSend
);
// execute prepared ops in batches, as requested by blobs
/*
* execute prepared ops in batches, as requested by blobs
* - blob error does not terminate execution
* - blob error sets error on operation
* - if error on operation skip blob calls
*/
ExecType
tExecType
;
NdbOperation
*
tPrepOp
;
int
ret
=
0
;
do
{
tExecType
=
aTypeOfExec
;
tPrepOp
=
theFirstOpInList
;
while
(
tPrepOp
!=
NULL
)
{
if
(
tPrepOp
->
theError
.
code
==
0
)
{
bool
batch
=
false
;
NdbBlob
*
tBlob
=
tPrepOp
->
theBlobList
;
while
(
tBlob
!=
NULL
)
{
if
(
tBlob
->
preExecute
(
tExecType
,
batch
)
==
-
1
)
return
-
1
;
ret
=
-
1
;
tBlob
=
tBlob
->
theNext
;
}
if
(
batch
)
{
...
...
@@ -290,6 +299,7 @@ NdbConnection::execute(ExecType aTypeOfExec,
tExecType
=
NoCommit
;
break
;
}
}
tPrepOp
=
tPrepOp
->
next
();
}
// save rest of prepared ops if batch
...
...
@@ -304,27 +314,31 @@ NdbConnection::execute(ExecType aTypeOfExec,
if
(
tExecType
==
Commit
)
{
NdbOperation
*
tOp
=
theCompletedFirstOp
;
while
(
tOp
!=
NULL
)
{
if
(
tOp
->
theError
.
code
==
0
)
{
NdbBlob
*
tBlob
=
tOp
->
theBlobList
;
while
(
tBlob
!=
NULL
)
{
if
(
tBlob
->
preCommit
()
==
-
1
)
return
-
1
;
ret
=
-
1
;
tBlob
=
tBlob
->
theNext
;
}
}
tOp
=
tOp
->
next
();
}
}
if
(
executeNoBlobs
(
tExecType
,
abortOption
,
forceSend
)
==
-
1
)
ret
urn
-
1
;
ret
=
-
1
;
{
NdbOperation
*
tOp
=
theCompletedFirstOp
;
while
(
tOp
!=
NULL
)
{
if
(
tOp
->
theError
.
code
==
0
)
{
NdbBlob
*
tBlob
=
tOp
->
theBlobList
;
while
(
tBlob
!=
NULL
)
{
// may add new operations if batch
if
(
tBlob
->
postExecute
(
tExecType
)
==
-
1
)
return
-
1
;
ret
=
-
1
;
tBlob
=
tBlob
->
theNext
;
}
}
tOp
=
tOp
->
next
();
}
}
...
...
@@ -338,7 +352,7 @@ NdbConnection::execute(ExecType aTypeOfExec,
}
}
while
(
theFirstOpInList
!=
NULL
||
tExecType
!=
aTypeOfExec
);
return
0
;
return
ret
;
}
int
...
...
@@ -397,6 +411,7 @@ NdbConnection::executeNoBlobs(ExecType aTypeOfExec,
break
;
}
}
thePendingBlobOps
=
0
;
return
0
;
}
//NdbConnection::execute()
...
...
ndb/src/ndbapi/NdbDictionary.cpp
View file @
e38792a6
...
...
@@ -806,73 +806,90 @@ NdbDictionary::Dictionary::getNdbError() const {
return
m_impl
.
getNdbError
();
}
NdbOut
&
operator
<<
(
NdbOut
&
ndbout
,
const
NdbDictionary
::
Column
::
Type
type
)
// printers
NdbOut
&
operator
<<
(
NdbOut
&
out
,
const
NdbDictionary
::
Column
&
col
)
{
switch
(
type
){
case
NdbDictionary
:
:
Column
::
Bigunsigned
:
ndbout
<<
"Bigunsigned"
;
out
<<
col
.
getName
()
<<
" "
;
switch
(
col
.
getType
())
{
case
NdbDictionary
:
:
Column
::
Tinyint
:
out
<<
"Tinyint"
;
break
;
case
NdbDictionary
:
:
Column
::
Unsigned
:
ndbout
<<
"Unsigned"
;
case
NdbDictionary
:
:
Column
::
Tinyunsigned
:
out
<<
"Tinyunsigned"
;
break
;
case
NdbDictionary
:
:
Column
::
Smallint
:
out
<<
"Smallint"
;
break
;
case
NdbDictionary
:
:
Column
::
Smallunsigned
:
ndb
out
<<
"Smallunsigned"
;
out
<<
"Smallunsigned"
;
break
;
case
NdbDictionary
:
:
Column
::
Tinyunsigned
:
ndbout
<<
"Tinyunsigned
"
;
case
NdbDictionary
:
:
Column
::
Mediumint
:
out
<<
"Mediumint
"
;
break
;
case
NdbDictionary
:
:
Column
::
Bigint
:
ndbout
<<
"Bigint
"
;
case
NdbDictionary
:
:
Column
::
Mediumunsigned
:
out
<<
"Mediumunsigned
"
;
break
;
case
NdbDictionary
:
:
Column
::
Int
:
ndb
out
<<
"Int"
;
out
<<
"Int"
;
break
;
case
NdbDictionary
:
:
Column
::
Smallint
:
ndbout
<<
"Smallint"
;
break
;
case
NdbDictionary
:
:
Column
::
Tinyint
:
ndbout
<<
"Tinyint"
;
case
NdbDictionary
:
:
Column
::
Unsigned
:
out
<<
"Unsigned"
;
break
;
case
NdbDictionary
:
:
Column
::
Char
:
ndbout
<<
"Char
"
;
case
NdbDictionary
:
:
Column
::
Bigint
:
out
<<
"Bigint
"
;
break
;
case
NdbDictionary
:
:
Column
::
Varchar
:
ndbout
<<
"Varchar
"
;
case
NdbDictionary
:
:
Column
::
Bigunsigned
:
out
<<
"Bigunsigned
"
;
break
;
case
NdbDictionary
:
:
Column
::
Float
:
ndb
out
<<
"Float"
;
out
<<
"Float"
;
break
;
case
NdbDictionary
:
:
Column
::
Double
:
ndb
out
<<
"Double"
;
out
<<
"Double"
;
break
;
case
NdbDictionary
:
:
Column
::
Mediumint
:
ndbout
<<
"Mediumint
"
;
case
NdbDictionary
:
:
Column
::
Decimal
:
out
<<
"Decimal("
<<
col
.
getScale
()
<<
","
<<
col
.
getPrecision
()
<<
")
"
;
break
;
case
NdbDictionary
:
:
Column
::
Mediumunsigned
:
ndbout
<<
"Mediumunsigend"
;
case
NdbDictionary
:
:
Column
::
Char
:
out
<<
"Char("
<<
col
.
getLength
()
<<
")"
;
break
;
case
NdbDictionary
:
:
Column
::
Varchar
:
out
<<
"Varchar("
<<
col
.
getLength
()
<<
")"
;
break
;
case
NdbDictionary
:
:
Column
::
Binary
:
ndbout
<<
"Binary
"
;
out
<<
"Binary("
<<
col
.
getLength
()
<<
")
"
;
break
;
case
NdbDictionary
:
:
Column
::
Varbinary
:
ndbout
<<
"Varbinary
"
;
out
<<
"Varbinary("
<<
col
.
getLength
()
<<
")
"
;
break
;
case
NdbDictionary
:
:
Column
::
D
ecimal
:
ndbout
<<
"Decimal
"
;
case
NdbDictionary
:
:
Column
::
D
atetime
:
out
<<
"Datetime
"
;
break
;
case
NdbDictionary
:
:
Column
::
Timespec
:
ndb
out
<<
"Timespec"
;
out
<<
"Timespec"
;
break
;
case
NdbDictionary
:
:
Column
::
Blob
:
ndbout
<<
"Blob"
;
out
<<
"Blob("
<<
col
.
getInlineSize
()
<<
","
<<
col
.
getPartSize
()
<<
";"
<<
col
.
getStripeSize
()
<<
")"
;
break
;
case
NdbDictionary
:
:
Column
::
Text
:
out
<<
"Text("
<<
col
.
getInlineSize
()
<<
","
<<
col
.
getPartSize
()
<<
";"
<<
col
.
getStripeSize
()
<<
")"
;
break
;
case
NdbDictionary
:
:
Column
::
Undefined
:
ndb
out
<<
"Undefined"
;
out
<<
"Undefined"
;
break
;
default:
ndbout
<<
"Unknown type="
<<
(
Uint32
)
type
;
out
<<
"Type"
<<
(
Uint32
)
col
.
getType
()
;
break
;
}
return
ndbout
;
if
(
col
.
getPrimaryKey
())
out
<<
" PRIMARY KEY"
;
else
if
(
!
col
.
getNullable
())
out
<<
" NOT NULL"
;
else
out
<<
" NULL"
;
return
out
;
}
ndb/src/ndbapi/NdbDictionaryImpl.cpp
View file @
e38792a6
...
...
@@ -181,7 +181,7 @@ NdbColumnImpl::equal(const NdbColumnImpl& col) const
case
NdbDictionary
:
:
Column
::
Timespec
:
break
;
case
NdbDictionary
:
:
Column
::
Blob
:
case
NdbDictionary
:
:
Column
::
Clob
:
case
NdbDictionary
:
:
Column
::
Text
:
if
(
m_precision
!=
col
.
m_precision
||
m_scale
!=
col
.
m_scale
||
m_length
!=
col
.
m_length
)
{
...
...
@@ -1088,7 +1088,7 @@ columnTypeMapping[] = {
{
DictTabInfo
::
ExtDatetime
,
NdbDictionary
::
Column
::
Datetime
},
{
DictTabInfo
::
ExtTimespec
,
NdbDictionary
::
Column
::
Timespec
},
{
DictTabInfo
::
ExtBlob
,
NdbDictionary
::
Column
::
Blob
},
{
DictTabInfo
::
Ext
Clob
,
NdbDictionary
::
Column
::
Clob
},
{
DictTabInfo
::
Ext
Text
,
NdbDictionary
::
Column
::
Text
},
{
-
1
,
-
1
}
};
...
...
@@ -1253,7 +1253,7 @@ NdbDictionaryImpl::createBlobTables(NdbTableImpl &t)
{
for
(
unsigned
i
=
0
;
i
<
t
.
m_columns
.
size
();
i
++
)
{
NdbColumnImpl
&
c
=
*
t
.
m_columns
[
i
];
if
(
!
c
.
getBlobType
())
if
(
!
c
.
getBlobType
()
||
c
.
getPartSize
()
==
0
)
continue
;
NdbTableImpl
bt
;
NdbBlob
::
getBlobTable
(
bt
,
&
t
,
&
c
);
...
...
@@ -1622,7 +1622,7 @@ NdbDictionaryImpl::dropBlobTables(NdbTableImpl & t)
{
for
(
unsigned
i
=
0
;
i
<
t
.
m_columns
.
size
();
i
++
)
{
NdbColumnImpl
&
c
=
*
t
.
m_columns
[
i
];
if
(
!
c
.
getBlobType
())
if
(
!
c
.
getBlobType
()
||
c
.
getPartSize
()
==
0
)
continue
;
char
btname
[
NdbBlob
::
BlobTableNameSize
];
NdbBlob
::
getBlobTableName
(
btname
,
&
t
,
&
c
);
...
...
ndb/src/ndbapi/NdbDictionaryImpl.hpp
View file @
e38792a6
...
...
@@ -441,7 +441,7 @@ inline
bool
NdbColumnImpl
::
getBlobType
()
const
{
return
(
m_type
==
NdbDictionary
::
Column
::
Blob
||
m_type
==
NdbDictionary
::
Column
::
Clob
);
m_type
==
NdbDictionary
::
Column
::
Text
);
}
inline
...
...
ndb/src/ndbapi/NdbRecAttr.cpp
View file @
e38792a6
...
...
@@ -29,6 +29,7 @@ Adjust: 971206 UABRONM First version
#include <ndb_global.h>
#include <NdbOut.hpp>
#include <NdbRecAttr.hpp>
#include <NdbBlob.hpp>
#include "NdbDictionaryImpl.hpp"
#include <NdbTCP.h>
...
...
@@ -147,78 +148,100 @@ NdbRecAttr::receive_data(const Uint32 * data, Uint32 sz){
return
false
;
}
NdbOut
&
operator
<<
(
NdbOut
&
ndb
out
,
const
NdbRecAttr
&
r
)
NdbOut
&
operator
<<
(
NdbOut
&
out
,
const
NdbRecAttr
&
r
)
{
if
(
r
.
isNULL
())
{
ndb
out
<<
"[NULL]"
;
return
ndb
out
;
out
<<
"[NULL]"
;
return
out
;
}
if
(
r
.
arraySize
()
>
1
)
ndb
out
<<
"["
;
out
<<
"["
;
for
(
Uint32
j
=
0
;
j
<
r
.
arraySize
();
j
++
)
{
if
(
j
>
0
)
ndb
out
<<
" "
;
out
<<
" "
;
switch
(
r
.
getType
())
{
case
NdbDictionary
:
:
Column
::
Bigunsigned
:
ndb
out
<<
r
.
u_64_value
();
out
<<
r
.
u_64_value
();
break
;
case
NdbDictionary
:
:
Column
::
Unsigned
:
ndb
out
<<
r
.
u_32_value
();
out
<<
r
.
u_32_value
();
break
;
case
NdbDictionary
:
:
Column
::
Smallunsigned
:
ndb
out
<<
r
.
u_short_value
();
out
<<
r
.
u_short_value
();
break
;
case
NdbDictionary
:
:
Column
::
Tinyunsigned
:
ndb
out
<<
(
unsigned
)
r
.
u_char_value
();
out
<<
(
unsigned
)
r
.
u_char_value
();
break
;
case
NdbDictionary
:
:
Column
::
Bigint
:
ndb
out
<<
r
.
int64_value
();
out
<<
r
.
int64_value
();
break
;
case
NdbDictionary
:
:
Column
::
Int
:
ndb
out
<<
r
.
int32_value
();
out
<<
r
.
int32_value
();
break
;
case
NdbDictionary
:
:
Column
::
Smallint
:
ndb
out
<<
r
.
short_value
();
out
<<
r
.
short_value
();
break
;
case
NdbDictionary
:
:
Column
::
Tinyint
:
ndb
out
<<
(
int
)
r
.
char_value
();
out
<<
(
int
)
r
.
char_value
();
break
;
case
NdbDictionary
:
:
Column
::
Char
:
ndb
out
.
print
(
"%.*s"
,
r
.
arraySize
(),
r
.
aRef
());
out
.
print
(
"%.*s"
,
r
.
arraySize
(),
r
.
aRef
());
j
=
r
.
arraySize
();
break
;
case
NdbDictionary
:
:
Column
::
Varchar
:
{
short
len
=
ntohs
(
r
.
u_short_value
());
ndb
out
.
print
(
"%.*s"
,
len
,
r
.
aRef
()
+
2
);
out
.
print
(
"%.*s"
,
len
,
r
.
aRef
()
+
2
);
}
j
=
r
.
arraySize
();
break
;
case
NdbDictionary
:
:
Column
::
Float
:
ndb
out
<<
r
.
float_value
();
out
<<
r
.
float_value
();
break
;
case
NdbDictionary
:
:
Column
::
Double
:
ndbout
<<
r
.
double_value
();
out
<<
r
.
double_value
();
break
;
case
NdbDictionary
:
:
Column
::
Blob
:
{
const
NdbBlob
::
Head
*
h
=
(
const
NdbBlob
::
Head
*
)
r
.
aRef
();
out
<<
h
->
length
<<
":"
;
const
unsigned
char
*
p
=
(
const
unsigned
char
*
)(
h
+
1
);
unsigned
n
=
r
.
arraySize
()
-
sizeof
(
*
h
);
for
(
unsigned
k
=
0
;
k
<
n
&&
k
<
h
->
length
;
k
++
)
out
.
print
(
"%02X"
,
(
int
)
p
[
k
]);
j
=
r
.
arraySize
();
}
break
;
case
NdbDictionary
:
:
Column
::
Text
:
{
const
NdbBlob
::
Head
*
h
=
(
const
NdbBlob
::
Head
*
)
r
.
aRef
();
out
<<
h
->
length
<<
":"
;
const
unsigned
char
*
p
=
(
const
unsigned
char
*
)(
h
+
1
);
unsigned
n
=
r
.
arraySize
()
-
sizeof
(
*
h
);
for
(
unsigned
k
=
0
;
k
<
n
&&
k
<
h
->
length
;
k
++
)
out
.
print
(
"%c"
,
(
int
)
p
[
k
]);
j
=
r
.
arraySize
();
}
break
;
default:
/* no print functions for the rest, just print type */
ndb
out
<<
r
.
getType
();
out
<<
r
.
getType
();
j
=
r
.
arraySize
();
if
(
j
>
1
)
ndbout
<<
" %u times"
<<
j
;
out
<<
" "
<<
j
<<
" times"
;
break
;
}
}
if
(
r
.
arraySize
()
>
1
)
{
ndb
out
<<
"]"
;
out
<<
"]"
;
}
return
ndb
out
;
return
out
;
}
ndb/src/ndbapi/NdbResultSet.cpp
View file @
e38792a6
...
...
@@ -55,6 +55,13 @@ int NdbResultSet::nextResult(bool fetchAllowed)
return
-
1
;
tBlob
=
tBlob
->
theNext
;
}
/*
* Flush blob part ops on behalf of user because
* - nextResult is analogous to execute(NoCommit)
* - user is likely to want blob value before next execute
*/
if
(
m_operation
->
m_transConnection
->
executePendingBlobOps
()
==
-
1
)
return
-
1
;
return
0
;
}
return
res
;
...
...
ndb/test/include/NDBT_Table.hpp
View file @
e38792a6
...
...
@@ -23,7 +23,6 @@
#include <NdbOut.hpp>
class
NDBT_Attribute
:
public
NdbDictionary
::
Column
{
friend
class
NdbOut
&
operator
<<
(
class
NdbOut
&
,
const
NDBT_Attribute
&
);
public:
NDBT_Attribute
(
const
char
*
_name
,
Column
::
Type
_type
,
...
...
ndb/test/ndbapi/testBlobs.cpp
View file @
e38792a6
...
...
@@ -38,6 +38,7 @@ struct Bcol {
};
struct
Opt
{
unsigned
m_batch
;
bool
m_core
;
bool
m_dbg
;
bool
m_dbgall
;
...
...
@@ -46,7 +47,8 @@ struct Opt {
unsigned
m_parts
;
unsigned
m_rows
;
unsigned
m_seed
;
char
m_skip
[
255
];
const
char
*
m_skip
;
const
char
*
m_style
;
// metadata
const
char
*
m_tname
;
const
char
*
m_x1name
;
// hash index
...
...
@@ -60,6 +62,7 @@ struct Opt {
int
m_bug
;
int
(
*
m_bugtest
)();
Opt
()
:
m_batch
(
7
),
m_core
(
false
),
m_dbg
(
false
),
m_dbgall
(
false
),
...
...
@@ -68,6 +71,8 @@ struct Opt {
m_parts
(
10
),
m_rows
(
100
),
m_seed
(
0
),
m_skip
(
""
),
m_style
(
"012"
),
// metadata
m_tname
(
"TBLOB1"
),
m_x1name
(
"TBLOB1X1"
),
...
...
@@ -80,7 +85,6 @@ struct Opt {
// bugs
m_bug
(
0
),
m_bugtest
(
0
)
{
memset
(
m_skip
,
false
,
sizeof
(
m_skip
));
}
};
...
...
@@ -92,6 +96,7 @@ printusage()
Opt
d
;
ndbout
<<
"usage: testBlobs options [default/max]"
<<
endl
<<
" -batch N number of pk ops in batch ["
<<
d
.
m_batch
<<
"]"
<<
endl
<<
" -core dump core on error"
<<
endl
<<
" -dbg print debug"
<<
endl
<<
" -dbgall print also NDB API debug (if compiled in)"
<<
endl
...
...
@@ -101,7 +106,8 @@ printusage()
<<
" -parts N max parts in blob value ["
<<
d
.
m_parts
<<
"]"
<<
endl
<<
" -rows N number of rows ["
<<
d
.
m_rows
<<
"]"
<<
endl
<<
" -seed N random seed 0=loop number ["
<<
d
.
m_seed
<<
"]"
<<
endl
<<
" -skip xxx skip these tests (see list)"
<<
endl
<<
" -skip xxx skip these tests (see list) ["
<<
d
.
m_skip
<<
endl
<<
" -style xxx access styles to test (see list) ["
<<
d
.
m_style
<<
"]"
<<
endl
<<
"metadata"
<<
endl
<<
" -pk2len N length of PK2 ["
<<
d
.
m_pk2len
<<
"/"
<<
g_max_pk2len
<<
"]"
<<
endl
<<
" -oneblob only 1 blob attribute [default 2]"
<<
endl
...
...
@@ -111,8 +117,10 @@ printusage()
<<
" s table scans"
<<
endl
<<
" r ordered index scans"
<<
endl
<<
" u update blob value"
<<
endl
<<
" v getValue / setValue"
<<
endl
<<
" w readData / writeData"
<<
endl
<<
"access styles for -style"
<<
endl
<<
" 0 getValue / setValue"
<<
endl
<<
" 1 setActiveHook"
<<
endl
<<
" 2 readData / writeData"
<<
endl
<<
"bug tests (no blob test)"
<<
endl
<<
" -bug 4088 ndb api hang with mixed ops on index table"
<<
endl
<<
" -bug 2222 delete + write gives 626"
<<
endl
...
...
@@ -122,11 +130,16 @@ printusage()
static
Opt
g_opt
;
static
char
&
skip
(
unsigned
x
)
static
bool
skip
case
(
int
x
)
{
assert
(
x
<
sizeof
(
g_opt
.
m_skip
));
return
g_opt
.
m_skip
[
x
];
return
strchr
(
g_opt
.
m_skip
,
x
)
!=
0
;
}
static
bool
skipstyle
(
int
x
)
{
return
strchr
(
g_opt
.
m_style
,
'0'
+
x
)
==
0
;
}
static
Ndb
*
g_ndb
=
0
;
...
...
@@ -138,11 +151,12 @@ static NdbScanOperation* g_ops = 0;
static
NdbBlob
*
g_bh1
=
0
;
static
NdbBlob
*
g_bh2
=
0
;
static
bool
g_printerror
=
true
;
static
unsigned
g_loop
=
0
;
static
void
printerror
(
int
line
,
const
char
*
msg
)
{
ndbout
<<
"line "
<<
line
<<
"
: "
<<
msg
<<
" failed"
<<
endl
;
ndbout
<<
"line "
<<
line
<<
"
FAIL "
<<
msg
<<
endl
;
if
(
!
g_printerror
)
{
return
;
}
...
...
@@ -205,6 +219,7 @@ static int
createTable
()
{
NdbDictionary
::
Table
tab
(
g_opt
.
m_tname
);
tab
.
setLogging
(
false
);
// col PK1 - Uint32
{
NdbDictionary
::
Column
col
(
"PK1"
);
col
.
setType
(
NdbDictionary
::
Column
::
Unsigned
);
...
...
@@ -228,11 +243,11 @@ createTable()
col
.
setPrimaryKey
(
true
);
tab
.
addColumn
(
col
);
}
// col BL2 -
Clob
nullable
// col BL2 -
Text
nullable
if
(
!
g_opt
.
m_oneblob
)
{
NdbDictionary
::
Column
col
(
"BL2"
);
const
Bcol
&
b
=
g_opt
.
m_blob2
;
col
.
setType
(
NdbDictionary
::
Column
::
Clob
);
col
.
setType
(
NdbDictionary
::
Column
::
Text
);
col
.
setNullable
(
true
);
col
.
setInlineSize
(
b
.
m_inline
);
col
.
setPartSize
(
b
.
m_partsize
);
...
...
@@ -245,6 +260,7 @@ createTable()
if
(
g_opt
.
m_pk2len
!=
0
)
{
NdbDictionary
::
Index
idx
(
g_opt
.
m_x1name
);
idx
.
setType
(
NdbDictionary
::
Index
::
UniqueHashIndex
);
idx
.
setLogging
(
false
);
idx
.
setTable
(
g_opt
.
m_tname
);
idx
.
addColumnName
(
"PK2"
);
CHK
(
g_dic
->
createIndex
(
idx
)
==
0
);
...
...
@@ -281,7 +297,7 @@ struct Bval {
m_buf
=
new
char
[
m_buflen
];
trash
();
}
void
copy
(
const
Bval
&
v
)
{
void
copy
from
(
const
Bval
&
v
)
{
m_len
=
v
.
m_len
;
delete
[]
m_val
;
if
(
v
.
m_val
==
0
)
...
...
@@ -313,10 +329,10 @@ struct Tup {
m_blob1
.
alloc
(
g_opt
.
m_blob1
.
m_inline
+
g_opt
.
m_blob1
.
m_partsize
*
g_opt
.
m_parts
);
m_blob2
.
alloc
(
g_opt
.
m_blob2
.
m_inline
+
g_opt
.
m_blob2
.
m_partsize
*
g_opt
.
m_parts
);
}
void
copy
(
const
Tup
&
tup
)
{
void
copy
from
(
const
Tup
&
tup
)
{
assert
(
m_pk1
==
tup
.
m_pk1
);
m_blob1
.
copy
(
tup
.
m_blob1
);
m_blob2
.
copy
(
tup
.
m_blob2
);
m_blob1
.
copy
from
(
tup
.
m_blob1
);
m_blob2
.
copy
from
(
tup
.
m_blob2
);
}
private:
Tup
(
const
Tup
&
);
...
...
@@ -357,6 +373,14 @@ calcBval(const Bcol& b, Bval& v, bool keepsize)
v
.
trash
();
}
static
void
calcBval
(
Tup
&
tup
,
bool
keepsize
)
{
calcBval
(
g_opt
.
m_blob1
,
tup
.
m_blob1
,
keepsize
);
if
(
!
g_opt
.
m_oneblob
)
calcBval
(
g_opt
.
m_blob2
,
tup
.
m_blob2
,
keepsize
);
}
static
void
calcTups
(
bool
keepsize
)
{
...
...
@@ -371,14 +395,39 @@ calcTups(bool keepsize)
tup
.
m_pk2
[
i
]
=
'a'
+
i
%
26
;
}
}
calcBval
(
g_opt
.
m_blob1
,
tup
.
m_blob1
,
keepsize
);
if
(
!
g_opt
.
m_oneblob
)
calcBval
(
g_opt
.
m_blob2
,
tup
.
m_blob2
,
keepsize
);
calcBval
(
tup
,
keepsize
);
}
}
// blob handle ops
static
int
getBlobHandles
(
NdbOperation
*
opr
)
{
CHK
((
g_bh1
=
opr
->
getBlobHandle
(
"BL1"
))
!=
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
((
g_bh2
=
opr
->
getBlobHandle
(
"BL2"
))
!=
0
);
return
0
;
}
static
int
getBlobHandles
(
NdbIndexOperation
*
opx
)
{
CHK
((
g_bh1
=
opx
->
getBlobHandle
(
"BL1"
))
!=
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
((
g_bh2
=
opx
->
getBlobHandle
(
"BL2"
))
!=
0
);
return
0
;
}
static
int
getBlobHandles
(
NdbScanOperation
*
ops
)
{
CHK
((
g_bh1
=
ops
->
getBlobHandle
(
"BL1"
))
!=
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
((
g_bh2
=
ops
->
getBlobHandle
(
"BL2"
))
!=
0
);
return
0
;
}
static
int
getBlobLength
(
NdbBlob
*
h
,
unsigned
&
len
)
{
...
...
@@ -386,16 +435,19 @@ getBlobLength(NdbBlob* h, unsigned& len)
CHK
(
h
->
getLength
(
len2
)
==
0
);
len
=
(
unsigned
)
len2
;
assert
(
len
==
len2
);
DBG
(
"getBlobLength "
<<
h
->
getColumn
()
->
getName
()
<<
" len="
<<
len
);
return
0
;
}
// setValue / getValue
static
int
setBlobValue
(
NdbBlob
*
h
,
const
Bval
&
v
)
{
bool
null
=
(
v
.
m_val
==
0
);
bool
isNull
;
unsigned
len
;
DBG
(
"set "
<<
h
->
getColumn
()
->
getName
()
<<
" len="
<<
v
.
m_len
<<
" null="
<<
null
);
DBG
(
"set
Value
"
<<
h
->
getColumn
()
->
getName
()
<<
" len="
<<
v
.
m_len
<<
" null="
<<
null
);
if
(
null
)
{
CHK
(
h
->
setNull
()
==
0
);
isNull
=
false
;
...
...
@@ -409,11 +461,20 @@ setBlobValue(NdbBlob* h, const Bval& v)
return
0
;
}
static
int
setBlobValue
(
const
Tup
&
tup
)
{
CHK
(
setBlobValue
(
g_bh1
,
tup
.
m_blob1
)
==
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
(
setBlobValue
(
g_bh2
,
tup
.
m_blob2
)
==
0
);
return
0
;
}
static
int
getBlobValue
(
NdbBlob
*
h
,
const
Bval
&
v
)
{
bool
null
=
(
v
.
m_val
==
0
);
DBG
(
"get
"
<<
h
->
getColumn
()
->
getName
()
<<
" len="
<<
v
.
m_len
<<
" null="
<<
null
);
DBG
(
"get
Value "
<<
h
->
getColumn
()
->
getName
()
<<
" buflen="
<<
v
.
m_buflen
);
CHK
(
h
->
getValue
(
v
.
m_buf
,
v
.
m_buflen
)
==
0
);
return
0
;
}
...
...
@@ -456,6 +517,8 @@ verifyBlobValue(const Tup& tup)
return
0
;
}
// readData / writeData
static
int
writeBlobData
(
NdbBlob
*
h
,
const
Bval
&
v
)
{
...
...
@@ -469,6 +532,7 @@ writeBlobData(NdbBlob* h, const Bval& v)
CHK
(
h
->
getNull
(
isNull
)
==
0
&&
isNull
==
true
);
CHK
(
getBlobLength
(
h
,
len
)
==
0
&&
len
==
0
);
}
else
{
CHK
(
h
->
truncate
(
v
.
m_len
)
==
0
);
unsigned
n
=
0
;
do
{
unsigned
m
=
g_opt
.
m_full
?
v
.
m_len
:
urandom
(
v
.
m_len
+
1
);
...
...
@@ -486,6 +550,15 @@ writeBlobData(NdbBlob* h, const Bval& v)
return
0
;
}
static
int
writeBlobData
(
const
Tup
&
tup
)
{
CHK
(
writeBlobData
(
g_bh1
,
tup
.
m_blob1
)
==
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
(
writeBlobData
(
g_bh2
,
tup
.
m_blob2
)
==
0
);
return
0
;
}
static
int
readBlobData
(
NdbBlob
*
h
,
const
Bval
&
v
)
{
...
...
@@ -531,6 +604,71 @@ readBlobData(const Tup& tup)
return
0
;
}
// hooks
static
NdbBlob
::
ActiveHook
blobWriteHook
;
static
int
blobWriteHook
(
NdbBlob
*
h
,
void
*
arg
)
{
DBG
(
"blobWriteHook"
);
Bval
&
v
=
*
(
Bval
*
)
arg
;
CHK
(
writeBlobData
(
h
,
v
)
==
0
);
return
0
;
}
static
int
setBlobWriteHook
(
NdbBlob
*
h
,
Bval
&
v
)
{
DBG
(
"setBlobWriteHook"
);
CHK
(
h
->
setActiveHook
(
blobWriteHook
,
&
v
)
==
0
);
return
0
;
}
static
int
setBlobWriteHook
(
Tup
&
tup
)
{
CHK
(
setBlobWriteHook
(
g_bh1
,
tup
.
m_blob1
)
==
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
(
setBlobWriteHook
(
g_bh2
,
tup
.
m_blob2
)
==
0
);
return
0
;
}
static
NdbBlob
::
ActiveHook
blobReadHook
;
// no PK yet to identify tuple so just read the value
static
int
blobReadHook
(
NdbBlob
*
h
,
void
*
arg
)
{
DBG
(
"blobReadHook"
);
Bval
&
v
=
*
(
Bval
*
)
arg
;
unsigned
len
;
CHK
(
getBlobLength
(
h
,
len
)
==
0
);
v
.
alloc
(
len
);
Uint32
maxlen
=
0xffffffff
;
CHK
(
h
->
readData
(
v
.
m_buf
,
maxlen
)
==
0
);
DBG
(
"read "
<<
maxlen
<<
" bytes"
);
CHK
(
len
==
maxlen
);
return
0
;
}
static
int
setBlobReadHook
(
NdbBlob
*
h
,
Bval
&
v
)
{
DBG
(
"setBlobReadHook"
);
CHK
(
h
->
setActiveHook
(
blobReadHook
,
&
v
)
==
0
);
return
0
;
}
static
int
setBlobReadHook
(
Tup
&
tup
)
{
CHK
(
setBlobReadHook
(
g_bh1
,
tup
.
m_blob1
)
==
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
(
setBlobReadHook
(
g_bh2
,
tup
.
m_blob2
)
==
0
);
return
0
;
}
// verify blob data
static
int
...
...
@@ -540,7 +678,11 @@ verifyHeadInline(const Bcol& c, const Bval& v, NdbRecAttr* ra)
CHK
(
ra
->
isNULL
()
==
1
);
}
else
{
CHK
(
ra
->
isNULL
()
==
0
);
CHK
(
ra
->
u_64_value
()
==
v
.
m_len
);
const
NdbBlob
::
Head
*
head
=
(
const
NdbBlob
::
Head
*
)
ra
->
aRef
();
CHK
(
head
->
length
==
v
.
m_len
);
const
char
*
data
=
(
const
char
*
)(
head
+
1
);
for
(
unsigned
i
=
0
;
i
<
head
->
length
&&
i
<
c
.
m_inline
;
i
++
)
CHK
(
data
[
i
]
==
v
.
m_val
[
i
]);
}
return
0
;
}
...
...
@@ -548,7 +690,7 @@ verifyHeadInline(const Bcol& c, const Bval& v, NdbRecAttr* ra)
static
int
verifyHeadInline
(
const
Tup
&
tup
)
{
DBG
(
"verifyHeadInline pk1="
<<
tup
.
m_pk1
);
DBG
(
"verifyHeadInline pk1="
<<
hex
<<
tup
.
m_pk1
);
CHK
((
g_con
=
g_ndb
->
startTransaction
())
!=
0
);
CHK
((
g_opr
=
g_con
->
getNdbOperation
(
g_opt
.
m_tname
))
!=
0
);
CHK
(
g_opr
->
readTuple
()
==
0
);
...
...
@@ -580,7 +722,7 @@ verifyHeadInline(const Tup& tup)
static
int
verifyBlobTable
(
const
Bcol
&
b
,
const
Bval
&
v
,
Uint32
pk1
,
bool
exists
)
{
DBG
(
"verify "
<<
b
.
m_btname
<<
" pk1="
<<
pk1
);
DBG
(
"verify "
<<
b
.
m_btname
<<
" pk1="
<<
hex
<<
pk1
);
NdbRecAttr
*
ra_pk
;
NdbRecAttr
*
ra_part
;
NdbRecAttr
*
ra_data
;
...
...
@@ -640,7 +782,7 @@ verifyBlob()
{
for
(
unsigned
k
=
0
;
k
<
g_opt
.
m_rows
;
k
++
)
{
const
Tup
&
tup
=
g_tups
[
k
];
DBG
(
"verifyBlob pk1="
<<
tup
.
m_pk1
);
DBG
(
"verifyBlob pk1="
<<
hex
<<
tup
.
m_pk1
);
CHK
(
verifyHeadInline
(
tup
)
==
0
);
CHK
(
verifyBlobTable
(
tup
)
==
0
);
}
...
...
@@ -649,105 +791,120 @@ verifyBlob()
// operations
static
const
char
*
stylename
[
3
]
=
{
"style=getValue/setValue"
,
"style=setActiveHook"
,
"style=readData/writeData"
};
// pk ops
static
int
insertPk
(
bool
rw
)
insertPk
(
int
style
)
{
DBG
(
"--- insertPk ---"
);
DBG
(
"--- insertPk "
<<
stylename
[
style
]
<<
" ---"
);
unsigned
n
=
0
;
CHK
((
g_con
=
g_ndb
->
startTransaction
())
!=
0
);
for
(
unsigned
k
=
0
;
k
<
g_opt
.
m_rows
;
k
++
)
{
Tup
&
tup
=
g_tups
[
k
];
DBG
(
"insertPk pk1="
<<
tup
.
m_pk1
);
CHK
((
g_con
=
g_ndb
->
startTransaction
())
!=
0
);
DBG
(
"insertPk pk1="
<<
hex
<<
tup
.
m_pk1
);
CHK
((
g_opr
=
g_con
->
getNdbOperation
(
g_opt
.
m_tname
))
!=
0
);
CHK
(
g_opr
->
insertTuple
()
==
0
);
CHK
(
g_opr
->
equal
(
"PK1"
,
tup
.
m_pk1
)
==
0
);
if
(
g_opt
.
m_pk2len
!=
0
)
CHK
(
g_opr
->
equal
(
"PK2"
,
tup
.
m_pk2
)
==
0
);
CHK
(
(
g_bh1
=
g_opr
->
getBlobHandle
(
"BL1"
))
!
=
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
(
(
g_bh2
=
g_opr
->
getBlobHandle
(
"BL2"
))
!
=
0
);
if
(
!
rw
)
{
CHK
(
setBlobValue
(
g_bh1
,
tup
.
m_blob1
)
==
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
(
setBlobValue
(
g_bh2
,
tup
.
m_blob2
)
==
0
);
CHK
(
getBlobHandles
(
g_opr
)
=
=
0
);
if
(
style
==
0
)
{
CHK
(
setBlobValue
(
tup
)
=
=
0
);
}
else
if
(
style
==
1
)
{
// non-nullable must be set
CHK
(
g_bh1
->
setValue
(
""
,
0
)
==
0
);
CHK
(
setBlobWriteHook
(
tup
)
==
0
);
}
else
{
// non-nullable must be set
CHK
(
g_bh1
->
setValue
(
""
,
0
)
==
0
);
CHK
(
g_con
->
execute
(
NoCommit
)
==
0
);
CHK
(
writeBlobData
(
g_bh1
,
tup
.
m_blob1
)
==
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
(
writeBlobData
(
g_bh2
,
tup
.
m_blob2
)
==
0
);
CHK
(
writeBlobData
(
tup
)
==
0
);
}
// just another trap
if
(
urandom
(
10
)
==
0
)
CHK
(
g_con
->
execute
(
NoCommit
)
==
0
);
if
(
++
n
==
g_opt
.
m_batch
)
{
CHK
(
g_con
->
execute
(
Commit
)
==
0
);
g_ndb
->
closeTransaction
(
g_con
);
CHK
((
g_con
=
g_ndb
->
startTransaction
())
!=
0
);
n
=
0
;
}
g_opr
=
0
;
g_con
=
0
;
tup
.
m_exists
=
true
;
}
if
(
n
!=
0
)
{
CHK
(
g_con
->
execute
(
Commit
)
==
0
);
n
=
0
;
}
g_ndb
->
closeTransaction
(
g_con
);
g_con
=
0
;
return
0
;
}
static
int
updatePk
(
bool
rw
)
readPk
(
int
style
)
{
DBG
(
"---
updatePk
---"
);
DBG
(
"---
readPk "
<<
stylename
[
style
]
<<
"
---"
);
for
(
unsigned
k
=
0
;
k
<
g_opt
.
m_rows
;
k
++
)
{
Tup
&
tup
=
g_tups
[
k
];
DBG
(
"
updatePk pk1="
<<
tup
.
m_pk1
);
DBG
(
"
readPk pk1="
<<
hex
<<
tup
.
m_pk1
);
CHK
((
g_con
=
g_ndb
->
startTransaction
())
!=
0
);
CHK
((
g_opr
=
g_con
->
getNdbOperation
(
g_opt
.
m_tname
))
!=
0
);
CHK
(
g_opr
->
update
Tuple
()
==
0
);
CHK
(
g_opr
->
read
Tuple
()
==
0
);
CHK
(
g_opr
->
equal
(
"PK1"
,
tup
.
m_pk1
)
==
0
);
if
(
g_opt
.
m_pk2len
!=
0
)
CHK
(
g_opr
->
equal
(
"PK2"
,
tup
.
m_pk2
)
==
0
);
CHK
((
g_bh1
=
g_opr
->
getBlobHandle
(
"BL1"
))
!=
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
((
g_bh2
=
g_opr
->
getBlobHandle
(
"BL2"
))
!=
0
);
if
(
!
rw
)
{
CHK
(
setBlobValue
(
g_bh1
,
tup
.
m_blob1
)
==
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
(
setBlobValue
(
g_bh2
,
tup
.
m_blob2
)
==
0
);
CHK
(
getBlobHandles
(
g_opr
)
==
0
);
if
(
style
==
0
)
{
CHK
(
getBlobValue
(
tup
)
==
0
);
}
else
if
(
style
==
1
)
{
CHK
(
setBlobReadHook
(
tup
)
==
0
);
}
else
{
CHK
(
g_con
->
execute
(
NoCommit
)
==
0
);
CHK
(
writeBlobData
(
g_bh1
,
tup
.
m_blob1
)
==
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
(
writeBlobData
(
g_bh2
,
tup
.
m_blob2
)
==
0
);
CHK
(
readBlobData
(
tup
)
==
0
);
}
CHK
(
g_con
->
execute
(
Commit
)
==
0
);
if
(
style
==
0
||
style
==
1
)
{
CHK
(
verifyBlobValue
(
tup
)
==
0
);
}
g_ndb
->
closeTransaction
(
g_con
);
g_opr
=
0
;
g_con
=
0
;
tup
.
m_exists
=
true
;
}
return
0
;
}
static
int
update
Idx
(
bool
rw
)
update
Pk
(
int
style
)
{
DBG
(
"--- update
Idx
---"
);
DBG
(
"--- update
Pk "
<<
stylename
[
style
]
<<
"
---"
);
for
(
unsigned
k
=
0
;
k
<
g_opt
.
m_rows
;
k
++
)
{
Tup
&
tup
=
g_tups
[
k
];
DBG
(
"update
Idx pk1="
<<
tup
.
m_pk1
);
DBG
(
"update
Pk pk1="
<<
hex
<<
tup
.
m_pk1
);
CHK
((
g_con
=
g_ndb
->
startTransaction
())
!=
0
);
CHK
((
g_op
x
=
g_con
->
getNdbIndexOperation
(
g_opt
.
m_x1name
,
g_opt
.
m_tname
))
!=
0
);
CHK
(
g_op
x
->
updateTuple
()
==
0
);
CHK
(
g_op
x
->
equal
(
"PK2"
,
tup
.
m_pk2
)
==
0
);
CHK
((
g_bh1
=
g_opx
->
getBlobHandle
(
"BL1"
))
!=
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
((
g_bh2
=
g_opx
->
getBlobHandle
(
"BL2"
))
!
=
0
);
if
(
!
rw
)
{
CHK
(
setBlobValue
(
g_bh1
,
tup
.
m_blob1
)
==
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
(
setBlobValue
(
g_bh2
,
tup
.
m_blob2
)
==
0
);
CHK
((
g_op
r
=
g_con
->
getNdbOperation
(
g_opt
.
m_tname
))
!=
0
);
CHK
(
g_op
r
->
updateTuple
()
==
0
);
CHK
(
g_op
r
->
equal
(
"PK1"
,
tup
.
m_pk1
)
==
0
);
if
(
g_opt
.
m_pk2len
!=
0
)
CHK
(
g_opr
->
equal
(
"PK2"
,
tup
.
m_pk2
)
==
0
);
CHK
(
getBlobHandles
(
g_opr
)
=
=
0
);
if
(
style
==
0
)
{
CHK
(
setBlobValue
(
tup
)
==
0
);
}
else
if
(
style
==
1
)
{
CHK
(
setBlobWriteHook
(
tup
)
==
0
);
}
else
{
CHK
(
g_con
->
execute
(
NoCommit
)
==
0
);
CHK
(
writeBlobData
(
g_bh1
,
tup
.
m_blob1
)
==
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
(
writeBlobData
(
g_bh2
,
tup
.
m_blob2
)
==
0
);
CHK
(
writeBlobData
(
tup
)
==
0
);
}
CHK
(
g_con
->
execute
(
Commit
)
==
0
);
g_ndb
->
closeTransaction
(
g_con
);
g_op
x
=
0
;
g_op
r
=
0
;
g_con
=
0
;
tup
.
m_exists
=
true
;
}
...
...
@@ -755,74 +912,115 @@ updateIdx(bool rw)
}
static
int
readPk
(
bool
rw
)
deletePk
(
)
{
DBG
(
"---
read
Pk ---"
);
DBG
(
"---
delete
Pk ---"
);
for
(
unsigned
k
=
0
;
k
<
g_opt
.
m_rows
;
k
++
)
{
Tup
&
tup
=
g_tups
[
k
];
DBG
(
"
readPk pk1="
<<
tup
.
m_pk1
);
DBG
(
"
deletePk pk1="
<<
hex
<<
tup
.
m_pk1
);
CHK
((
g_con
=
g_ndb
->
startTransaction
())
!=
0
);
CHK
((
g_opr
=
g_con
->
getNdbOperation
(
g_opt
.
m_tname
))
!=
0
);
CHK
(
g_opr
->
read
Tuple
()
==
0
);
CHK
(
g_opr
->
delete
Tuple
()
==
0
);
CHK
(
g_opr
->
equal
(
"PK1"
,
tup
.
m_pk1
)
==
0
);
if
(
g_opt
.
m_pk2len
!=
0
)
CHK
(
g_opr
->
equal
(
"PK2"
,
tup
.
m_pk2
)
==
0
);
CHK
((
g_bh1
=
g_opr
->
getBlobHandle
(
"BL1"
))
!=
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
((
g_bh2
=
g_opr
->
getBlobHandle
(
"BL2"
))
!=
0
);
if
(
!
rw
)
{
CHK
(
g_con
->
execute
(
Commit
)
==
0
);
g_ndb
->
closeTransaction
(
g_con
);
g_opr
=
0
;
g_con
=
0
;
tup
.
m_exists
=
false
;
}
return
0
;
}
// hash index ops
static
int
readIdx
(
int
style
)
{
DBG
(
"--- readIdx "
<<
stylename
[
style
]
<<
" ---"
);
for
(
unsigned
k
=
0
;
k
<
g_opt
.
m_rows
;
k
++
)
{
Tup
&
tup
=
g_tups
[
k
];
DBG
(
"readIdx pk1="
<<
hex
<<
tup
.
m_pk1
);
CHK
((
g_con
=
g_ndb
->
startTransaction
())
!=
0
);
CHK
((
g_opx
=
g_con
->
getNdbIndexOperation
(
g_opt
.
m_x1name
,
g_opt
.
m_tname
))
!=
0
);
CHK
(
g_opx
->
readTuple
()
==
0
);
CHK
(
g_opx
->
equal
(
"PK2"
,
tup
.
m_pk2
)
==
0
);
CHK
(
getBlobHandles
(
g_opx
)
==
0
);
if
(
style
==
0
)
{
CHK
(
getBlobValue
(
tup
)
==
0
);
}
else
if
(
style
==
1
)
{
CHK
(
setBlobReadHook
(
tup
)
==
0
);
}
else
{
CHK
(
g_con
->
execute
(
NoCommit
)
==
0
);
CHK
(
readBlobData
(
tup
)
==
0
);
}
CHK
(
g_con
->
execute
(
Commit
)
==
0
);
if
(
!
rw
)
{
if
(
style
==
0
||
style
==
1
)
{
CHK
(
verifyBlobValue
(
tup
)
==
0
);
}
g_ndb
->
closeTransaction
(
g_con
);
g_op
r
=
0
;
g_op
x
=
0
;
g_con
=
0
;
}
return
0
;
}
static
int
readIdx
(
bool
rw
)
updateIdx
(
int
style
)
{
DBG
(
"---
readIdx
---"
);
DBG
(
"---
updateIdx "
<<
stylename
[
style
]
<<
"
---"
);
for
(
unsigned
k
=
0
;
k
<
g_opt
.
m_rows
;
k
++
)
{
Tup
&
tup
=
g_tups
[
k
];
DBG
(
"
readIdx pk1="
<<
tup
.
m_pk1
);
DBG
(
"
updateIdx pk1="
<<
hex
<<
tup
.
m_pk1
);
CHK
((
g_con
=
g_ndb
->
startTransaction
())
!=
0
);
CHK
((
g_opx
=
g_con
->
getNdbIndexOperation
(
g_opt
.
m_x1name
,
g_opt
.
m_tname
))
!=
0
);
CHK
(
g_opx
->
read
Tuple
()
==
0
);
CHK
(
g_opx
->
update
Tuple
()
==
0
);
CHK
(
g_opx
->
equal
(
"PK2"
,
tup
.
m_pk2
)
==
0
);
CHK
(
(
g_bh1
=
g_opx
->
getBlobHandle
(
"BL1"
))
!
=
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
(
(
g_bh2
=
g_opx
->
getBlobHandle
(
"BL2"
))
!
=
0
);
if
(
!
rw
)
{
CHK
(
getBlobValue
(
tup
)
==
0
);
CHK
(
getBlobHandles
(
g_opx
)
=
=
0
);
if
(
style
==
0
)
{
CHK
(
setBlobValue
(
tup
)
=
=
0
);
}
else
if
(
style
==
1
)
{
CHK
(
setBlobWriteHook
(
tup
)
==
0
);
}
else
{
CHK
(
g_con
->
execute
(
NoCommit
)
==
0
);
CHK
(
read
BlobData
(
tup
)
==
0
);
CHK
(
write
BlobData
(
tup
)
==
0
);
}
CHK
(
g_con
->
execute
(
Commit
)
==
0
);
if
(
!
rw
)
{
CHK
(
verifyBlobValue
(
tup
)
==
0
);
g_ndb
->
closeTransaction
(
g_con
);
g_opx
=
0
;
g_con
=
0
;
tup
.
m_exists
=
true
;
}
return
0
;
}
static
int
deleteIdx
()
{
DBG
(
"--- deleteIdx ---"
);
for
(
unsigned
k
=
0
;
k
<
g_opt
.
m_rows
;
k
++
)
{
Tup
&
tup
=
g_tups
[
k
];
DBG
(
"deleteIdx pk1="
<<
hex
<<
tup
.
m_pk1
);
CHK
((
g_con
=
g_ndb
->
startTransaction
())
!=
0
);
CHK
((
g_opx
=
g_con
->
getNdbIndexOperation
(
g_opt
.
m_x1name
,
g_opt
.
m_tname
))
!=
0
);
CHK
(
g_opx
->
deleteTuple
()
==
0
);
CHK
(
g_opx
->
equal
(
"PK2"
,
tup
.
m_pk2
)
==
0
);
CHK
(
g_con
->
execute
(
Commit
)
==
0
);
g_ndb
->
closeTransaction
(
g_con
);
g_opx
=
0
;
g_con
=
0
;
tup
.
m_exists
=
false
;
}
return
0
;
}
// scan ops table and index
static
int
readScan
(
bool
rw
,
bool
idx
)
readScan
(
int
style
,
bool
idx
)
{
const
char
*
func
=
!
idx
?
"scan read table"
:
"scan read index"
;
DBG
(
"--- "
<<
func
<<
" ---"
);
DBG
(
"--- "
<<
"readScan"
<<
(
idx
?
"Idx"
:
""
)
<<
" "
<<
stylename
[
style
]
<<
" ---"
);
Tup
tup
;
tup
.
alloc
();
// allocate buffers
NdbResultSet
*
rs
;
...
...
@@ -836,11 +1034,11 @@ readScan(bool rw, bool idx)
CHK
(
g_ops
->
getValue
(
"PK1"
,
(
char
*
)
&
tup
.
m_pk1
)
!=
0
);
if
(
g_opt
.
m_pk2len
!=
0
)
CHK
(
g_ops
->
getValue
(
"PK2"
,
tup
.
m_pk2
)
!=
0
);
CHK
((
g_bh1
=
g_ops
->
getBlobHandle
(
"BL1"
))
!=
0
);
if
(
!
g_opt
.
m_oneblob
)
CHK
((
g_bh2
=
g_ops
->
getBlobHandle
(
"BL2"
))
!=
0
);
if
(
!
rw
)
{
CHK
(
getBlobHandles
(
g_ops
)
==
0
);
if
(
style
==
0
)
{
CHK
(
getBlobValue
(
tup
)
==
0
);
}
else
if
(
style
==
1
)
{
CHK
(
setBlobReadHook
(
tup
)
==
0
);
}
CHK
(
g_con
->
execute
(
NoCommit
)
==
0
);
unsigned
rows
=
0
;
...
...
@@ -851,11 +1049,14 @@ readScan(bool rw, bool idx)
CHK
((
ret
=
rs
->
nextResult
(
true
))
==
0
||
ret
==
1
);
if
(
ret
==
1
)
break
;
DBG
(
func
<<
" pk1="
<<
tup
.
m_pk1
);
DBG
(
"readScan"
<<
(
idx
?
"Idx"
:
""
)
<<
" pk1="
<<
hex
<<
tup
.
m_pk1
);
Uint32
k
=
tup
.
m_pk1
-
g_opt
.
m_pk1off
;
CHK
(
k
<
g_opt
.
m_rows
&&
g_tups
[
k
].
m_exists
);
tup
.
copy
(
g_tups
[
k
]);
if
(
!
rw
)
{
tup
.
copyfrom
(
g_tups
[
k
]);
if
(
style
==
0
)
{
CHK
(
verifyBlobValue
(
tup
)
==
0
);
}
else
if
(
style
==
1
)
{
// execute ops generated by callbacks, if any
CHK
(
verifyBlobValue
(
tup
)
==
0
);
}
else
{
CHK
(
readBlobData
(
tup
)
==
0
);
...
...
@@ -870,52 +1071,63 @@ readScan(bool rw, bool idx)
}
static
int
deletePk
(
)
updateScan
(
int
style
,
bool
idx
)
{
DBG
(
"---
deletePk
---"
);
for
(
unsigned
k
=
0
;
k
<
g_opt
.
m_rows
;
k
++
)
{
Tup
&
tup
=
g_tups
[
k
];
DBG
(
"deletePk pk1="
<<
tup
.
m_pk1
)
;
DBG
(
"---
"
<<
"updateScan"
<<
(
idx
?
"Idx"
:
""
)
<<
" "
<<
stylename
[
style
]
<<
"
---"
);
Tup
tup
;
tup
.
alloc
();
// allocate buffers
NdbResultSet
*
rs
;
CHK
((
g_con
=
g_ndb
->
startTransaction
())
!=
0
);
CHK
((
g_opr
=
g_con
->
getNdbOperation
(
g_opt
.
m_tname
))
!=
0
);
CHK
(
g_opr
->
deleteTuple
()
==
0
);
CHK
(
g_opr
->
equal
(
"PK1"
,
tup
.
m_pk1
)
==
0
);
if
(
!
idx
)
{
CHK
((
g_ops
=
g_con
->
getNdbScanOperation
(
g_opt
.
m_tname
))
!=
0
);
}
else
{
CHK
((
g_ops
=
g_con
->
getNdbIndexScanOperation
(
g_opt
.
m_x2name
,
g_opt
.
m_tname
))
!=
0
);
}
CHK
((
rs
=
g_ops
->
readTuples
(
NdbScanOperation
::
LM_Exclusive
))
!=
0
);
CHK
(
g_ops
->
getValue
(
"PK1"
,
(
char
*
)
&
tup
.
m_pk1
)
!=
0
);
if
(
g_opt
.
m_pk2len
!=
0
)
CHK
(
g_opr
->
equal
(
"PK2"
,
tup
.
m_pk2
)
==
0
);
CHK
(
g_con
->
execute
(
Commit
)
==
0
);
g_ndb
->
closeTransaction
(
g_con
);
CHK
(
g_ops
->
getValue
(
"PK2"
,
tup
.
m_pk2
)
!=
0
);
CHK
(
g_con
->
execute
(
NoCommit
)
==
0
);
unsigned
rows
=
0
;
while
(
1
)
{
int
ret
;
tup
.
m_pk1
=
(
Uint32
)
-
1
;
memset
(
tup
.
m_pk2
,
'x'
,
g_opt
.
m_pk2len
);
CHK
((
ret
=
rs
->
nextResult
(
true
))
==
0
||
ret
==
1
);
if
(
ret
==
1
)
break
;
DBG
(
"updateScan"
<<
(
idx
?
"Idx"
:
""
)
<<
" pk1="
<<
hex
<<
tup
.
m_pk1
);
Uint32
k
=
tup
.
m_pk1
-
g_opt
.
m_pk1off
;
CHK
(
k
<
g_opt
.
m_rows
&&
g_tups
[
k
].
m_exists
);
// calculate new blob values
calcBval
(
g_tups
[
k
],
false
);
tup
.
copyfrom
(
g_tups
[
k
]);
CHK
((
g_opr
=
rs
->
updateTuple
())
!=
0
);
CHK
(
getBlobHandles
(
g_opr
)
==
0
);
if
(
style
==
0
)
{
CHK
(
setBlobValue
(
tup
)
==
0
);
}
else
if
(
style
==
1
)
{
CHK
(
setBlobWriteHook
(
tup
)
==
0
);
}
else
{
CHK
(
g_con
->
execute
(
NoCommit
)
==
0
);
CHK
(
writeBlobData
(
tup
)
==
0
);
}
CHK
(
g_con
->
execute
(
NoCommit
)
==
0
);
g_opr
=
0
;
g_con
=
0
;
tup
.
m_exists
=
false
;
rows
++
;
}
return
0
;
}
static
int
deleteIdx
()
{
DBG
(
"--- deleteIdx ---"
);
for
(
unsigned
k
=
0
;
k
<
g_opt
.
m_rows
;
k
++
)
{
Tup
&
tup
=
g_tups
[
k
];
DBG
(
"deleteIdx pk1="
<<
tup
.
m_pk1
);
CHK
((
g_con
=
g_ndb
->
startTransaction
())
!=
0
);
CHK
((
g_opx
=
g_con
->
getNdbIndexOperation
(
g_opt
.
m_x1name
,
g_opt
.
m_tname
))
!=
0
);
CHK
(
g_opx
->
deleteTuple
()
==
0
);
CHK
(
g_opx
->
equal
(
"PK2"
,
tup
.
m_pk2
)
==
0
);
CHK
(
g_con
->
execute
(
Commit
)
==
0
);
g_ndb
->
closeTransaction
(
g_con
);
g_opx
=
0
;
g_con
=
0
;
tup
.
m_exists
=
false
;
}
g_ops
=
0
;
CHK
(
g_opt
.
m_rows
==
rows
);
return
0
;
}
static
int
deleteScan
(
bool
idx
)
{
const
char
*
func
=
!
idx
?
"scan delete table"
:
"scan delete index"
;
DBG
(
"--- "
<<
func
<<
" ---"
);
DBG
(
"--- "
<<
"deleteScan"
<<
(
idx
?
"Idx"
:
""
)
<<
" ---"
);
Tup
tup
;
NdbResultSet
*
rs
;
CHK
((
g_con
=
g_ndb
->
startTransaction
())
!=
0
);
...
...
@@ -937,7 +1149,7 @@ deleteScan(bool idx)
CHK
((
ret
=
rs
->
nextResult
())
==
0
||
ret
==
1
);
if
(
ret
==
1
)
break
;
DBG
(
func
<<
" pk1="
<<
tup
.
m_pk1
);
DBG
(
"deleteScan"
<<
(
idx
?
"Idx"
:
""
)
<<
" pk1="
<<
hex
<<
tup
.
m_pk1
);
CHK
(
rs
->
deleteTuple
()
==
0
);
CHK
(
g_con
->
execute
(
NoCommit
)
==
0
);
Uint32
k
=
tup
.
m_pk1
-
g_opt
.
m_pk1off
;
...
...
@@ -948,7 +1160,6 @@ deleteScan(bool idx)
CHK
(
g_con
->
execute
(
Commit
)
==
0
);
g_ndb
->
closeTransaction
(
g_con
);
g_con
=
0
;
g_opr
=
0
;
g_ops
=
0
;
CHK
(
g_opt
.
m_rows
==
rows
);
return
0
;
...
...
@@ -981,69 +1192,75 @@ testmain()
}
if
(
g_opt
.
m_seed
!=
0
)
srandom
(
g_opt
.
m_seed
);
for
(
unsigned
loop
=
0
;
g_opt
.
m_loop
==
0
||
loop
<
g_opt
.
m_loop
;
loop
++
)
{
DBG
(
"=== loop "
<<
loop
<<
" ==="
);
for
(
g_loop
=
0
;
g_opt
.
m_loop
==
0
||
g_loop
<
g_opt
.
m_loop
;
g_
loop
++
)
{
DBG
(
"=== loop "
<<
g_
loop
<<
" ==="
);
if
(
g_opt
.
m_seed
==
0
)
srandom
(
loop
);
bool
llim
=
skip
(
'v'
)
?
true
:
false
;
bool
ulim
=
skip
(
'w'
)
?
false
:
true
;
srandom
(
g_loop
);
// pk
for
(
int
rw
=
llim
;
rw
<=
ulim
;
rw
++
)
{
if
(
skip
(
'k'
))
for
(
int
style
=
0
;
style
<=
2
;
style
++
)
{
if
(
skip
case
(
'k'
)
||
skipstyle
(
style
))
continue
;
DBG
(
"--- pk ops "
<<
(
!
rw
?
"get/set"
:
"read/write"
)
<<
" ---"
);
DBG
(
"--- pk ops "
<<
stylename
[
style
]
<<
" ---"
);
calcTups
(
false
);
CHK
(
insertPk
(
rw
)
==
0
);
CHK
(
insertPk
(
style
)
==
0
);
CHK
(
verifyBlob
()
==
0
);
CHK
(
readPk
(
rw
)
==
0
);
if
(
!
skip
(
'u'
))
{
calcTups
(
rw
);
CHK
(
updatePk
(
rw
)
==
0
);
CHK
(
readPk
(
style
)
==
0
);
if
(
!
skip
case
(
'u'
))
{
calcTups
(
style
);
CHK
(
updatePk
(
style
)
==
0
);
CHK
(
verifyBlob
()
==
0
);
}
CHK
(
readPk
(
rw
)
==
0
);
CHK
(
readPk
(
style
)
==
0
);
CHK
(
deletePk
()
==
0
);
CHK
(
verifyBlob
()
==
0
);
}
// hash index
for
(
int
rw
=
llim
;
rw
<=
ulim
;
rw
++
)
{
if
(
skip
(
'i'
))
for
(
int
style
=
0
;
style
<=
2
;
style
++
)
{
if
(
skip
case
(
'i'
)
||
skipstyle
(
style
))
continue
;
DBG
(
"--- idx ops "
<<
(
!
rw
?
"get/set"
:
"read/write"
)
<<
" ---"
);
DBG
(
"--- idx ops "
<<
stylename
[
style
]
<<
" ---"
);
calcTups
(
false
);
CHK
(
insertPk
(
rw
)
==
0
);
CHK
(
insertPk
(
style
)
==
0
);
CHK
(
verifyBlob
()
==
0
);
CHK
(
readIdx
(
rw
)
==
0
);
calcTups
(
rw
);
if
(
!
skip
(
'u'
))
{
CHK
(
updateIdx
(
rw
)
==
0
);
CHK
(
readIdx
(
style
)
==
0
);
calcTups
(
style
);
if
(
!
skip
case
(
'u'
))
{
CHK
(
updateIdx
(
style
)
==
0
);
CHK
(
verifyBlob
()
==
0
);
CHK
(
readIdx
(
rw
)
==
0
);
CHK
(
readIdx
(
style
)
==
0
);
}
CHK
(
deleteIdx
()
==
0
);
CHK
(
verifyBlob
()
==
0
);
}
// scan table
for
(
int
rw
=
llim
;
rw
<=
ulim
;
rw
++
)
{
if
(
skip
(
's'
))
for
(
int
style
=
0
;
style
<=
2
;
style
++
)
{
if
(
skip
case
(
's'
)
||
skipstyle
(
style
))
continue
;
DBG
(
"--- table scan "
<<
(
!
rw
?
"get/set"
:
"read/write"
)
<<
" ---"
);
DBG
(
"--- table scan "
<<
stylename
[
style
]
<<
" ---"
);
calcTups
(
false
);
CHK
(
insertPk
(
rw
)
==
0
);
CHK
(
insertPk
(
style
)
==
0
);
CHK
(
verifyBlob
()
==
0
);
CHK
(
readScan
(
style
,
false
)
==
0
);
if
(
!
skipcase
(
'u'
))
{
CHK
(
updateScan
(
style
,
false
)
==
0
);
CHK
(
verifyBlob
()
==
0
);
CHK
(
readScan
(
rw
,
false
)
==
0
);
}
CHK
(
deleteScan
(
false
)
==
0
);
CHK
(
verifyBlob
()
==
0
);
}
// scan index
for
(
int
rw
=
llim
;
rw
<=
ulim
;
rw
++
)
{
if
(
skip
(
'r'
))
for
(
int
style
=
0
;
style
<=
2
;
style
++
)
{
if
(
skip
case
(
'r'
)
||
skipstyle
(
style
))
continue
;
DBG
(
"--- index scan "
<<
(
!
rw
?
"get/set"
:
"read/write"
)
<<
" ---"
);
DBG
(
"--- index scan "
<<
stylename
[
style
]
<<
" ---"
);
calcTups
(
false
);
CHK
(
insertPk
(
rw
)
==
0
);
CHK
(
insertPk
(
style
)
==
0
);
CHK
(
verifyBlob
()
==
0
);
CHK
(
readScan
(
style
,
true
)
==
0
);
if
(
!
skipcase
(
'u'
))
{
CHK
(
updateScan
(
style
,
true
)
==
0
);
CHK
(
verifyBlob
()
==
0
);
CHK
(
readScan
(
rw
,
true
)
==
0
);
}
CHK
(
deleteScan
(
true
)
==
0
);
CHK
(
verifyBlob
()
==
0
);
}
...
...
@@ -1121,6 +1338,12 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
{
while
(
++
argv
,
--
argc
>
0
)
{
const
char
*
arg
=
argv
[
0
];
if
(
strcmp
(
arg
,
"-batch"
)
==
0
)
{
if
(
++
argv
,
--
argc
>
0
)
{
g_opt
.
m_batch
=
atoi
(
argv
[
0
]);
continue
;
}
}
if
(
strcmp
(
arg
,
"-core"
)
==
0
)
{
g_opt
.
m_core
=
true
;
continue
;
...
...
@@ -1165,9 +1388,13 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
}
if
(
strcmp
(
arg
,
"-skip"
)
==
0
)
{
if
(
++
argv
,
--
argc
>
0
)
{
for
(
const
char
*
p
=
argv
[
0
];
*
p
!=
0
;
p
++
)
{
skip
(
*
p
)
=
tr
ue
;
g_opt
.
m_skip
=
strdup
(
argv
[
0
]);
contin
ue
;
}
}
if
(
strcmp
(
arg
,
"-style"
)
==
0
)
{
if
(
++
argv
,
--
argc
>
0
)
{
g_opt
.
m_style
=
strdup
(
argv
[
0
]);
continue
;
}
}
...
...
@@ -1175,10 +1402,6 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
if
(
strcmp
(
arg
,
"-pk2len"
)
==
0
)
{
if
(
++
argv
,
--
argc
>
0
)
{
g_opt
.
m_pk2len
=
atoi
(
argv
[
0
]);
if
(
g_opt
.
m_pk2len
==
0
)
{
skip
(
'i'
)
=
true
;
skip
(
'r'
)
=
true
;
}
if
(
g_opt
.
m_pk2len
<=
g_max_pk2len
)
continue
;
}
...
...
@@ -1205,7 +1428,15 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
printusage
();
return
NDBT_ProgramExit
(
NDBT_WRONGARGS
);
}
if
(
g_opt
.
m_pk2len
==
0
)
{
char
b
[
100
];
strcpy
(
b
,
g_opt
.
m_skip
);
strcat
(
b
,
"i"
);
strcat
(
b
,
"r"
);
g_opt
.
m_skip
=
strdup
(
b
);
}
if
(
testmain
()
==
-
1
)
{
ndbout
<<
"line "
<<
__LINE__
<<
" FAIL loop="
<<
g_loop
<<
endl
;
return
NDBT_ProgramExit
(
NDBT_FAILED
);
}
return
NDBT_ProgramExit
(
NDBT_OK
);
...
...
ndb/test/src/NDBT_Table.cpp
View file @
e38792a6
...
...
@@ -18,35 +18,6 @@
#include <NdbTimer.hpp>
#include <NDBT.hpp>
class
NdbOut
&
operator
<<
(
class
NdbOut
&
ndbout
,
const
NDBT_Attribute
&
attr
){
NdbDictionary
::
Column
::
Type
type
=
attr
.
getType
();
ndbout
<<
attr
.
getName
()
<<
" "
<<
type
;
switch
(
type
){
case
NdbDictionary
:
:
Column
::
Decimal
:
ndbout
<<
"("
<<
attr
.
getScale
()
<<
", "
<<
attr
.
getPrecision
()
<<
")"
;
break
;
default:
break
;
}
if
(
attr
.
getLength
()
!=
1
)
ndbout
<<
"["
<<
attr
.
getLength
()
<<
"]"
;
if
(
attr
.
getNullable
())
ndbout
<<
" NULL"
;
else
ndbout
<<
" NOT NULL"
;
if
(
attr
.
getPrimaryKey
())
ndbout
<<
" PRIMARY KEY"
;
return
ndbout
;
}
class
NdbOut
&
operator
<<
(
class
NdbOut
&
ndbout
,
const
NDBT_Table
&
tab
)
{
...
...
ndb/test/src/NDBT_Test.cpp
View file @
e38792a6
...
...
@@ -830,7 +830,8 @@ void NDBT_TestSuite::execute(Ndb* ndb, const NdbDictionary::Table* pTab,
if
(
pTab2
==
0
&&
pDict
->
createTable
(
*
pTab
)
!=
0
){
numTestsFail
++
;
numTestsExecuted
++
;
g_err
<<
"ERROR1: Failed to create table "
<<
pTab
->
getName
()
<<
endl
;
g_err
<<
"ERROR1: Failed to create table "
<<
pTab
->
getName
()
<<
pDict
->
getNdbError
()
<<
endl
;
tests
[
t
]
->
saveTestResult
(
pTab
,
FAILED_TO_CREATE
);
continue
;
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment