Página 1 de 2

Estructuras dinámicas a partir de consultas de BD

Publicado: 20 Jun 2011, 07:09
por pspCaracas
Tengo definidas varias estructuras que pueblo a partir de consultas de base de datos. Algo como:

Código: Seleccionar todo

int size;

main{

   size = getNumRows("persona")

   struct persona[size]

  getPeople(persona)

}

int getNumRows(char *tabla){

  int numOfRows;
  char sql = "select * from ";
  strcat(sql, tabla);

  executeQuery(sql);

   numOfRows  = fetchNumOfRows();

   return numOfRows;
}


void getPeople(struct persona[ ]){

  int i;
  char sql = "select * from peole";

   executeQuery(sql);

   numOfRows  = fetchNumOfRows();

   for(i=0;fetchRow != NULL,i++){

      persona[i].nombre = fetchField(0);
      persona[i].nombre = fetchField(1);

      ...

   }
   
}


Como pueden ver en el main, requiero ejecutar dos consultas a la base de datos, una primera consulta para saber el tamaño de la estructura "dinámica", y luego una segunda vez para llenar los datos.

Ahora mi pregunta: ¿Hay alguna forma de hacer esto en una sola función? He pensado en hacer la declaración de la estructura en la segunda función a través de un puntero...y de esta forma me arroaría una consulta a la base de datos.

¿Alguna idea de cómo hacerlo? O algún sitio donde leer?

Re: Estructuras dinámicas a partir de consultas de BD

Publicado: 15 Ago 2011, 20:19
por m0skit0
Siento la tardanza... ¿Conseguiste resolver esto?

Re: Estructuras dinámicas a partir de consultas de BD

Publicado: 15 Ago 2011, 20:36
por pspCaracas
De momento no...he tenido que sobrevivir con las dobles consultas :(

Mi duda en esencia es si se pueden declarar estructuras dinámicas y cambiarles el tamaño a voluntad (en ejemplo dependiendo de la cantidad de registros que arroje la base de datos consultada).

No te preocupes por la tardanza...como todo, se responde cuando se puede!! (regla n° 1 de listas de correos y foros)

Re: Estructuras dinámicas a partir de consultas de BD

Publicado: 16 Ago 2011, 09:10
por m0skit0
Primero, una bronca: ¡usa las etiquetas [code] para el código!

Segundo, otra brona: ¡no uses variables globales!

A ver si he entendido bien tu problema: lo que quieres es que el array persona sea dinámico, es decir, que pueda variar dependiendo de cuántas entradas tenga la tabla. Además quieres hacerlo en una sola consulta.

Re: Estructuras dinámicas a partir de consultas de BD

Publicado: 16 Ago 2011, 14:35
por pspCaracas
m0skit0 escribió:Primero, una bronca: ¡usa las etiquetas [code] para el código!

Listo!
m0skit0 escribió:Segundo, otra brona: ¡no uses variables globales!

Entendido!!
m0skit0 escribió:A ver si he entendido bien tu problema: lo que quieres es que el array persona sea dinámico, es decir, que pueda variar dependiendo de cuántas entradas tenga la tabla. Además quieres hacerlo en una sola consulta.

Exacto!!

Re: Estructuras dinámicas a partir de consultas de BD

Publicado: 16 Ago 2011, 14:50
por m0skit0
Aclarar que yo no he hecho consultas a BBDD en C...

Supongo que executeQuery() te tiene que devolver un result set o algo parecido. En vez de devolver el número de filas, devuelve el result set entero, así podrás consultar tanto los datos como el número de filas cuando desees.

En cuanto a la estructura dinámica, es bastante fácil (asumiendo que el struct se llama persona - te aconsejo que uses typedef struct en vez de struct a secas):

Código: Seleccionar todo

persona* personas;
unsigned long long size = getSize();
personas = (persona*) malloc(size * sizeof(persona));
personas[0]; etc...
free(personas);

Re: Estructuras dinámicas a partir de consultas de BD

Publicado: 16 Ago 2011, 17:42
por pspCaracas
Voy a proba a ver cómo me va...

¿Y cuál es la diferencia con typdef?

Re: Estructuras dinámicas a partir de consultas de BD

Publicado: 16 Ago 2011, 18:54
por m0skit0
pspCaracas escribió:¿Y cuál es la diferencia con typdef?

No necesitas andar poniendo struct delante todo el rato :mrgreen:

Ah y con

m0skit0 escribió:devuelve el result set entero

me refiero a un puntero :D

Re: Estructuras dinámicas a partir de consultas de BD

Publicado: 16 Ago 2011, 22:17
por pspCaracas
m0skit0 escribió:
pspCaracas escribió:¿Y cuál es la diferencia con typdef?

No necesitas andar poniendo struct delante todo el rato :mrgreen:


Esto mola muchísimo!!!

m0skit0 escribió:Ah y con

m0skit0 escribió:devuelve el result set entero

me refiero a un puntero :D


Eso si lo había entendido/asumido!!

Re: Estructuras dinámicas a partir de consultas de BD

Publicado: 19 Ago 2011, 21:55
por pspCaracas
Ya lo logré, pero faltaron apuntadores ¬¬

Busqué un poco más para completar tu ejemplo m0skit0, y encontré este de cómo reservar arreglos multidimensionales (en inglés para el que lo quiera revisar).

En mi caso tengo esto:

En el SQL.h

Código: Seleccionar todo


struct definition {
   int id;
   char valueType[10];
   float value;            
   int time;            
};

int getDefinition(MYSQL *, struct histDefinition **);


En el SQL.c

Código: Seleccionar todo

int getDefinition(MYSQL *conn, struct definition  **def){

   MYSQL_STMT *stmt;
   char *sql;

   // Bind variables
   MYSQL_BIND result[4];

   int myId, myTime;
   float myValue;
   char myValueType[10];
   unsigned long myValueTypeLength;

   my_bool is_null[3];
   my_ulonglong  numRows;

   int i;

   sql = "select * DefinitionTable";

   // Statement handler
   statementHandler(&conn, &stmt, &sql);

   // Initialize the result column structures
   memset(result, 0, sizeof(result)); /* zero the structures */

   // Init param structure
   // Result
   result[0].buffer_type    = MYSQL_TYPE_LONG;
   result[0].buffer       = (void *) &myId;
   result[0].is_unsigned   = 0;
   result[0].is_null       = &is_null[0];
   result[0].length       = 0;

   result[1].buffer_type    = MYSQL_TYPE_FLOAT;
   result[1].buffer       = (void *) &myValue;
   result[1].is_unsigned   = 0;
   result[1].is_null       = &is_null[1];
   result[1].length       = 0;

   result[2].buffer_type    = MYSQL_TYPE_LONG;
   result[2].buffer       = (void *) &myTime;
   result[2].is_unsigned   = 0;
   result[2].is_null       = &is_null[2];
   result[2].length       = 0;

   result[3].buffer_type    = MYSQL_TYPE_STRING;
   result[3].buffer       = (void *) myValueType;
   result[3].buffer_length   = sizeof (myValueType);
   result[3].is_null       = &is_null[4];
   result[3].length       = &myValueTypeLength;


   // Bind result
   if (mysql_stmt_bind_result(stmt, result) != 0) {
      print_stmt_error(stmt, "Could not bind results");
      return -1;
   }

   // Execute!!
   if (mysql_stmt_execute(stmt) != 0) {
      print_stmt_error(stmt, "Could not execute statement");
      return -1;
   }

   if (mysql_stmt_store_result(stmt) != 0) {
      print_stmt_error(stmt, "Could not buffer result set");
      return -1;
   }

   // Get the number of rows
   numRows = mysql_stmt_num_rows (stmt);

       // Dynamic structure
   *def = (struct definition*) malloc (numRows * sizeof(struct definition));

   // Fetch
   for(i=0; mysql_stmt_fetch (stmt) == 0; i++){

      // Init data
      (*def)[i].id       = 0;
      (*def)[i].value   = 0;
      (*def)[i].time   = 0;
      strcpy((*def)[i].valueType,"");

      (*def)[i].id       = myId;
      (*def)[i].deadband   = myValue;
      (*def)[i].deadtime   = myTime;
      strncpy((*def)[i].valueType, myValueType, strlen(myValueType));
      (*def)[i].valueType[strlen(myValueType)] = '\0';

   }

   // Deallocate result set
   mysql_stmt_free_result(stmt);

   // Close the statement
   mysql_stmt_close(stmt);

   return ((int) numRows);

}




En el programa.c

Código: Seleccionar todo

int main(){

    int numHistDef;

    // Open database
    openDB(&conn);

    struct definition *def = NULL;

    numDef = getDefinition(conn, &def);

    syslog(LOG_INFO,"> num of Definitions: %d", numHistDef);

    for (i = 0; i < numDef; i++) {

      syslog(LOG_INFO, "> def[%d].id: %d", i, def[i].id);
      syslog(LOG_INFO, "> def[%d].value: %f", i, def[i].value);
      syslog(LOG_INFO, "> def[%d].time: %d", i, def[i].time);
      syslog(LOG_INFO, "> def[%d].valueType: %s",i, def[i].valueType);
    }
   exit(0);
}



Salida:

Código: Seleccionar todo

Aug 19 15:14:53 buckbeak programa: > num of Definitions: 3
Aug 19 15:14:53 buckbeak programa: > def[0].id: 1
Aug 19 15:14:53 buckbeak programa: > def[0].value: 0.100000
Aug 19 15:14:53 buckbeak programa: > def[0].time: 30
Aug 19 15:14:53 buckbeak programa: > def[0].valueType: fsw
Aug 19 15:14:53 buckbeak programa: > def[1].id: 3
Aug 19 15:14:53 buckbeak programa: > def[1].value: 10.000000
Aug 19 15:14:53 buckbeak programa: > def[1].time: 30
Aug 19 15:14:53 buckbeak programa: > def[1].valueType: fsw
Aug 19 15:14:53 buckbeak programa: > def[2].id: 5
Aug 19 15:14:53 buckbeak programa: > def[2].value: 5.000000
Aug 19 15:14:53 buckbeak programa: > def[2].time: 20
Aug 19 15:14:53 buckbeak programa: > def[2].valueType: fsw




Lo bonito del conector de MySQL es que en el mismo result set viene el número de registros, haciendo solo una consulta. Justo lo que quería :)

PD: Te debo los typdef porque aun no soy diestro con eso :P