]> git.sur5r.net Git - openldap/commitdiff
add support for binary attributes (ITS#4868)
authorPierangelo Masarati <ando@openldap.org>
Tue, 13 Mar 2007 00:34:37 +0000 (00:34 +0000)
committerPierangelo Masarati <ando@openldap.org>
Tue, 13 Mar 2007 00:34:37 +0000 (00:34 +0000)
servers/slapd/back-sql/back-sql.h
servers/slapd/back-sql/entry-id.c
servers/slapd/back-sql/schema-map.c
servers/slapd/back-sql/sql-wrap.c

index f21467914824f30008f4f0698489160391fcf4b3..83f58d0ea2f598b3bec3b86ea0eb7624be35722d 100644 (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__ */
 
index 39122f2c1064125963e8bd2537d2e29ef3bfe4d4..e12b2081215a0e34f02ad09973a503ea7abd4950 100644 (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 ) {
index d64d5e937e1ecef30a5573e5a2fe9195be18117c..cc1f82c2751e645190281d1696ade03b6df7ed10 100644 (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;
 
index d01d9cbb31e1e403927f9b8e2ed76fd6e131b934..810fc6a4d8da8734b8f18f556444023372101d8f 100644 (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;