ibmdb / node-ibm_db

IBM DB2 and IBM Informix bindings for node
MIT License
188 stars 151 forks source link

Empty Strings in Batch inserts result in corrupt values being inserted #875

Closed markddrake closed 1 year ago

markddrake commented 1 year ago

Executing the following code

import ibmdb  from 'ibm_db'
import crypto from 'crypto';
import assert from 'assert';

async function main() { 
    const cn = "DATABASE=SAMPLE;HOSTNAME=yadamu-db2;PORT=50000;PROTOCOL=TCPIP;UID=DB2INST1;PWD=oracle;"
    const BLOB_LENGTH = 1024 * 16;

    const conn = await ibmdb.open(cn)
    let results 

    results = await conn.query(`BEGIN DECLARE V_STATEMENT VARCHAR(300) DEFAULT 'drop table VARCHAR_TAB'; DECLARE CONTINUE HANDLER FOR SQLSTATE '42704' BEGIN  END;  EXECUTE IMMEDIATE V_STATEMENT; END;`)
    console.log(results)

    results = await conn.querySync(`create table VARCHAR_TAB (VC30 VARCHAR(30))`);
    console.log(results)

    const columnValues = [
        'Alberta',
        'A',
        'AA',
        ' ',
        ''
    ];

    const batch = {
      sql: `insert into VARCHAR_TAB (VC30) values (?)`,
      params: [{ 
        ParamType: 'ARRAY',
        SQLType: 1,
        Data: columnValues,
        Length: 10
      }],
      ArraySize: columnValues.length
    }

    console.dir(batch,{depth:null})

    try {
      results = await conn.query(batch)
      console.log(results)
    } catch (e) {
      console.log(1,e)
    }

    results = await conn.query(`select VC30, length(VC30) "LEN" from VARCHAR_TAB`)
    console.log(results)

}

main().then(() => { console.log('success')}).catch((e) => { console.log(e) })

Results in

C:\Development\YADAMU>node src\scratch\db2\BlankPadding.js
[]
[]
{
  sql: 'insert into VARCHAR_TAB (VC30) values (?)',
  params: [
    {
      ParamType: 'ARRAY',
      SQLType: 1,
      Data: [ 'Alberta', 'A', 'AA', ' ', '' ],
      Length: 10
    }
  ],
  ArraySize: 5
}
[]
[
  { VC30: 'Alberta', LEN: 7 },
  { VC30: 'A', LEN: 1 },
  { VC30: 'AA', LEN: 2 },
  { VC30: ' ', LEN: 1 },
  { VC30: '', LEN: 13 }
]
success

C:\Development\YADAMU>

As can be seem, while the content of the row where VC30 was set to '' appears to be correct visually the length of the value stored in the table is not correct.

Examination of the table in SQL shows

C:\Program Files\IBM\SQLLIB\BIN>db2
(c) Copyright IBM Corporation 1993,2007
Command Line Processor for DB2 Client 11.5.4.0

You can issue database manager commands and SQL statements from the command
prompt. For example:
    db2 => connect to sample
    db2 => bind sample.bnd

For general help, type: ?.
For command help, type: ? command, where command can be
the first few keywords of a database manager command. For example:
 ? CATALOG DATABASE for help on the CATALOG DATABASE command
 ? CATALOG          for help on all of the CATALOG commands.

To exit db2 interactive mode, type QUIT at the command prompt. Outside
interactive mode, all commands must be prefixed with 'db2'.
To list the current command option settings, type LIST COMMAND OPTIONS.

For more detailed help, refer to the Online Reference Manual.

db2 => connect to sample user db2inst1 using oracle

   Database Connection Information

 Database server        = DB2/LINUXX8664 11.5.7.0
 SQL authorization ID   = DB2INST1
 Local database alias   = SAMPLE

db2 => describe table VARCHAR_TAB

                                Data type                     Column
Column name                     schema    Data type name      Length     Scale Nulls
------------------------------- --------- ------------------- ---------- ----- ------
VC30                            SYSIBM    VARCHAR                     30     0 Yes

  1 record(s) selected.

db2 => select VC30, cast('!' || VC30 || '!' as VARCHAR50), length(VC30) from VARCHAR_TAB
SQL0204N  "VARCHAR50" is an undefined name.  SQLSTATE=42704
db2 => select VC30, cast('!' || VC30 || '!' as VARCHAR(50)), length(VC30) from VARCHAR_TAB

VC30                           2                                                  3
------------------------------ -------------------------------------------------- -----------
Alberta                        !Alberta!                                                    7
A                              !A!                                                          1
AA                             !AA!                                                         2
                               ! !                                                          1
                               !                                                           13

  5 record(s) selected.

db2 => insert into VARCHAR_TAB values ('')
DB20000I  The SQL command completed successfully.
db2 => select VC30, cast('!' || VC30 || '!' as VARCHAR(50)), length(VC30) from VARCHAR_TAB

VC30                           2                                                  3
------------------------------ -------------------------------------------------- -----------
Alberta                        !Alberta!                                                    7
A                              !A!                                                          1
AA                             !AA!                                                         2
                               ! !                                                          1
                               !                                                           13
                               !!                                                           0

  6 record(s) selected.

db2 =>

If the empty string is inserted via SQL then it's length is 0. When an empty string is inserted via node as part of a batch insert the data inserted appears to be corrupt (note there is no closing '!' character in the concat operation and the length is reported as 13

markddrake commented 1 year ago

Problem also occurs with VARGRAPHIC columns

markddrake commented 1 year ago

Confirm that this appears to be fixed in v3.0.0