Mysql e Codepage

Sto impazzendo…
Quale codepage o ‘Table collation’ dovrei utilizzare per riuscire a visualizzare gli accenti, il simbolo dell’euro etc etc etc …
Davvero st impazzendo …

Ti consiglio di utilizzare sempre unicode8 sul db e subito dopo la connessione db.SQLExecute “set names ‘utf8’”

Tieni anche conto che quando fai la select, l’encoding delle stringhe nullo.

Io per quel caso ho fatto una estensione a DatabaseField, per cui nel caso in cui sia nullo l’encoding ottengo la stringa utf8 (come per sqlite ad esempio) altrimenti la stringa codificata.
Speriamo che un giorno trattino mySql come nativo utf8 e non come caso anomalo.

Function utfValue(extends dbf as DatabaseField) As String
dim s as String=dbf.StringValue
if s.Encoding=nil then
Return s.DefineEncoding(Encodings.UTF8)
else
Return s
end if
End Function

Dopo aver acceso il cervello …

Dici che potrei utilizzarlo cos al posto di .stringvalue ?

if rsitem.eof then
  ' se serve metti qui qualcosa in caso la tabella sia vuota
else
  lista.DeleteAllRows()
  rsitem.movefirst
  while not rsitem.eof
    self.lista.AddRow ""

lista.Cell(lista.ListCount -1, 0) = rsitem.field(“rowid”).utfValue
lista.Cell(lista.ListCount -1, 1) = rsitem.field(“codice”).StringValue
lista.Cell(lista.ListCount -1, 2) = rsitem.field(“descrizione”).StringValue
if rsitem.field(“principale”).BooleanValue = true then
lista.RowPicture(lista.ListCount -1) = ckdefault
end if
rsitem.movenext
wend
end if
end if

Ho provato per curiosit, ovviamente si blocca…
Poi provo la tua funzione togliendo il controllo

Function utfValue(extends dbf as DatabaseField) As String dim s as String=dbf.StringValue Return s.DefineEncoding(Encodings.UTF8) End Function

Vediamo se funziona senza arrabbiarsi …

In che senso di blocca?
da errore ? Dove?
La uso correntemente per trasferire dati da e per mySql molto intensivamente e senza problemi.

Ho messo la funzione come pubblica assieme a tutte le mie procedure …
(controllo email, controllo iban, controllo codice fiscale, partita iva, numero di scarpe, glicemia, azotemia e diabete… )
E la ho impiegata ovviamente come ti ho mostrato, dopo aver scritto

  • una procedura che legge un file XML con la configurazione ( in questo caso mi serviva per impostare il database MYSQL )
  • dopo aver passato la giornata ad inserire il comando db.SQLExecute “set names ‘utf8’”
  • e dopo aver poi controllato tutte le query SQL, i campi BOOLEAN e tutto quello che serviva per essere 100% compatibile con MYSQL

Faccio partire tutto e l’app si pianta alla prima al primo utilizzo di utfValue
Con un bel errore per eccezione.

Poi ho goooglato,
Ho riconvertito tutto il db in UTF8, ma nulla
Ho cancellato il db e ho importato il DUMP cambiando latin1 con utf8
Ma ancora nulla.

Alla fine ho convertito il comando : db.SQLExecute “set names ‘utf8’” con
db.SQLExecute(“SET NAMES utf8 COLLATE utf8_general_ci; SET CHARACTER SET utf8”)
E tutto, compresa la tua magica funzione cominciato a FUNZIONARE !

Quindi postiamo tutto BENE per chi come me, non ha mai usato MYSQL

  1. Il db si apre con qualche parametro in pi rispetto a sqlite esempio :
    dim db as new MySQLCommunityServer
    db.DatabaseName = “prova”
    db.Host = “127.0.0.1” oppure il nome file dell’host solo se il DNS lo risolve ‘mysql.prova.com’ oppure ‘localhost’ o l’indirizzo ip della macchina dove mysql sta funzionando ( attenzione all’utilizzo dall’esterno perch MYSQL se non adeguatamente settato non accessibile da una rete esterna a quella dove installato oppure addirittura da un pc diverso da quello che lo ospita )
    db.Username = “nomeutente”
    db.Password = “password”
    [opzionale] db.Port = “4453” [indicare solo se diversa da quella standard]

  2. prima di eseguire una qualsiasi query lanciamo il comando per l’impostazione della CODEPAGE del database :
    db.SQLExecute(“SET NAMES utf8 COLLATE utf8_general_ci; SET CHARACTER SET utf8”)

  3. attenzione ai dati inseriti nei comandi :
    riga.column(“nomecampo”) deve contenere un testo !! meglio se lo convertiamo in UTF8 esempio
    riga.column(“nomecampo”) = variabilstringa…ConvertEncoding(Encodings.UTF8)
    riga.doublecolumn(“nomecampo”) deve contenere un valore double
    riga.integer … etc

per le date utilizzare campodata.SQLDateTime
per i valori BOOLEAN ( quindi ad esempio i valori del checkbox ) utilizzare un campo di tipo TINYINT

per recuperare i valori dai db utilizzare la funzione magica del grande Antonio Rinaldi

Function utfValue(extends dbf as DatabaseField) As String dim s as String=dbf.StringValue if s.Encoding=nil then Return s.DefineEncoding(Encodings.UTF8) else Return s end if End Function

in questo modo
variabilestringa = recordset.field(“nomecampo”).utfValue

La codifica in UTF8 ( o altro … ) necessaria per visualizzare tutti i caratteri ASCII del set esteso, quindi le lettere accentate e gli altri segni, compreso euro, sterlina e dollaro

Unica nota da ricordare per MYSQL che il comando LIKE non CASE INSENSITIVE quindi per effettuare una ricerca CASE INSENSITIVE con la clausola LIKE vedere l’esempio

“SELECT * FROM nometabella WHERE LOWER(nomecampo) LIKE '%” + nomevariabile.lowercase + “%’”

Altra raccomandazione in MYSQL il campo ROWID non esiste, se ci siete abituati potete ad esempio con MySQLWorkbench
usare la query :
ALTER TABLE nometabella ADD rowid INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST;
ovviamente la chiave rowid autoincrement e per non dinamica come in SQLITE.

Spero questa mia piccola guida possa essere utile.
Ringrazio di quore il Maestro Antonio Rinaldi per le sue UTILISSIME chicche.

Antonio che dici,
se inverto la tua funzione e la faccio diventare una sub
Posso usarla anche per definire un campo in una rowset ?

Sub utfValue(extends campo as DatabaseField, Assigns valore As String) campo.StringValue = valore.ConvertEncoding(Encodings.UTF8) End Sub

Ora la provo …

Ho dovuto cambiare il nome alla funzione ma in questo caso possibile utilizzarla in modo EDIT

Sub UTF8Value(Extends field As DatabaseField, Assigns value As String) field.StringValue = value.ConvertEncoding(Encodings.UTF8) End Sub

in questo modo possibile utilizzare la sintassi :
recordset.field(“nomecampo”).UTF8Value = “Quello che vuoi come lo vuoi e con tutti gli accenti che preferisci … cdgh e slamla”

Ora Antonio, vediamo se assieme riusciamo a creare anche un tipo del tipo ( ora che ho fatto la rima sono peggio di prima ).
Vorrei dire in base all’esempio :
rowsa.column(“indirizzo”) = satxtindirizzo.text.ConvertEncoding(Encodings.UTF8)
rowsa.column(“cap”) = satxtcap.text.ConvertEncoding(Encodings.UTF8)
rowsa.column(“localita”) = satxtlocalita.text.ConvertEncoding(Encodings.UTF8)
rowsa.column(“provincia”) = satxtsigla.text.ConvertEncoding(Encodings.UTF8)
rowsa.column(“telefono1”) = satxttelefono.text.ConvertEncoding(Encodings.UTF8)
rowsa.column(“telefono2”) = satxttelefono2.text.ConvertEncoding(Encodings.UTF8)
rowsa.column(“cig”) = satxtcig.text.ConvertEncoding(Encodings.UTF8)
rowsa.column(“cup”) = satxtcup.text.ConvertEncoding(Encodings.UTF8)
rowsa.column(“note”) = satxtnote.text.ConvertEncoding(Encodings.UTF8)
rowsa.column(“stato”) = satxtstato.text.ConvertEncoding(Encodings.UTF8)

Riuscire a fare questo :
rowsa.utf8column(“indirizzo”) = satxtindirizzo.text

Ti ringrazio.

Un paio di puntualizzazioni.

La definizione del collate e del charset sarebbe opportuno inserirla nella definizione della tabella.
In questo dovrai impostare solo names alla connessione.
(puoi sempre ridefinire queste cose con i normali strumenti di lavoro si mySql)

Ovviamente se le impostazioni del server o della connessione lato server sono particolari probabilmente dovrai fare come hai scritto, ma in linea di principio non strettamente necessario e in ogni caso lo puoi controllare alla connessione interrogando opportunamente il server.

Per quanto riguarda le note che hai scritto:
La connessione la puoi anche fare tramite ssl, nella guida al linguaggio c’ un esempio.

La conversione IN utf di quello che scrivi, non strettamente necessaria.
Xojo gestisce come nativo la codifica UTF per cui a meno che non tu non stia leggendo dati da un server web, una seriale o altra fonte simile per cui la codifica in genere nil, o da un file con codifica particolare, ma a te nota (in qualche modo), non devi riconvertire in utf.
Quindi se inserisci i dati da un campo di testo dell’interfaccia (textfield) non dovresti doverlo convertire, gi UTF (come ti ho detto verificalo nel debugger)

Anche se sqlite ha il rowid, sempre buona norma avere una chiave primaria (certo dipende da cosa devi fare, le strategie possono cambiare)

Anche per sqlite meglio utilizzare sqlDateTime per le date. Anzi SEMPRE utilizzare le date in questo formato. Come dico spesso un conto il dato, un conto la visualizzazione. Nel caso di sqlDateTime hai sempre il valore della date, se lo inserisci come testo alla “italiana” corri il rischio che se uno ha impostazioni diverse, avrai date diverse; se utilizzi TotalSeconds, corri il rischio che se cambia il riferimento non avrai dati consistenti. (Tra l’altro anche se lo inserisci un uno semplice campo testo, puoi sempre fare selezioni per anno, anno-mese e cos via)

Quando ho tempo controllo come realizzare l’estensione per l’edit.