Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 28 additions & 5 deletions db/types.c
Original file line number Diff line number Diff line change
Expand Up @@ -6401,6 +6401,9 @@ static TYPES_INLINE int SERVER_VUTF8_to_SERVER_BCSTR(
{
const char *cin = (const char *)in;
int len, tmp;
const char *str;
int str_len;
int valid_len;

if (inlen < VUTF8_ON_DISK_LEN)
return -1;
Expand All @@ -6421,11 +6424,31 @@ static TYPES_INLINE int SERVER_VUTF8_to_SERVER_BCSTR(
memcpy(&tmp, cin + 1, sizeof(int));
len = ntohl(tmp);

*outdtsz = 1;
/* copy the actual data around */
return vutf8_convert(len, cin + VUTF8_ON_DISK_LEN,
inlen - VUTF8_ON_DISK_LEN, (char *)out + 1, outlen - 1,
inblob, NULL, outdtsz);
if (len <= 0) {
memset((char *)out + 1, 0, outlen - 1);
*outdtsz = outlen;
return 0;
}

str_len = len - 1;
if (str_len > outlen - 1)
return -1;
if (len <= inlen - VUTF8_ON_DISK_LEN) {
str = cin + VUTF8_ON_DISK_LEN;
} else if (inblob && inblob->exists && inblob->data && inblob->length != OSQL_BLOB_FILLER_LENGTH) {
str = inblob->data;
} else {
logmsg(LOGMSG_ERROR, "SERVER_VUTF8_to_SERVER_BCSTR: missing data for %d byte string\n", len);
return -1;
}

if (utf8_validate(str, len, &valid_len) || valid_len != str_len)
return -1;
memset((char *)out + 1, 0, outlen - 1);
memcpy((char *)out + 1, str, str_len);
*outdtsz = outlen;

return 0;
}

static TYPES_INLINE int SERVER_VUTF8_to_SERVER_VUTF8(
Expand Down
2 changes: 1 addition & 1 deletion tests/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ basicops: basicops_nokey
$(shell TOTAL="${TOTAL}" $(TESTSROOTDIR)/tools/smalldelay.sh)
$(shell TESTDIR="${TESTDIR}" CLUSTER="${CLUSTER}" TESTSROOTDIR="${TESTSROOTDIR}" COMDB2_EXE=${COMDB2_EXE} CDB2SQL_EXE=${CDB2SQL_EXE} COPYCOMDB2_EXE=${COPYCOMDB2_EXE} COMDB2AR_EXE=${COMDB2AR_EXE} CDB2VERIFY_EXE=${CDB2VERIFY_EXE} PMUX_EXE=${PMUX_EXE} PMUXPORT=${PMUXPORT} SKIP_COPY_EXE="${SKIP_COPY_EXE}" ${TESTSROOTDIR}/tools/copy_files_to_cluster.sh > ${TESTDIR}/copy_files_to_cluster.log 2>&1 || echo "exit 1 copy_files_to_cluster failed, see ${TESTDIR}/copy_files_to_cluster.log" )

showparams:
showparams:
@echo MAKECMDGOALS=${MAKECMDGOALS}
@echo DOALL=${DOALL}
@echo TESTSROOTDIR=${TESTSROOTDIR}
Expand Down
8 changes: 8 additions & 0 deletions tests/sc_vutf8_to_cstring.test/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ifeq ($(TESTSROOTDIR),)
include ../testcase.mk
else
include $(TESTSROOTDIR)/testcase.mk
endif
ifeq ($(TEST_TIMEOUT),)
export TEST_TIMEOUT=3m
endif
100 changes: 100 additions & 0 deletions tests/sc_vutf8_to_cstring.test/runit
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
#!/usr/bin/env bash
bash -n "$0" | exit 1

source ${TESTSROOTDIR}/tools/runit_common.sh

set -eo pipefail

dbnm=$1

if [ "x$dbnm" == "x" ] ; then
echo "need a DB name"
exit 1
fi

nins=0

function insert_fixed_width_records()
{
j=$1
nstop=$2
let nins=nins+1
insfl=insert${nins}.out
echo "Inserting $((nstop-j+1)) records ($j to $nstop)."
echo "" > $insfl

while [[ $j -le $nstop ]]; do
cdb2sql ${CDB2_OPTIONS} $dbnm default "insert into t1(id,txt) values ($j,'$(printf '%010d' $j)')" &>> $insfl
let j=j+1
done
}

cluster=`cdb2sql --tabs ${CDB2_OPTIONS} $dbnm default 'exec procedure sys.cmd.send("bdb cluster")' | grep lsn | cut -f1 -d':' `

function flushall()
{
for node in $cluster; do
cdb2sql ${CDB2_OPTIONS} $dbnm --host $node "exec procedure sys.cmd.send('flush')"
done
}


echo "Test vutf8[10] to cstring[11] conversion during schema change"

function init_vutf8_field_table() {
len=$1
cdb2sql ${CDB2_OPTIONS} $dbnm default "drop table if exists t1"
cdb2sql ${CDB2_OPTIONS} $dbnm default - << EOF
create table t1 {
schema {
int id
vutf8 txt[$len]
}
}\$\$
EOF
}

function verify_schemachange_to_cstring() {
insert_fixed_width_records 1 100

assertcnt t1 100

a=$(cdb2sql ${CDB2_OPTIONS} $dbnm default "select * from t1 where id <= 5 order by id")
cdb2sql ${CDB2_OPTIONS} $dbnm default "alter table t1 { `cat t1_2.csc2 ` }"
rc=$?

if [[ "$rc" != 0 ]]; then
failexit "Test Failed: Schema change failed with rc=$rc, expected success"
fi

assertcnt t1 100
do_verify t1

b=$(cdb2sql ${CDB2_OPTIONS} $dbnm default "select * from t1 where id <= 5 order by id")

if [[ "$a" != "$b" ]]; then
failexit "Test Failed: Data mismatch after schema change. Before:\n$a\nAfter:\n$b"
fi

cdb2sql ${CDB2_OPTIONS} $dbnm default "insert into t1(id,txt) values (101,'1234567890')"
assertcnt t1 101

flushall
}

# let's test for set cstr len of 10, + 1 for \0 = 11
#case 1: vutf8 overflows, vutf8[5] -> cstring[11]
init_vutf8_field_table 5
verify_schemachange_to_cstring

#case 2: vutf8 just fits, vutf8[10] -> cstring[11]
init_vutf8_field_table 10
verify_schemachange_to_cstring

#case 3: vutf8 larger (should be ez even without fix should pass),
# vutf8[20] -> cstring[11]
init_vutf8_field_table 20
verify_schemachange_to_cstring

echo "Pass!"
exit 0
10 changes: 10 additions & 0 deletions tests/sc_vutf8_to_cstring.test/t1_2.csc2
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
schema
{
int id
cstring txt[11]
}

keys
{
dup "ID" = id
}
Loading