Monty Taylor wrote:
> Maybe we should load the data dictionary at initialization time and have
> our wrappers for equal and setValue for char* types do a lookup in the
> data dictionary on the column type and either space pad char columns or
> add length to the varchar columns. That could all be done once in C++ in
> the swig file and taken advantage of by all the languages. Sound
> reasonable? Then, perhaps, we could make an NdbVarchar and an NdbChar
> type that you could instantiate and pass in if you want to avoid the
> data dictionary step. But if we load the dictionary at init time, the
> API caches it, so it really shouldn't be too much of a hit in the
> context of a calling Perl or Python program.
Ok, I checked with Johan and the API itself will cache the Data
Dictionary. So I started writing some code to do this.
Here's what I've got so far:
=== modified file 'swig/NdbOperation.i'
--- swig/NdbOperation.i 2007-03-23 11:14:00 +0000
+++ swig/NdbOperation.i 2007-04-24 05:42:43 +0000
@@ -95,10 +95,10 @@
%rename(setVal) setValue(Uint32 anAttrId, float aValue);
%rename(setVal) setValue(Uint32 anAttrId, double aValue);
-
#endif
- int setValue(const char* anAttrName, const char* aValue);
+ %rename(setValueRaw) setValue(const char* anAttrName, const char*
aValue);
+
int setValue(const char* anAttrName, Int32 aValue);
int setValue(const char* anAttrName, Uint32 aValue);
int setValue(const char* anAttrName, Uint64 aValue);
@@ -217,6 +217,36 @@
%extend NdbOperation {
public:
+ int setValue(const char* anAttrName, const char* theValue) {
+ char * theModifiedValue;
+ const NdbDictionary::Table * theTable = self->getTable();
+ const NdbDictionary::Column * theColumn =
theTable->getColumn(anAttrName);
+ switch (theColumn->getType()) {
+
+ case NDB_TYPE_CHAR :
+ {
+ const int colLength = theColumn->getLength();
+ theModifiedValue=(char *)malloc(colLength);
+ memset(theModifiedValue,32,colLength);
+ memcpy(theModifiedValue,theValue,strlen(theValue));
+ }
+ break;
+ case NDB_TYPE_VARCHAR :
+ {
+ int extraBytes = (strlen(theValue)<=256) ? 1 : 2;
+ theModifiedValue=(char *)malloc(strlen(theValue+extraBytes));
+ memset(theModifiedValue,0,strlen(theValue));
+ theModifiedValue[0]=strlen(theValue);
+ memcpy(theModifiedValue,theValue,strlen(theValue));
+ }
+ break;
+ default :
+ break;
+ }
+ int ret = self->setValue(anAttrName,theModifiedValue);
+ free(theModifiedValue);
+ return ret;
+ }
NdbRecAttr* getValue(const char* anAttrName) {
return self->getValue(anAttrName,NULL);
}
I haven't really tested this yet - but I thought I'd get some thoughts
on this approach before going to far. What do you think? If you want to
avoid the switch, you can just use setValueRaw.
Granted - there is no error checking here, but I think it's easier to
read and talk about before I add that.
--
Monty Taylor
Senior Consultant
MySQL Inc., www.mysql.com
Get More with MySQL! www.mysql.com/consulting