Changeset 37c5882 in tol


Ignore:
Timestamp:
Feb 18, 2016, 12:17:42 PM (11 years ago)
Author:
Jorge Pérez <josp.jorge@…>
Branches:
1941-docker-image-to-test, devel, master
Children:
a1c9e632
Parents:
9c4daac
Message:

fixes #1913, se reimplementa la lógica para extraer las cadenas de caracteres muy grandes. SQlGetData retorna SQL_NO_DATA cuando ya no hay más datos por retornar. Correciones a los test.

git-svn-id: ​https://www.tol-project.org/svn/tolp/trunk@7235 be4846ae-f051-483a-831f-b64e7d08527f

Location:
tol/dbdrivers
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • tol/dbdrivers/CMakeLists.txt

    r9c4daac r37c5882  
     1if( CMAKE_COMPILER_IS_GNUCC )
     2  add_definitions( -Wimplicit-function-declaration )
     3endif( )
     4
    15if( ODBC_FOUND )
    26  add_library( tolodbc0 SHARED libtolodbc.c )
  • tol/dbdrivers/libtolodbc.c

    r9c4daac r37c5882  
    2222
    2323#include <stdlib.h>
     24#include <stdint.h>
    2425#include <stdio.h>
    2526#include <string.h>
    … …  
    686687}
    687688
     689//#define CHUNK_SIZE 16*1024
     690#define CHUNK_SIZE 4*1024
     691#define INITIAL_ARRAY_SIZE 10
     692#define GROW_ARRAY_INCR 10
     693
     694typedef struct
     695{
     696  uint32_t NumberOfChunks;
     697  int32_t LastChunk;
     698  SQLLEN SizeOfLastChunk;
     699  char **ArrayOfChunks;
     700  SQLLEN SizeOfChunk;
     701} ChunkOfTextType;
     702
     703void ChunkOfTextType_Init( ChunkOfTextType *chunkData )
     704{
     705  uint32_t i;
     706  chunkData->NumberOfChunks = INITIAL_ARRAY_SIZE;
     707  chunkData->ArrayOfChunks = calloc( INITIAL_ARRAY_SIZE, sizeof( char* ) );
     708  for( i = 0; i < INITIAL_ARRAY_SIZE; ++i )
     709    {
     710      chunkData->ArrayOfChunks[i] = NULL;
     711    }
     712  chunkData->LastChunk = -1;
     713  chunkData->SizeOfLastChunk = 0;
     714  chunkData->SizeOfChunk = CHUNK_SIZE;
     715}
     716
     717void ChunkOfTextType_Release( ChunkOfTextType *chunkData )
     718{
     719  uint32_t i;
     720  for( i = 0; i < chunkData->NumberOfChunks; ++i )
     721    {
     722      if( chunkData->ArrayOfChunks[i] )
     723        {
     724          free( chunkData->ArrayOfChunks[i] );
     725          chunkData->ArrayOfChunks[i] = NULL;
     726        }
     727    }
     728  free( chunkData->ArrayOfChunks );
     729  chunkData->ArrayOfChunks = NULL;
     730  chunkData->NumberOfChunks = 0;
     731  chunkData->LastChunk = -1;
     732  chunkData->SizeOfLastChunk = 0;
     733}
     734
     735char * ChunkOfTextType_GetChunk( ChunkOfTextType *chunkData )
     736{
     737  chunkData->LastChunk++;
     738  if ( chunkData->LastChunk == chunkData->NumberOfChunks )
     739    {
     740      /*
     741        printf( "reallocating array of chunks: LastChunk = %ld\n", chunkData->LastChunk );*/
     742      uint32_t sizeNew = chunkData->NumberOfChunks + GROW_ARRAY_INCR;
     743      int32_t i;
     744      chunkData->ArrayOfChunks = realloc( chunkData->ArrayOfChunks,
     745                                          sizeNew * sizeof( char* ) );
     746      for( i = chunkData->LastChunk; i < sizeNew; ++i )
     747        {
     748          chunkData->ArrayOfChunks[i] = NULL;
     749        }
     750      chunkData->NumberOfChunks = sizeNew;
     751    }
     752  if ( !chunkData->ArrayOfChunks[ chunkData->LastChunk ] )
     753    {
     754      chunkData->ArrayOfChunks[ chunkData->LastChunk ] = calloc( CHUNK_SIZE, sizeof(char) );
     755    }
     756  return chunkData->ArrayOfChunks[ chunkData->LastChunk ];
     757}
     758
     759void ChunkOfTextType_DiscardLast( ChunkOfTextType *chunkData )
     760{
     761  if ( chunkData->LastChunk >= 0 )
     762    {
     763      --chunkData->LastChunk;
     764    }
     765}
     766
     767void ChunkOfTextType_SetLastSize( ChunkOfTextType *chunkData )
     768{
     769  chunkData->SizeOfLastChunk = strlen( chunkData->ArrayOfChunks[ chunkData->LastChunk ] );
     770}
     771
     772char *ChunkOfTextType_GetCopyFullBuffer( ChunkOfTextType *chunkData )
     773{
     774  uint32_t size = chunkData->LastChunk * (chunkData->SizeOfChunk - 1) + chunkData->SizeOfLastChunk;
     775  char *buffer = malloc( size + 1), *ptr;
     776  uint32_t i;
     777
     778  //printf( "GetCopyFullBuffer: size = %ld, LastChunk = %ld, SizeOfLastChunk = %ld\n", size, chunkData->LastChunk, chunkData->SizeOfLastChunk );
     779  ptr = buffer;
     780  for( i = 0; i < chunkData->LastChunk; ++i )
     781    {
     782      memcpy( ptr, chunkData->ArrayOfChunks[i], chunkData->SizeOfChunk - 1);
     783      ptr += chunkData->SizeOfChunk - 1;
     784    }
     785  // copy last chunk
     786  memcpy( ptr, chunkData->ArrayOfChunks[i], chunkData->SizeOfLastChunk );
     787  buffer[ size ] = '\0';
     788  return buffer;
     789}
     790
    688791//-------------------------------------------------------------------
    689792DLLEXPORT(int) odbc_GetAsText(odbcd *dbd, int n_field, UCHAR **txt_val)
    690793{
    691   SQLRETURN status;
    692   SQLINTEGER num_required=MAX_TEXT_FIELD_LENGTH;
    693   SQLLEN num_available=0;
    694   UCHAR *str, *long_str;
    695 
    696   str = (UCHAR*) calloc(num_required, sizeof(UCHAR));
    697   if(str==NULL) {
    698     stdOutWriter("Out of memory retrieving text ODBC.\n");
    699     return 0;
    700   }
    701  
    702   status = SQLGetData(dbd->hstmt,n_field+1,SQL_CHAR,str,num_required,&num_available);
    703   if((status!=SQL_SUCCESS) && (status!=SQL_SUCCESS_WITH_INFO)) { return 0; }
    704   if(num_available==SQL_NULL_DATA) { return 1; }
    705 
    706   if(status==SQL_SUCCESS_WITH_INFO)
    707   {
    708     long_str = (UCHAR*) calloc(num_available+1, sizeof(UCHAR));
    709     if(long_str==NULL) {
    710       stdOutWriter("Out of memory retrieving text from ODBC.\n");
    711       return 0;
    712     }
    713     long_str = (unsigned char*) strncpy((char*)long_str,(char*)str,MAX_TEXT_FIELD_LENGTH-1);
    714     free(str);
    715     str = (UCHAR*) calloc((num_available+2)-num_required, sizeof(UCHAR));
    716     if(str==NULL) {
    717       stdOutWriter("Out of memory retrieving text from ODBC.\n");
    718       return 0;
    719     }
    720     status = SQLGetData(dbd->hstmt,n_field+1,SQL_CHAR,str,num_available,&num_available);
    721     long_str = (unsigned char*) strncat((char*)long_str, (char*)str, num_available);
    722     free(str);
    723     str = long_str;
    724   }
    725    
    726   *txt_val = str;
     794  ChunkOfTextType chunkData;
     795  char *buffer = NULL;
     796  SQLLEN LenOrInd;
     797  SQLRETURN     rc;
     798
     799  ChunkOfTextType_Init( &chunkData );
     800
     801  do
     802    {
     803      buffer = ChunkOfTextType_GetChunk( &chunkData );
     804      rc = SQLGetData( dbd->hstmt, n_field+1,
     805                       SQL_C_CHAR, buffer, chunkData.SizeOfChunk,
     806                       &LenOrInd );
     807      //printf( "rc = %ld LenOrInd = %ld\n", rc, LenOrInd );
     808      if ( rc == SQL_NO_DATA )
     809        {
     810          ChunkOfTextType_DiscardLast( &chunkData );
     811          break;
     812        }
     813      if ( rc == SQL_ERROR )
     814        {
     815          ChunkOfTextType_Release( &chunkData );
     816          return 0;
     817        }
     818      if ( LenOrInd == SQL_NO_TOTAL )
     819        {
     820          continue;
     821        }
     822      if ( LenOrInd ==  SQL_NULL_DATA )
     823        {
     824          // Esto solo puede pasar en el primer chunk
     825          ChunkOfTextType_Release( &chunkData );
     826          *txt_val = NULL;
     827          return 1;
     828        }
     829      ChunkOfTextType_SetLastSize( &chunkData );
     830    } while( 1 );
     831  *txt_val = ChunkOfTextType_GetCopyFullBuffer( &chunkData );
     832  ChunkOfTextType_Release( &chunkData );
    727833  return 1;
    728834}
  • tol/dbdrivers/libtolsqlite.c

    r9c4daac r37c5882  
    2424#include <stdio.h>
    2525#include <string.h>
     26#include <ctype.h>
    2627
    2728#define SQLFLOAT double
  • tol/dbdrivers/tests/DBTestBigTextODBC.tol

    r9c4daac r37c5882  
    1919    Real res01 = If (DBExecQuery("drop table pruebas1") == 0, 1, 0);
    2020    Real res02 = If (DBExecQuery("CREATE TABLE pruebas1 (
    21                       `campo1` VARCHAR(1),
    22                       `campo2` VARCHAR(255),
    23                       `campo3` TEXT,
    24                       `campo4` TEXT,
    25                       `campo5` TEXT)
     21                      campo1 VARCHAR(1),
     22                      campo2 VARCHAR(255),
     23                      campo3 TEXT,
     24                      campo4 TEXT,
     25                      campo5 TEXT)
    2626                     ") == 0,1,0);
    2727
    … …  
    4444  Real TestRow(Set row)
    4545  {
     46    Set lengths = EvalSet( row, Real(Text field) {TextLength(field)} );
     47    Set View( lengths, "" ); WriteLn( "" );
    4648    Real (TextMatch(row[1],"A")&
    4749          TextMatch(row[2],Repeat("ABCDE",25))&
    … …  
    6769  {
    6870    Set ODBC   = DBStructODBC("odbc");
    69     Real res01 = DBOpen(aliasNames[1],user,passwd, ODBC);
     71    Real res01 = DBOpen(aliasNames[1],user,passwd);
    7072
    7173    Real res02 = InitDB(0);
    72     Real res03 = FillDB(100);
    73     Real res04 = TestDB(100);
     74    Real res03 = FillDB(1);
     75    Real res04 = TestDB(1);
    7476
    7577    Real res20 = DBClose(aliasNames[1]);
  • tol/dbdrivers/tests/DBTestIni.tol

    r9c4daac r37c5882  
    66
    77//If FALSE, no DB check will be done:
    8 Real testDB    = False;
     8Real testDB    = True;
    99
    1010// Same user/password for all test databases:
    11 Text user      = "user";
    12 Text passwd    = "password";
     11Text user      = "toldevel";
     12Text passwd    = "tol!116.";
    1313
    1414// Database name for native access:
    15 Text dbName    = "test";
     15Text dbName    = "bysfortoldevel";
    1616
    1717//Host name for mysql access:
    18 Text host      = "localhost";
     18Text host      = "t-mysql01.localbayes.es";
    1919
    2020// Aliasnames for two ODBC handlers:
    21 Set aliasNames = [["test2","test3"]];
     21Set aliasNames = [["MySQLTolDevel", "OTAN","MSSQLTolDevel"]];
Note: See TracChangeset for help on using the changeset viewer.