Przeglądaj źródła

HPCC-12110 MySQL plugin returns random data for NULL fields

Signed-off-by: Richard Chapman <rchapman@hpccsystems.com>
Richard Chapman 10 lat temu
rodzic
commit
205c86f21f

+ 37 - 0
plugins/mysql/mysqlembed.cpp

@@ -342,6 +342,8 @@ static bool isInteger(enum_field_types type)
 
 static bool getBooleanResult(const RtlFieldInfo *field, const MYSQL_BIND &bound)
 {
+    if (*bound.is_null)
+        return false;
     if (!isInteger(bound.buffer_type))
         typeError("boolean", field);
     return rtlReadUInt(bound.buffer, *bound.length) != 0;
@@ -349,6 +351,12 @@ static bool getBooleanResult(const RtlFieldInfo *field, const MYSQL_BIND &bound)
 
 static void getDataResult(const RtlFieldInfo *field, const MYSQL_BIND &bound, size32_t &chars, void * &result)
 {
+    if (*bound.is_null)
+    {
+        result = NULL;
+        chars = 0;
+        return;
+    }
     if (bound.buffer_type == MYSQL_TYPE_TINY_BLOB ||
         bound.buffer_type == MYSQL_TYPE_MEDIUM_BLOB ||
         bound.buffer_type == MYSQL_TYPE_LONG_BLOB ||
@@ -366,6 +374,8 @@ static unsigned __int64 getUnsignedResult(const RtlFieldInfo *field, const MYSQL
 
 static double getRealResult(const RtlFieldInfo *field, const MYSQL_BIND &bound)
 {
+    if (*bound.is_null)
+        return 0;
     if (isInteger(bound.buffer_type))
     {
         if (bound.is_unsigned)
@@ -383,6 +393,8 @@ static double getRealResult(const RtlFieldInfo *field, const MYSQL_BIND &bound)
 
 static __int64 getSignedResult(const RtlFieldInfo *field, const MYSQL_BIND &bound)
 {
+    if (*bound.is_null)
+        return 0;
     if (isInteger(bound.buffer_type))
     {
         if (bound.is_unsigned)
@@ -396,6 +408,8 @@ static __int64 getSignedResult(const RtlFieldInfo *field, const MYSQL_BIND &boun
 
 static unsigned __int64 getUnsignedResult(const RtlFieldInfo *field, const MYSQL_BIND &bound)
 {
+    if (*bound.is_null)
+        return 0;
     if (!isInteger(bound.buffer_type))
         typeError("integer", field);
     if (bound.is_unsigned)
@@ -406,6 +420,12 @@ static unsigned __int64 getUnsignedResult(const RtlFieldInfo *field, const MYSQL
 
 static void getStringResult(const RtlFieldInfo *field, const MYSQL_BIND &bound, size32_t &chars, char * &result)
 {
+    if (*bound.is_null)
+    {
+        result = NULL;
+        chars = 0;
+        return;
+    }
     if (bound.buffer_type != MYSQL_TYPE_STRING && bound.buffer_type != MYSQL_TYPE_VAR_STRING)
         typeError("string", field);
     const char *text = (const char *) bound.buffer;
@@ -416,6 +436,12 @@ static void getStringResult(const RtlFieldInfo *field, const MYSQL_BIND &bound,
 
 static void getUTF8Result(const RtlFieldInfo *field, const MYSQL_BIND &bound, size32_t &chars, char * &result)
 {
+    if (*bound.is_null)
+    {
+        result = NULL;
+        chars = 0;
+        return;
+    }
     if (bound.buffer_type != MYSQL_TYPE_STRING && bound.buffer_type != MYSQL_TYPE_VAR_STRING)
         typeError("string", field);
     const char *text = (const char *) bound.buffer;
@@ -426,6 +452,12 @@ static void getUTF8Result(const RtlFieldInfo *field, const MYSQL_BIND &bound, si
 
 static void getUnicodeResult(const RtlFieldInfo *field, const MYSQL_BIND &bound, size32_t &chars, UChar * &result)
 {
+    if (*bound.is_null)
+    {
+        result = NULL;
+        chars = 0;
+        return;
+    }
     if (bound.buffer_type != MYSQL_TYPE_STRING && bound.buffer_type != MYSQL_TYPE_VAR_STRING)
         typeError("string", field);
     const char *text = (const char *) bound.buffer;
@@ -436,6 +468,11 @@ static void getUnicodeResult(const RtlFieldInfo *field, const MYSQL_BIND &bound,
 
 static void getDecimalResult(const RtlFieldInfo *field, const MYSQL_BIND &bound, Decimal &value)
 {
+    if (*bound.is_null)
+    {
+        value.setInt(0);
+        return;
+    }
     size32_t chars;
     rtlDataAttr result;
     mysqlembed::getStringResult(field, bound, chars, result.refstr());

+ 3 - 2
testing/regress/ecl/key/mysqlembed.xml

@@ -1,6 +1,7 @@
 <Dataset name='Result 1'>
  <Row><name>name1</name><value>1</value><boolval>true</boolval><r8>1.2</r8><r4>3.400000095367432</r4><d>6161353561613535</d><ddd>1234567.89</ddd><u1>Straße</u1><u2>Straße  </u2></Row>
  <Row><name>name2</name><value>2</value><boolval>false</boolval><r8>5.6</r8><r4>7.800000190734863</r4><d>3030</d><ddd>-1234567.89</ddd><u1>là</u1><u2>là      </u2></Row>
+ <Row><name>nulls</name><value>0</value><boolval>false</boolval><r8>0.0</r8><r4>0.0</r4><d></d><ddd>0</ddd><u1></u1><u2>        </u2></Row>
 </Dataset>
 <Dataset name='Result 2'>
  <Row><Result_2>name1</Result_2></Row>
@@ -9,10 +10,10 @@
  <Row><name>name1</name><value>1</value><boolval>true</boolval><r8>1.2</r8><r4>3.400000095367432</r4><d>6161353561613535</d><ddd>1234567.89</ddd><u1>Straße</u1><u2>Straße  </u2></Row>
 </Dataset>
 <Dataset name='Result 4'>
- <Row><Result_4>name2</Result_4></Row>
+ <Row><Result_4>nulls</Result_4></Row>
 </Dataset>
 <Dataset name='Result 5'>
- <Row><name>name2</name><value>2</value><boolval>false</boolval><r8>5.6</r8><r4>7.800000190734863</r4><d>3030</d><ddd>-1234567.89</ddd><u1>là</u1><u2>là      </u2></Row>
+ <Row><name>nulls</name><value>0</value><boolval>false</boolval><r8>0.0</r8><r4>0.0</r4><d></d><ddd>0</ddd><u1></u1><u2>        </u2></Row>
 </Dataset>
 <Dataset name='Result 6'>
  <Row><name>name1</name><value>1</value><boolval>true</boolval><r8>1.2</r8><r4>3.400000095367432</r4><d>6161353561613535</d><ddd>1234567.89</ddd><u1>Straße</u1><u2>Straße  </u2></Row>

+ 5 - 0
testing/regress/ecl/mysqlembed.ecl

@@ -52,6 +52,10 @@ initialize(dataset(childrec) values) := EMBED(mysql : user('rchapman'),database(
   INSERT INTO tbl1 values (?, ?, ?, ?, ?, ?, ?, ?, ?);
 ENDEMBED;
 
+initializeNulls() := EMBED(mysql : user('rchapman'),database('test'))
+  INSERT INTO tbl1 (name) values ('nulls');
+ENDEMBED;
+
 dataset(childrec) testMySQLDS() := EMBED(mysql : user('rchapman'),database('test'))
   SELECT * from tbl1;
 ENDEMBED;
@@ -116,6 +120,7 @@ sequential (
   drop(),
   create(),
   initialize(init),
+  initializeNulls(),
   OUTPUT(testMySQLDS()),
   OUTPUT(testMySQLRow().name),
   OUTPUT(testMySQLParms('name1', 1, true, 1.2, 3.4, D'aa55aa55', U'Straße', U'Straße')),