Skip to content

Commit

Permalink
Add support for columns defined with "CHARACTER SET OCTETS"
Browse files Browse the repository at this point in the history
For CHAR/VARCHAR columns, if the associated XSQLVAR has "sqlsubtype"
set to 1, this means the column was defined with "CHARACTER SET
OCTETS".

As OCTETS are raw binary data, convert these values into hexadecimal
representation, to match what isql does.

It may be desirable to add a connection-level option to return the
raw bytes, but there doesn't seem much point at the moment.
  • Loading branch information
ibarwick committed Aug 20, 2023
1 parent d2c5330 commit bb4ae5a
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 9 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
Revision history for libfq

0.6.0 2023-??-??
- support columns defined with "CHARACTER SET OCTETS"

0.5.0 2022-12-28
- Add functions FQprepare() and FQexecPrepared()
- Handle errors encountered when executing isc_dsql_fetch()
Expand Down
73 changes: 64 additions & 9 deletions src/libfq.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ static int _FQdspstrlen_line(FQresTupleAtt *att, short encoding_id);
static int check_tuple_field_number(const FBresult *res,
int row_number, int column_number);


static char *_FQformatOctet(char *data, int len);

/* keep this in same order as FQexecStatusType in libfq.h */
char *const fbresStatus[] = {
"FBRES_NO_ACTION",
Expand Down Expand Up @@ -3346,7 +3349,6 @@ _FQformatDatum(FBconn *conn, FQresTupleAttDesc *att_desc, XSQLVAR *var)
FQresTupleAtt *tuple_att;
short datatype;
char *p;
VARY2 *vary2;
struct tm times;
char format_buffer[1024];
char pad_buffer[1024];
Expand All @@ -3373,20 +3375,38 @@ _FQformatDatum(FBconn *conn, FQresTupleAttDesc *att_desc, XSQLVAR *var)
switch (datatype)
{
case SQL_TEXT:
p = (char *)malloc(var->sqllen + 1);

memcpy(p, var->sqldata, var->sqllen);
p[var->sqllen] = '\0';
if (var->sqlsubtype == 1)
{
/* column defined as "CHARACTER SET OCTETS" */
p = _FQformatOctet(var->sqldata, var->sqllen);
}
else
{
p = (char *)malloc(var->sqllen + 1);

memcpy(p, var->sqldata, var->sqllen);
p[var->sqllen] = '\0';
}
break;

case SQL_VARYING:
vary2 = (VARY2*)var->sqldata;
p = (char *)malloc(vary2->vary_length + 1);
memcpy(p, vary2->vary_string, vary2->vary_length + 1);
p[vary2->vary_length] = '\0';
{
VARY2 *vary2 = (VARY2*)var->sqldata;

if (var->sqlsubtype == 1)
{
/* column defined as "CHARACTER SET OCTETS" */
p = _FQformatOctet(vary2->vary_string, vary2->vary_length);
}
else
{
p = (char *)malloc(vary2->vary_length + 1);
memcpy(p, vary2->vary_string, vary2->vary_length + 1);
p[vary2->vary_length] = '\0';
}
}
break;

case SQL_SHORT:
case SQL_LONG:
case SQL_INT64:
Expand Down Expand Up @@ -3724,6 +3744,41 @@ _FQformatDatum(FBconn *conn, FQresTupleAttDesc *att_desc, XSQLVAR *var)
}


/**
* _FQformatOctet
*
* Display an octet string as hex values in upper case.
*/
static char *
_FQformatOctet(char *data, int len)
{
int i;
char *p, *q;


p = (char *)malloc((len * 2) + 1);
q = p;

for (i = 0; i < len; i++)
{
if (data[i])
{

sprintf(q, "%02X", (unsigned int)(data[i] & 0xFF));
q += 2;
}
else
{
sprintf(q, "00");
q += 2;
}

}

return p;
}


/**
* FQformatDbKey()
*
Expand Down

0 comments on commit bb4ae5a

Please sign in to comment.