mirror of
https://git.openldap.org/openldap/openldap.git
synced 2025-01-06 10:46:21 +08:00
add support for binary attributes (ITS#4868)
This commit is contained in:
parent
0d5a53815a
commit
8e8633b241
@ -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__ */
|
||||
|
||||
|
@ -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 ) {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user