Newsgroup: it.comp.os.linux.development
Titolo: sqlite: riempire una lista

Lavorando con un database SQLite ho composto una funzione per 
"formattare" i dati estratti e metterli in una GList.
Il problema e' che tale funzione non riempie interamente la lista, ma 
solo qualche elementuccio qua e la'.
Piu' o meno, ecco i punti salienti:
int get ( void *args, int numCols, char **result, char **columnNames ) {
	int i,
	    type;
	Struttura *sett;
	GList *lista;
	...
	lista = ( GList* ) args;
	// riempie sett
	g_list_prepend ( lista, sett );
	return 0;
}
void mia_funzione () {
	sqlite *db;
	int n;
	char query;
	GList *lista;
	...
	sprintf (query, "SELECT COUNT (*) FROM TABELLA WHERE A=%d", b);
	// eseguendo la query sopra e stampando il risultato
	// viene il numero giusto
	...
	sprintf ( query, "SELECT CAMPO FROM TABELLA WHERE A = %d", b );
	sqlite_exec ( db, query, get, lista );
	printf ( "%d", g_list_length ( lista ) );  // un altro numero!
	...
}
Ho usato apposta una GList per poter "prependere" agevolmente gli 
elementi che man mano si trovano, ma ugualmente non ne vuole sapere: 
laddove ci sono 35 risultati, ne tira fuori 3!
Suggerimenti? Magari si deve fare in tutt'altro modo, e ho capito male 
io? Oppure il modo e' corretto, ma c'e' qualche accorgimento da prendere?
Grazie :-)
-- 
Roberto -MadBob- Guido
mail bob4mail***@***
gmail.com
web 
http://madbob.homelinux.com
BrainTop Project maintainer - 
http://braintop.sf.net

 	g_list_prepend ( lista, sett );
La prima cosa che mi salta sott'occhio:
devi salvare il valore ritornato da g_list_prepend
lista = g_list_prepend (lista, sett);
E poi se gli passi il ptr alla lista come arg, e vuoi rendere visibili le
modifiche al puntatore, passagli il **args
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**
  -<! I Never Wanted To Be What They Told Me To Be
  		Fulfill My Fate Then I'll Be Free >!- Blind Guardian - Mordred's Song

 
Con questo che vuoi dire? Ho provato a sostituire
lista = ( GList* ) args;
con
lista = ( GList* ) **args;
ma in fase di compilazione mi dice che non si puo'.
Tra l'altro ho aggiunto anche qualche printf per il debugging, e... Ho 
scoperto che in effetti la lista viene riempita, in get(), con tutti gli 
elementi! Ma poi, quando nella funzione primaria vado a verificare con 
g_list_length(), mi trovo con molti meno elementi (ieri 3, oggi 
addirittura 2... Su 35...).
Sicuramente a questo punto si tratta di una faccenda di puntatori, che 
pero' non so veramente come risolvere...


 
Errata corrige: in get() passano tutti gli elementi estratti dal 
database, ma facendo una printf sulla lunghezza della lista si ottiene 
sempre e solo 2 (che e' anche la lunghezza finale, sbagliata).
Perche'???


 pero' non so veramente come risolvere...
Cosě a occhio et semplificando assai:
Se a questa funzione
void a(int x)
passi un intero, e la funzione a() lo modifica, la modifica non č visibile
nella funzione chiamante.
Il ptr che passi alla tua funzione č un intero, e le modifiche che gli fai
all'interno della tua funzione non sono visibili all'esterno.
Per cui devi passare un puntatore al puntatore alla GList. In breve:
void miafn (GList **p)	{
	GList *x = (*p);
	x = g_list_prepend (blahblah);
}
main ()	{
	GList *x;
	miafn (&x);
}
Prova e vediamo. Poi magari salta fuori che son tutte cazzate e io ci avrň
fatto una figura di merda.
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
    **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail** 
-<! At first there was nothing. Then God said 'Let there be light!' Then
		there was still nothing. But you could see it. !>-

 
Il punto e' che la funzione cui fa riferimento *deve* avere i parametri 
citati nel primo post:
int funzione ( void *args, int numCols, char **result, char **columnNames );
Ho risolto (credo... Devo fare ancora qualche prova...) in una maniera 
assai poco elegante ma che comunque funziona. La riporto, caso mai 
dovesse servire a qualcuno (o, soprattutto, se qualcuno puo' suggerire 
qualcosa di migliore ;-) ):
int get ( void *args, int numCols, char **result, char **columnNames ) {
	int i,
	    type;
	Struttura *sett;
	GList *lista;
	...
	lista = ( GList* ) args;
	lista = g_list_first ( lista );
	sett = lista->data;
	while ( sett->campo_a_caso != -1 )
		lista = g_list_next ( lista );
	sett->campo_a_caso = result [ 0 ];
	sett->campo_a_caso_1 = result [ 1 ];
	...
	return 0;
}
void funzione () {
	void mia_funzione () {
	sqlite *db;
	int n,
	    i;
	char query;
	Struttura *tmp;
	GList *lista;
	...
	sprintf (query, "SELECT COUNT (*) FROM TABELLA WHERE A=%d", b);
	// eseguendo la query sopra e stampando il risultato
	// viene il numero giusto. Metto tale numero in n
	...
	for ( i = 0; i < n; i++ ) {
		tmp = g_new ( Struttura, 1 );
		tmp->campo_a_caso = -1;
		lista = g_list_prepend ( lista, tmp );
	}
	...
	sprintf ( query, "SELECT CAMPO FROM TABELLA WHERE A = %d", b );
	sqlite_exec ( db, query, get, lista );
	...
}
Sostanzialmente, riempio la lista *prima* di passarla alla funzione 
chiamata da sqlite_exec e poi vado a riempire via via le strutture 
ancora vuote (ovvero: non ancora riempite) con i dati prelevati dal db.


 	    type;
la funzione get() è quella di callback per sqlite? se è così, tieni
presente che viene chiamata una volta per ogni record del risultato della
query...

 int funzione ( void *args, int numCols, char **result, char **columnNames );
Giusto, il callback di sqlite.
Comunque con un void* puoi passare qualunque cosa. Prova: anzichč passare il
GList* passa GList**
All'interno della funzione dereferenzi da GList** a GList* e mantieni
aggiornato quest'ultimo.
-- 
  Giuseppe "Cowo" Corbelli \/\ My software: 
http://cowo.yoda2000.net
        **ANTI-SPAM** -- **Substitute IHATESPAM with cowo to reply by mail**
 [cowo@braveheart cowo]$ make sex
    make: *** No rule to make target 'sex'.  Stop.