Cómo get el tamaño de un BLOB sin leer el contenido del BLOB

Tengo las siguientes preguntas con respecto a los BLOB en sqlite:

  • ¿Sqlite realiza un seguimiento de los tamaños de los BLOB?
  • Supongo que sí, pero ¿lo usa la function de longitud o lee el contenido del BLOB?
  • Si sqlite realiza un seguimiento del tamaño del BLOB y la longitud no lo usa, ¿se puede acceder al tamaño a través de alguna otra funcionalidad?

Pregunto esto porque me pregunto si debería implementar desencadenantes que establecen tamaños de BLOB en columnas adicionales, o si puedo get los tamaños dinámicamente sin el golpe de performance de sqlite leyendo los BLOB.

De la fuente:

 ** In an SQLite index record, the serial type is stonetworking directly before ** the blob of data that it corresponds to. In a table record, all serial ** types are stonetworking at the start of the record, and the blobs of data at ** the end. Hence these functions allow the caller to handle the ** serial-type and data blob seperately. ** ** The following table describes the various storage classes for data: ** ** serial type bytes of data type ** -------------- --------------- --------------- ** 0 0 NULL ** 1 1 signed integer ** 2 2 signed integer ** 3 3 signed integer ** 4 4 signed integer ** 5 6 signed integer ** 6 8 signed integer ** 7 8 IEEE float ** 8 0 Integer constant 0 ** 9 0 Integer constant 1 ** 10,11 reserved for expansion ** N>=12 and even (N-12)/2 BLOB ** N>=13 and odd (N-13)/2 text 

En otras palabras, el tamaño del blob está en serie, y su longitud es simplemente "(serial_type-12) / 2".
Esta serie se almacena antes del blob real, por lo que no necesita leer el blob para get su tamaño.
Llame a sqlite3_blob_open y luego sqlite3_blob_bytes para get este valor.

Si tiene acceso a la versión en línea cruda sqlite3_blob_bytes hará el trabajo por usted. De lo contrario, proporcione información adicional.

Escriba un blob de 1 byte y 10 GB en una database de testing. Si length() toma el mismo time para ambos blobs, probablemente se acceda a la longitud del blob. De lo contrario, el blob probablemente se lea.

O bien, descargue el código fuente y depurelo: http://www.sqlite.org/download.html . Estos son algunos bits relevantes:

 /* ** Implementation of the length() function */ static void lengthFunc( sqlite3_context *context, int argc, sqlite3_value **argv ){ int len; assert( argc==1 ); UNUSED_PARAMETER(argc); switch( sqlite3_value_type(argv[0]) ){ case SQLITE_BLOB: case SQLITE_INTEGER: case SQLITE_FLOAT: { sqlite3_result_int(context, sqlite3_value_bytes(argv[0])); break; } case SQLITE_TEXT: { const unsigned char *z = sqlite3_value_text(argv[0]); if( z==0 ) return; len = 0; while( *z ){ len++; SQLITE_SKIP_UTF8(z); } sqlite3_result_int(context, len); break; } default: { sqlite3_result_null(context); break; } } } 

y entonces

 /* ** Return the number of bytes in the sqlite3_value object assuming ** that it uses the encoding "enc" */ SQLITE_PRIVATE int sqlite3ValueBytes(sqlite3_value *pVal, u8 enc){ Mem *p = (Mem*)pVal; if( (p->flags & MEM_Blob)!=0 || sqlite3ValueText(pVal, enc) ){ if( p->flags & MEM_Zero ){ return p->n + p->u.nZero; }else{ return p->n; } } return 0; } 

Puede ver que la longitud de los datos de text se calcula sobre la marcha. El de blobs … bueno, no soy lo suficientemente fluido en C … 🙂