Autore Topic: Lettura stringhe da SQLite  (Letto 8176 volte)

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Lettura stringhe da SQLite
« il: 26 Agosto 2008, 01:51:26 »
Stavo provando ad implementare pgDesigner, inserendo le funzionalità per la gestione di database in formato SQLite, e facendo delle prove in Gambas, è uscito un problema, che non capisco se è un errore nelle librerie Gambas oppure mio che non le leggo bene.

A dir la verità, ho provato anche con l'esempio Database, ma il risultato è lo stesso. Con programmi esterni invece funziona tutto, per cui penso proprio che l'anomalia sia dovuta a Gambas.

Il problema è semplice:

a) ho creato una semplice tabella, con ognuno dei campi definiti nei vari formati ammessi in SQLite (parliamo di quelli reali, descritti nella doc ufficiale): TEXT, INTEGER, REAL e BLOB;
b) ho inserito dei dati, rispettando ovviamente i formati;
c) mi connetto al db tramite l'applicazione di esempio;
d) eseguo la query (es. SELECT * FROM table1);
e) determino il nome dei campi;
f) loop all'interno del ResultSet;
g) stampo i campi, convertendoli in stringa (con Str(), tanto per gradire);

risultato:

1) tutti i campi numerici vengono rappresentati con il corretto contenuto;
2) per i campi TEXT viene visualizzato solo il primo carattere;
3) i campi BLOB non si leggono direttamente, ma và bene così.

Andando a fondo al problema, mi sono stampato anche le carattestiche di ogni campo e, sorpresa, per TEXT il valore di Length è sempre ZERO!
Oltre al fatto strano che sia zero, non capisco allora perchè comunque mi prende un carattere! Se è zero... è ZERO. Bho?

Ho fatto le stesse cose andando a leggere le tabelle di sistema all'interno del database, ma il ritorno è lo stesso.
Provando a modificare i tipi, ad esempio TEXT con VARCHAR(50), il risultato è idem con patate.

Non mi pare di aver letto di questa anomalia nei forum, ma mi può anche essere sfuggito.

Vi risulta 'sta cosa ?

Ha, tanto per ribadire il concetto espresso tempo fà qui nel sito: SQLite tratta tutti i campi in formato stringa, e per i formati ammessi ufficialmente (INTEGER, READ e BLOB) usa lo stesso concetto, solo che se si usano le api C per interfacciarlo, queste hanno modalità di conversione interne che ne rendono possibile la gestione. Riguardo l'utilizzo di sintassi, utilizzate in database più blasonati, SQLite usa un metodo interno che ne determina il tipo.

Esempio:

- se si dichiara un campo di una tabella:
  VARCHAR(10) <...>

- il tipo viene riconosciuto come stringa, determinandolo dalla stringa "CHAR" contenuta all'interno del tipo (VARCHAR).

- la cosa, come ho scritto, è però fittizzia, in quanto anche una dichiarazione, del tipo:
  INTEGER <...>

- viene interpretata come numero, ma all'interno viene comunque memorizzato come stringa

- idem con patate:
  NUMBER(10,2) <...>

- la definizione del campo viene accettata, capita come numero, ma sempre memorizzata come stringa.

Questo porta ad un problema importante, ovvero il fatto di scrivere codice alquanto robusto, che non permetta di inserire zozzerie all'interno del db.

Per fare un'altro esempio, deleterio:

- definire un campo DATE o DATETIME;
- provate a scriverci dentro una stringa del tipo "PRRRRRRR";
- l'inserimento verrà effettuato regolarmente, perchè il database non effettua alcun controllo, nè logico nè sintattico e nè di formato sul dati immesso.

Nei database con motore incorporato, questo non certamente fattibile, ma in SQLite, che non è un database basato su motore, la cosa è alquanto prevedibile, e anche un pochino pericolosa (tanto per essere prudenti).

Per quanto mi riguarda, l'unica cosa che differenzia SQLite da un semplice file di testo, è il fatto si supportare una limitata sintassi SQL ma, facendo un paragone al vecchio DBIII (o anche il Clipper), la differenza si nota, e parecchio.

Perdonatemi la lunga spiegazione, ma spero sia utile a qualcuno.

Comunque, spero che qualcuno mi dia una dritta sul perchè del problema che ho riscontrato.

Ciao a tutti!

g.paolo

  • Visitatore
Re: Lettura stringhe da SQLite
« Risposta #1 il: 26 Agosto 2008, 08:34:51 »
Per non avere problemi di sorta sui campi, io ho sempre impostato i medesimi come testo, sia per i numeri che per le date.
Forse dico una fesseria, ma non penso che tu converta il tuo campo testo con Str(), pertanto il passaggio g) nominato non effettua questa operazione di conversione sui medesimi.
Quindi se ho ben capito è solo un problema di stampa a video in una griglia?

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: Lettura stringhe da SQLite
« Risposta #2 il: 26 Agosto 2008, 11:03:00 »
Ciao darth

no, il passo g) è corretto, uso il classico PRINT per visualizzare il contenuto del campo, ma in ogni caso, qualsiasi funzione riporta solo il primo carattere.

Il codice, alquanto semplice, che stò utilizzando per testare le funzionalità di sqlite, è il seguente:

Codice: [Seleziona]

PRIVATE $hConn AS Connection

PUBLIC SUB Main()
  DIM sName AS String = User.Home &/ "tmp" &/ "dbsqlite.db"
  DIM hRes AS Result
  DIM hField AS ResultField
  DIM nRec AS Integer
  $hConn = NEW Connection
  WITH $hConn
    .Type = "sqlite3"
    .Host = ""
    .Login = ""
    .Password = ""
    .Name = sName
  END WITH
  PRINT "File = "; sName
  PRINT "Exist = "; Exist(sName)
  $hConn.Open()
  PRINT "Database opened"
  PRINT "Database name = " & $hConn.Name
  'hRes = $hConn.Exec("SELECT name FROM sqlite_master WHERE type = 'table';")
  hRes = $hConn.Exec("SELECT * FROM test;")
  PRINT "Count = "; hRes.Count
  hRes.MoveFirst()
  FOR nRec = 0 TO hRes.Max
    FOR EACH hField IN hRes.Fields
      PRINT "Field = "; hField.Name, hField.Type, hField.Length, CStr(hRes[hField.Name])
    NEXT
    hRes.MoveNext()
  NEXT
FINALLY
  TRY $hConn.Close()
  PRINT "Database closed"
  RETURN
CATCH
  PRINT "Error = "; Error.Code, Error.Text
END

g.paolo

  • Visitatore
Re: Lettura stringhe da SQLite
« Risposta #3 il: 26 Agosto 2008, 11:55:29 »
Ti dispiace allegare la table che stai usando per provare, in modo che posso controllare come funziona sul mio sistema?
Non vorrei fosse un problema legato alla distro!

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: Lettura stringhe da SQLite
« Risposta #4 il: 26 Agosto 2008, 14:55:54 »
Ti invio il file, ma tieni conto che solo con gambas (esempi compresi) non funziona.

Con programmi esterni, come ad esempio con "sqlite3" e "sqliteman", tutto funziona a dovere.

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: Lettura stringhe da SQLite
« Risposta #5 il: 26 Agosto 2008, 15:14:06 »
Ho fatto una prova, cercando di ottenere l'elenco delle tabelle contenute nel database, e mi dà lo stesso identico problema:

Codice: [Seleziona]

PRIVATE $hConn AS Connection
PRIVATE $hRes AS Result
PRIVATE $hTable AS Table
PRIVATE $hField AS ResultField

PUBLIC SUB Main()
  DIM sName AS String = User.Home &/ "tmp" &/ "dbsqlite.db"
  DIM nRec AS Integer
  $hConn = NEW Connection
  WITH $hConn
    .Type = "sqlite3"
    .Host = ""
    .Login = ""
    .Password = ""
    .Name = sName
  END WITH
  PRINT "File = "; sName
  PRINT "Exist = "; Exist(sName)
  $hConn.Open()
  IF (NOT $hConn.Opened) THEN Error.Raise("Database not opened.")
  PRINT "Database opened"
  PRINT "Database name = " & $hConn.Name
  PRINT "Charset = "; $hConn.Charset
  PRINT "Version = "; Left(Str($hConn.Version), Len(Str($hConn.Version)) - 4)
  '--------------------------------------------
  ' elenco tabelle. Errore -1 e visualizza solo il primo carattere del nome
  FOR EACH $hTable IN $hConn.Tables
    PRINT "Table = "; $hTable.Name
  NEXT
  '--------------------------------------------
  'hRes = $hConn.Exec("SELECT name FROM sqlite_master WHERE type = 'table';")
  $hRes = $hConn.Exec("SELECT * FROM " & $hConn.Quote("color"))
  PRINT "Count = "; $hRes.Count
  PRINT "        "; "Name", "Type", "Length", "Value"
  PRINT "        "; "----", "----", "------", "-----"
  $hRes.MoveFirst()
  FOR nRec = 0 TO 0 'hRes.Max
    FOR EACH $hField IN $hRes.Fields
      TRY PRINT "Field = "; $hField.Name, $hField.Type, $hField.Length, $hRes[$hField.Name]
    NEXT
    $hRes.MoveNext()
  NEXT
  TRY $hConn.Close()
  PRINT "Database closed"
CATCH
  PRINT "Error = "; Error.Code, Error.Text
END


Inoltre, stessa anomalia cambiando il nome del driver in "sqlite"; prove con "sqlite2" non posso farle perchè non esiste più nel repository di fedora, già da parecchio tempo.

g.paolo

  • Visitatore
Re: Lettura stringhe da SQLite
« Risposta #6 il: 26 Agosto 2008, 18:03:36 »
Oops! Sto rispondendoti usando il CD live di Ubuntu perchè da sprovveduto quale sono ho piantato letteralmente il mio sistema con gambas. Volevo fare pulizia dei kernel vecchi, ma invece di disinstallare solo i pacchetti linux-image sono andato ad eliminare anche i vecchi linux-headers.
Morale: modalità testuale e basta, ma con quella posso fare ben poco!!!
Mi accingo a reinstallare il tutto, porta pazienza!

g.paolo

  • Visitatore
Re: Lettura stringhe da SQLite
« Risposta #7 il: 26 Agosto 2008, 18:56:05 »
Fiuuuuuu! L'ho scampata bella, funziona tutto. Ho dovuto avviare con il CD live e fare un "fsck" e tutto è tornato a posto.
Probabilmente durante l'eliminazione degli headers il sistema ha combinato qualche pasticcio!
Tornando al tuo problema, ho scaricato il tuo archivio e collocato correttamente in "/home/darth14n/tmp".
Ho poi copiato il tuo codice in un modulo di avvio ed ho provato passo-passo.
Stranamente mi si ferma ancora alla 2° riga dicendo "unknown identifier: Connection".
Ho impostato male il prg?
Comunque sia ho cercato di aprire il DB con "sqlitebrowser" e mi trovo davanti ad una cosa orrenda che non capisco: guarda lo snapshot in corrispondenza di table1!
Vedi che c'è qualcosa che non va, mentre il resto è tutto a posto!

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: Lettura stringhe da SQLite
« Risposta #8 il: 28 Agosto 2008, 00:09:01 »
Intanto ti manca l'includione della libreria gambas2.db, nei parametri di progetto.

Che intenti per "cosa orrenda"? Forse il fatto che visualizza la DDL di creazione della tabella su una sola riga in modo tagliuzzato?

Credo che sia normale, anche se brutto, dato dal fatto che forse non tiene conto dei ritorni a capo, cosa che ho utilizzato nel comando di creazione; ma questo non è un problema, dato che la tabella esiste ed è corretta, e poi con sqlite3 da riga di comando la vedo tutta. Il fatto che si veda tagliata è solo un problema di sqlitebrowser.

Per il tuo problema kernel, anche per come è strutturato linux la cosa mi lascia perplesso, mi pare strano che l'eliminazione del package ti abbia incasinato il file-system, al massimo il problema si verificava al riavvio che non trovava il kernel per il boot. Se non ricordo male linux si mette tutto in memoria quando parte, e ci rimane fino al riavvio, ma è anche possibile che vi siano delle funzionalità che si incasinano in questi casi; forse sarebbe il caso di segnalarlo.

Offline leo72

  • Amministratore
  • Senatore Gambero
  • *****
  • Post: 2.163
    • Mostra profilo
    • http://www.leonardomiliani.com
Re: Lettura stringhe da SQLite
« Risposta #9 il: 28 Agosto 2008, 00:32:27 »
Ho dato un'occhiata al DB, dato che ho smanettato per un po' con l'SQLite3, che usavo per il DB del mio gestionale prima versione (prima di riconvertire tutto a MySQL). Confermo l'errore -1 e la lettura di un solo carattere.

Non ho tempo a quest'ora di indagare però posso dirti che io i DB SQLite3 li creavo per comodità con Knoda, che reputo ottimo. Ho notato che questo programma usava CHAR(x) per impostare i campi testuali e non VARCHAR(x), anche se entrambe le sintassi sono accettate da SQLite.
Visita il mio sito personale: http://www.leonardomiliani.com

g.paolo

  • Visitatore
Re: Lettura stringhe da SQLite
« Risposta #10 il: 28 Agosto 2008, 08:00:10 »
@md9327
La cosa mi pare orrenda perchè in tal modo non si vedono eventuali ulteriori campi!
Capisco che sia un problema di sqlitebrowser, ma da quando ho abbandonato kexi sto usando solo quello.
Il mio problema relativo ai kernel disinstallati in realtà non era da attribuire ai medesimi. Probabilmente l'azione di rimozione ha rovinato qualche cluster del HD e pertanto con il fsck si è risolto. Strana coincidenza però, non mi era mai accaduto prima.

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: Lettura stringhe da SQLite
« Risposta #11 il: 29 Agosto 2008, 15:12:28 »
Bè, se il problema si è verificato in relazione al guaio è molto probabile che non ci siano stati danni fisici, ovvero, è molto probabile che qualcosa negli indici sia stata scritta male, ma poi fsck l'ha sistemata.
Se il guaio proviene dal disco, il guaio è serio, e vuol dire che stà per lasciare questo mondo; difficilmente il software può causare danni di questo genere, che sono di norma causati dal tempo, dall'uso o da qualche anomalia elettrica.

...al massimo dovevi formattare tutto... ehm...

Scherzi a parte, non sò se hai modo, ma con Sqliteman (ad esempio), anche se molto sempliciotto, puoi vedere che sembra tutto a posto; a riga di comando sqlite3 dice altrettanto.

Ma a parte questo, è solo con Gambas che non riesco a far funzionare la cosa, ne con il mio programma di test, nè con gli esempi a corredo. Nell'esempio "Database", dopo esserti connesso al database, inserendo il nome e la path del file al posto del nome db, e aver impostato "sqlite3" o "sqlite" nel tipo db, la creazione delle tabelle di esempio và benissimo, tanto è vero che con strumenti esterni a gambas, vedo le tabelle e i dati in modo corretto, mentre visualizzando le cose dalla form dell'esempio, per i campi testo appare solo il primo carattere.

Se questo dipenda dalla distribuzione ci credo molto poco, altrimenti non dovrebbe funzionare nulla, e anche le librerie dovrebbero essere a posto; è come se nella libreria Gambas manchi la parte che determini la dimensione effettiva del campo, oppure che la legga male. In effetti, se viene specificato, la definizione del campo riporta la dimensione data in fase di creazione, ma poi al dunque riporta sempre e solo il primo carattere. Questa cosa si verifica non solo per i campi di tabella, ma con tutti i metodi delle classi contenute nella libreria gambas2.db; ovviamente questo non avviene per PostgreSQL, per MySQL non ci ho provato.

Se tu riesci a darmi conferma della cosa, toccherà segnalarla al team.

Tu pensa, avevo già buttato giù gran parte delle funzionalità in pgDesigner per SQLite, ma mi sono fermato sulla parte interfaccia db. Se non riesco a risolvere, mi toccherà abbandonare il discorso...

g.paolo

  • Visitatore
Re: Lettura stringhe da SQLite
« Risposta #12 il: 29 Agosto 2008, 15:24:11 »
Confermo l'errore che hai riscontrato!
Questo l'output che ricevo:
Codice: [Seleziona]
File = /home/han/tmp/dbsqlite.db Exist = True Database opened Database name = /home/han/tmp/dbsqlite.db Charset = UTF-8 Version = 3 Error = -1      Unknown table: c

Sarebbe proprio un peccato dover abbandonare queste nuove funzionalità che stai implementando; continuo a sperare!

Offline md9327

  • Moderatore
  • Senatore Gambero
  • *****
  • Post: 2.840
    • Mostra profilo
Re: Lettura stringhe da SQLite
« Risposta #13 il: 30 Agosto 2008, 02:25:50 »
Più che abbandonarle, le metto in sospeso...

Comunque ho già comunicato il problema a Benoit, vediamo la sua risposta.

A dir la verità, dato che non mi sono mai interessato a SQLite, non ho punti di riferimento che mi possano far pensare che l'anomalia sia legata a questa ultima release, per cui non sò effettivamente cosa pensare; rimetter su versioni precedenti non lo vedo fattibile, andare a cercare e trovare una versione funzionante, ammesso che esista, mi pare un lavoro inutile dato che se il problema è legato a questa ultima, è sicuramente il caso di sistemarla.

Bè, ti farò sapere.

Ciao