PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

La funzione superiore di Postgres sul carattere turco non restituisce il risultato atteso

Il tuo problema è 100% Windows. (O meglio Microsoft Visual Studio, con cui è stato creato PostgreSQL, per essere più precisi.)

Per la cronaca, SQL UPPER finisce per chiamare LCMapStringW di Windows (tramite towupper tramite str_toupper ) con quasi tutti i parametri corretti (locale 1055 turco per un UTF-8 -codificato, Turkish_Turkey banca dati),

ma

il runtime di Visual Studio (towupper ) non imposta il LCMAP_LINGUISTIC_CASING bit in LCMapStringW dwMapFlags . (Posso confermare che l'impostazione funziona.) Questo non è considerato un bug in Microsoft; è di progettazione e probabilmente non sarà mai "riparato" (oh le gioie dell'eredità.)

Hai tre vie d'uscita:

  • implementa la soluzione wrapper di @Sorrow (o scrivi la tua sostituzione di funzione nativa (DLL).)
  • esegui la tua istanza PostgreSQL ad es. Ubuntu che mostra il comportamento giusto per le località turche (@Sorrow ha confermato che funziona per lui); questa è probabilmente la via d'uscita più semplice e pulita.
  • inserisci un MSVCR100.DLL a 32 bit con patch nel tuo bin di PostgreSQL directory (ma sebbene UPPER e LOWER funzionerebbe, altre cose come le regole di confronto potrebbero continuare a fallire, ancora una volta, a livello di Windows. MMV.)

Per completezza (e divertimento nostalgico) SOLO , ecco la procedura per correggere un sistema Windows (ma ricorda, a meno che non gestirai questa istanza PostgreSQL dalla culla alla tomba, potresti causare molto dolore ai tuoi successori; ogni volta che distribuisci un nuovo sistema di test o backup da scratch, tu o i tuoi successori dovreste ricordarvi di applicare nuovamente la patch -- e se diciamo che un giorno esegui l'aggiornamento a PostgreSQL 10, che dice usa MSVCR120.DLL invece di MSVCR100.DLL , quindi dovrai tentare la fortuna anche con l'applicazione di patch alla nuova DLL.) Su un sistema di test

  • usa HxD per aprire C:\WINDOWS\SYSTEM32\MSVCR100.DLL
  • salva subito la DLL con lo stesso nome in PostgreSQL bin directory (non tentare di copiare il file utilizzando Explorer o la riga di comando, potrebbero copiare la versione a 64 bit)
  • con il file ancora aperto in HxD, vai su Cerca> Sostituisci , scegli Tipo di dati:valori esadecimali , quindi
    • cerca... 4E 14 33 DB 3B CB 0F 84 41 12 00 00 B8 00 01 00 00
    • sostituire con... 4E 14 33 DB 3B CB 0F 84 41 12 00 00 B8 00 01 00 01
    • ...poi ancora una volta...
    • cerca...... FC 51 6A 01 8D 4D 08 51 68 00 02 00 00 50 E8 E2
    • sostituire con... FC 51 6A 01 8D 4D 08 51 68 00 02 00 01 50 E8 E2
  • ...e salva nuovamente sotto il bin di PostgreSQL directory, quindi riavvia PostgreSQL ed esegui nuovamente la query.
    • se la tua query continua a non funzionare (assicurati che il tuo database sia codificato UTF-8 con Turkish_Turkey per entrambi LC_CTYPE e LC_COLLATE ) apri postgres.exe in Dependency Walker a 32 bit e assicurati che indichi che carica MSVCR100.DLL dal bin di PostgreSQL directory.
    • se tutte le funzioni sono corrette, copiate la DLL patchata nel bin di PostgreSQL di produzione directory e riavvia.

MA RICORDA, nel momento in cui sposti i dati dal sistema Ubuntu o dal sistema Windows con patch a un sistema Windows senza patch, avrai di nuovo il problema e potresti non essere in grado di importare nuovamente questi dati su Ubuntu se l'istanza di Windows ha introdotto duplicati in un citext o in un UPPER /LOWER -indice di funzione basato.