diff --git a/gixsql-tests-nunit/data/TSQL044A.cbl b/gixsql-tests-nunit/data/TSQL044A.cbl new file mode 100644 index 0000000..b04643b --- /dev/null +++ b/gixsql-tests-nunit/data/TSQL044A.cbl @@ -0,0 +1,79 @@ + IDENTIFICATION DIVISION. + + PROGRAM-ID. TSQL044A. + + ENVIRONMENT DIVISION. + + CONFIGURATION SECTION. + SOURCE-COMPUTER. IBM-AT. + OBJECT-COMPUTER. IBM-AT. + + INPUT-OUTPUT SECTION. + FILE-CONTROL. + + DATA DIVISION. + + FILE SECTION. + + WORKING-STORAGE SECTION. + + 01 DATASRC PIC X(64). + 01 DBUSR PIC X(64). + + 01 H-KEY PIC S9(9) COMP. + 01 H-RES PIC S9(9) COMP. + 01 H-DISP PIC 9(4). + + EXEC SQL + INCLUDE SQLCA + END-EXEC. + + PROCEDURE DIVISION. + + 000-CONNECT. + + DISPLAY "DATASRC" UPON ENVIRONMENT-NAME. + ACCEPT DATASRC FROM ENVIRONMENT-VALUE. + DISPLAY "DATASRC_USR" UPON ENVIRONMENT-NAME. + ACCEPT DBUSR FROM ENVIRONMENT-VALUE. + + EXEC SQL + CONNECT TO :DATASRC USER :DBUSR + END-EXEC. + + IF SQLCODE <> 0 THEN + DISPLAY 'CONNECT SQLCODE. ' SQLCODE + DISPLAY 'CONNECT SQLERRM. ' SQLERRM + GO TO 100-EXIT + END-IF. + + 100-MAIN. + + * H-KEY is USAGE COMP (binary). It is rendered to a display + * string at runtime, so it must be bound as text, not as a raw + * binary value, both as a WHERE parameter and a FETCH target. + + MOVE 42 TO H-KEY. + + EXEC SQL + SELECT FLD2 INTO :H-RES FROM TAB1 + WHERE FLD1 = :H-KEY + END-EXEC. + + MOVE H-RES TO H-DISP. + + DISPLAY 'SELECT SQLCODE: ' SQLCODE. + DISPLAY 'FLD2: ' H-DISP. + + EXEC SQL + CONNECT RESET + END-EXEC. + + IF SQLCODE <> 0 THEN + DISPLAY 'DISCONNECT SQLCODE. ' SQLCODE + DISPLAY 'DISCONNECT SQLERRM. ' SQLERRM + GO TO 100-EXIT + END-IF. + + 100-EXIT. + STOP RUN. diff --git a/gixsql-tests-nunit/data/gixsql_test_data.xml b/gixsql-tests-nunit/data/gixsql_test_data.xml index 7680b50..6f8a5e9 100644 --- a/gixsql-tests-nunit/data/gixsql_test_data.xml +++ b/gixsql-tests-nunit/data/gixsql_test_data.xml @@ -3512,5 +3512,36 @@ + + COMP (USAGE BINARY) host variable as parameter and target + #000 + + all + all + + + + + + + tab1 + CREATE TABLE TAB1 (FLD1 INT, FLD2 INT) + INSERT INTO TAB1(FLD1, FLD2) VALUES(42, 1234) + + + + + + + + + + + + SELECT SQLCODE: +0000000000 + FLD2: 1234 + + + diff --git a/runtime/libgixsql/SqlVar.cpp b/runtime/libgixsql/SqlVar.cpp index 009c66e..77b0afc 100644 --- a/runtime/libgixsql/SqlVar.cpp +++ b/runtime/libgixsql/SqlVar.cpp @@ -78,9 +78,14 @@ SqlVar::SqlVar(CobolVarType _type, int _length, int _power, uint32_t _flags, voi addr = _addr; ind_addr = _ind_addr; flags = _flags; - is_variable_length = (_flags & CBL_FIELD_FLAG_VARLEN); - is_binary = (_flags & CBL_FIELD_FLAG_BINARY); - is_autotrim = (_flags & CBL_FIELD_FLAG_AUTOTRIM); + // COMP integers are rendered to a display string by createRealData, so they + // must bind as text: clear the binary flag gixpp sets for USAGE BINARY. + if (_type == CobolVarType::COBOL_TYPE_UNSIGNED_BINARY || + _type == CobolVarType::COBOL_TYPE_SIGNED_BINARY) + flags &= ~CBL_FIELD_FLAG_BINARY; + is_variable_length = (flags & CBL_FIELD_FLAG_VARLEN); + is_binary = (flags & CBL_FIELD_FLAG_BINARY); + is_autotrim = (flags & CBL_FIELD_FLAG_AUTOTRIM); allocate_realdata_buffer(); } @@ -316,6 +321,9 @@ void SqlVar::createRealData() } + // snprintf wrote a decimal string into the length-sized buffer; trim + // db_data_len to the text so trailing NULs aren't sent to the database. + db_data_len = (int)strlen((const char*)db_data_buffer.data()); spdlog::trace(FMT_FILE_FUNC "type: {}, length: {}, data: {}, db_data_buffer: [{}]", __FILE__, __func__, type, length, addr, std::string((const char *)db_data_buffer.data(), db_data_buffer_len)); break; @@ -367,6 +375,9 @@ void SqlVar::createRealData() } + // snprintf wrote a decimal string into the length-sized buffer; trim + // db_data_len to the text so trailing NULs aren't sent to the database. + db_data_len = (int)strlen((const char*)db_data_buffer.data()); spdlog::trace(FMT_FILE_FUNC "type: {}, length: {}, data: {}, db_data_buffer: [{}]", __FILE__, __func__, type, length, addr, std::string((const char *)db_data_buffer.data(), db_data_buffer_len)); break;