add support for binary attributes (ITS#4868)

This commit is contained in:
Pierangelo Masarati 2007-03-13 00:34:37 +00:00
parent 0d5a53815a
commit 8e8633b241
4 changed files with 136 additions and 33 deletions

View File

@ -181,6 +181,7 @@ typedef struct {
SWORD ncols;
BerVarray col_names;
UDWORD *col_prec;
SQLSMALLINT *col_type;
char **cols;
SQLINTEGER *value_len;
} BACKSQL_ROW_NTS;
@ -582,5 +583,10 @@ typedef struct backsql_info {
#define BACKSQL_SANITIZE_ERROR( rc ) \
( BACKSQL_LEGAL_ERROR( (rc) ) ? (rc) : LDAP_OTHER )
#define BACKSQL_IS_BINARY(ct) \
( (ct) == SQL_BINARY \
|| (ct) == SQL_VARBINARY \
|| (ct) == SQL_LONGVARBINARY)
#endif /* __BACKSQL_H__ */

View File

@ -735,11 +735,27 @@ backsql_get_attr_vals( void *v_at, void *v_bsi )
}
#endif /* BACKSQL_TRACE */
/*
* FIXME: what if a binary
* is fetched?
/* ITS#3386, ITS#3113 - 20070308
* If a binary is fetched?
* must use the actual size read
* from the database.
*/
ber_str2bv( row.cols[ i ], 0, 0, &bv );
if ( BACKSQL_IS_BINARY( row.col_type[ i ] ) ) {
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_ANY,
"==>backsql_get_attr_vals(\"%s\"): "
"column name %s: data is binary; "
"using database size %ld\n",
bsi->bsi_e->e_name.bv_val,
ad->ad_cname.bv_val,
row.value_len[ i ] );
#endif /* BACKSQL_TRACE */
bv.bv_val = row.cols[ i ];
bv.bv_len = row.value_len[ i ];
} else {
ber_str2bv( row.cols[ i ], 0, 0, &bv );
}
#ifdef BACKSQL_PRETTY_VALIDATE
if ( pretty ) {

View File

@ -74,6 +74,14 @@ backsql_cmp_attr( const void *v_m1, const void *v_m2 )
const backsql_at_map_rec *m1 = v_m1,
*m2 = v_m2;
if ( slap_ad_is_binary( m1->bam_ad ) || slap_ad_is_binary( m2->bam_ad ) ) {
#ifdef BACKSQL_USE_PTR_CMP
return SLAP_PTRCMP( m1->bam_ad->ad_type, m2->bam_ad->ad_type );
#else /* ! BACKSQL_USE_PTR_CMP */
return ber_bvcmp( &m1->bam_ad->ad_type->sat_cname, &m2->bam_ad->ad_type->sat_cname );
#endif /* ! BACKSQL_USE_PTR_CMP */
}
#ifdef BACKSQL_USE_PTR_CMP
return SLAP_PTRCMP( m1->bam_ad, m2->bam_ad );
#else /* ! BACKSQL_USE_PTR_CMP */
@ -87,12 +95,26 @@ backsql_dup_attr( void *v_m1, void *v_m2 )
backsql_at_map_rec *m1 = v_m1,
*m2 = v_m2;
assert( m1->bam_ad == m2->bam_ad );
if ( slap_ad_is_binary( m1->bam_ad ) || slap_ad_is_binary( m2->bam_ad ) ) {
#ifdef BACKSQL_USE_PTR_CMP
assert( m1->bam_ad->ad_type == m2->bam_ad->ad_type );
#else /* ! BACKSQL_USE_PTR_CMP */
assert( ber_bvcmp( &m1->bam_ad->ad_type->sat_cname, &m2->bam_ad->ad_type->sat_cname ) == 0 );
#endif /* ! BACKSQL_USE_PTR_CMP */
} else {
#ifdef BACKSQL_USE_PTR_CMP
assert( m1->bam_ad == m2->bam_ad );
#else /* ! BACKSQL_USE_PTR_CMP */
assert( ber_bvcmp( &m1->bam_ad->ad_cname, &m2->bam_ad->ad_cname ) == 0 );
#endif /* ! BACKSQL_USE_PTR_CMP */
}
/* duplicate definitions of attributeTypes are appended;
* this allows to define multiple rules for the same
* attributeType. Use with care! */
for ( ; m1->bam_next ; m1 = m1->bam_next );
m1->bam_next = m2;
m2->bam_next = NULL;

View File

@ -132,10 +132,6 @@ RETCODE
backsql_BindRowAsStrings_x( SQLHSTMT sth, BACKSQL_ROW_NTS *row, void *ctx )
{
RETCODE rc;
SQLCHAR colname[ 64 ];
SQLSMALLINT name_len, col_type, col_scale, col_null;
UDWORD col_prec;
int i;
if ( row == NULL ) {
return SQL_ERROR;
@ -155,6 +151,11 @@ backsql_BindRowAsStrings_x( SQLHSTMT sth, BACKSQL_ROW_NTS *row, void *ctx )
backsql_PrintErrors( SQL_NULL_HENV, SQL_NULL_HDBC, sth, rc );
} else {
SQLCHAR colname[ 64 ];
SQLSMALLINT name_len, col_type, col_scale, col_null;
UDWORD col_prec;
int i;
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"ncols=%d\n", (int)row->ncols, 0, 0 );
@ -162,58 +163,115 @@ backsql_BindRowAsStrings_x( SQLHSTMT sth, BACKSQL_ROW_NTS *row, void *ctx )
row->col_names = (BerVarray)ber_memcalloc_x( row->ncols + 1,
sizeof( struct berval ), ctx );
if ( !row->col_names ) goto nomem3;
row->cols = (char **)ber_memcalloc_x( row->ncols + 1,
sizeof( char * ), ctx );
if ( !row->cols ) goto nomem2;
if ( row->col_names == NULL ) {
goto nomem;
}
row->col_prec = (UDWORD *)ber_memcalloc_x( row->ncols,
sizeof( UDWORD ), ctx );
if ( !row->col_prec ) goto nomem1;
if ( row->col_prec == NULL ) {
goto nomem;
}
row->col_type = (SQLSMALLINT *)ber_memcalloc_x( row->ncols,
sizeof( SQLSMALLINT ), ctx );
if ( row->col_type == NULL ) {
goto nomem;
}
row->cols = (char **)ber_memcalloc_x( row->ncols + 1,
sizeof( char * ), ctx );
if ( row->cols == NULL ) {
goto nomem;
}
row->value_len = (SQLINTEGER *)ber_memcalloc_x( row->ncols,
sizeof( SQLINTEGER ), ctx );
if ( !row->value_len ) {
if ( row->value_len == NULL ) {
goto nomem;
}
if ( 0 ) {
nomem:
ber_memfree_x( row->col_names, ctx );
row->col_names = NULL;
ber_memfree_x( row->col_prec, ctx );
row->col_prec = NULL;
nomem1: ber_memfree_x( row->cols, ctx );
ber_memfree_x( row->col_type, ctx );
row->col_type = NULL;
ber_memfree_x( row->cols, ctx );
row->cols = NULL;
nomem2: ber_memfree_x( row->col_names, ctx );
row->col_names = NULL;
nomem3: Debug( LDAP_DEBUG_ANY, "backsql_BindRowAsStrings: "
ber_memfree_x( row->value_len, ctx );
row->value_len = NULL;
Debug( LDAP_DEBUG_ANY, "backsql_BindRowAsStrings: "
"out of memory\n", 0, 0, 0 );
return LDAP_NO_MEMORY;
}
for ( i = 1; i <= row->ncols; i++ ) {
rc = SQLDescribeCol( sth, (SQLSMALLINT)i, &colname[ 0 ],
for ( i = 0; i < row->ncols; i++ ) {
SQLSMALLINT TargetType;
rc = SQLDescribeCol( sth, (SQLSMALLINT)(i + 1), &colname[ 0 ],
(SQLUINTEGER)( sizeof( colname ) - 1 ),
&name_len, &col_type,
&col_prec, &col_scale, &col_null );
/* FIXME: test rc? */
ber_str2bv_x( (char *)colname, 0, 1,
&row->col_names[ i - 1 ], ctx );
&row->col_names[ i ], ctx );
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"col_name=%s, col_prec[%d]=%d\n",
colname, (int)i, (int)col_prec );
colname, (int)(i + 1), (int)col_prec );
#endif /* BACKSQL_TRACE */
if ( col_type != SQL_CHAR && col_type != SQL_VARCHAR )
{
col_prec = MAX_ATTR_LEN;
}
row->cols[ i - 1 ] = (char *)ber_memcalloc_x( col_prec + 1,
row->cols[ i ] = (char *)ber_memcalloc_x( col_prec + 1,
sizeof( char ), ctx );
row->col_prec[ i - 1 ] = col_prec;
rc = SQLBindCol( sth, (SQLUSMALLINT)i,
SQL_C_CHAR,
(SQLPOINTER)row->cols[ i - 1 ],
col_prec + 1,
&row->value_len[ i - 1 ] );
row->col_prec[ i ] = col_prec;
row->col_type[ i ] = col_type;
/*
* ITS#3386, ITS#3113 - 20070308
* Note: there are many differences between various DPMS and ODBC
* Systems; some support SQL_C_BLOB, SQL_C_BLOB_LOCATOR. YMMV:
* This has only been tested on Linux/MySQL/UnixODBC
* For BINARY-type Fields (BLOB, etc), read the data as BINARY
*/
if ( BACKSQL_IS_BINARY( col_type ) ) {
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"col_name=%s, col_type[%d]=%d: reading binary data\n",
colname, (int)(i + 1), (int)col_type);
#endif /* BACKSQL_TRACE */
TargetType = SQL_C_BINARY;
} else {
/* Otherwise read it as Character data */
#ifdef BACKSQL_TRACE
Debug( LDAP_DEBUG_TRACE, "backsql_BindRowAsStrings: "
"col_name=%s, col_type[%d]=%d: reading character data\n",
colname, (int)(i + 1), (int)col_type);
#endif /* BACKSQL_TRACE */
TargetType = SQL_C_CHAR;
}
rc = SQLBindCol( sth, (SQLUSMALLINT)(i + 1),
TargetType,
(SQLPOINTER)row->cols[ i ],
col_prec + 1,
&row->value_len[ i ] );
/* FIXME: test rc? */
}
BER_BVZERO( &row->col_names[ i - 1 ] );
row->cols[ i - 1 ] = NULL;
BER_BVZERO( &row->col_names[ i ] );
row->cols[ i ] = NULL;
}
#ifdef BACKSQL_TRACE
@ -237,8 +295,9 @@ backsql_FreeRow_x( BACKSQL_ROW_NTS *row, void *ctx )
}
ber_bvarray_free_x( row->col_names, ctx );
ber_memvfree_x( (void **)row->cols, ctx );
ber_memfree_x( row->col_prec, ctx );
ber_memfree_x( row->col_type, ctx );
ber_memvfree_x( (void **)row->cols, ctx );
ber_memfree_x( row->value_len, ctx );
return SQL_SUCCESS;