FiveTech Support Forums

FiveWin / Harbour / xBase community
Board index FiveWin para Harbour/xHarbour XBrowse con MySQL - no respeta Collation Latin1_spanish_ci
Posts: 54
Joined: Sat Dec 10, 2016 08:58 PM
XBrowse con MySQL - no respeta Collation Latin1_spanish_ci
Posted: Fri May 01, 2026 01:08 AM

Antonio / Mr Rao / Amigos

Hola a todos, solicito guía por favor.

A la base de datos MySQL/MaríaDB de mi software le he establecido CHARSET Latin1.

A las tablas ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_spanish_ci.

También me he asegurado que los campos de texto Tengan COLLATE latin1_spanish_ci.

Y la Conexión con FWConnect incluye Charset 'latin1' y luego agrego oCnx:Execute( "SET NAMES latin1 COLLATE latin1_spanish_ci" )

Eso por cuestiones de compatibilidad con DBF/CDX y con otros productos, y por la necesidad de ordenar correctamente las tildes (á, Á, é, É…) y las ñ y Ñ.

Resulta que los Rowset se alimentan correctamente en las consultas con ORDER BY, lo se porque si inmediatamente después de la consulta hago un browse() o si navego el Rowset de otras formas las filas se ven correctamente ordenadas.

El problema es que al usar XBrowse con sus atributos ya no se respeta el orden latin_spanish_ci, sino que, al parecer, y como me indica la IA, asume el orden Binario por como quedan ordenadas las filas, y al parecer sería porque XBrowse ordena internamente aunwue no se lo pida, y usaría ese método binario.

He probado con lSortOrder:= .f., que no aplica ordenamiento desde las cabeceras, pero tampoco lo resuelve, igual se pierde el orden.

Por favor si alguien sabe como resolverlo, como evitar que se ordene diferente a lo que el Order By trae correctamente.

Uso HB MSVSC + FWH 24.04 + MySQL/MaríaDB/DBFCDX (64 bits)

Muchas Gracias!

José Concha Leiva - Chile
"Querer, saber y hacer, es poder"
HB MSVSC + FWH 24.04 + MySQL/MaríaDB/DBFCDX (64 bits)
https://zenitx.com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: XBrowse con MySQL - no respeta Collation Latin1_spanish_ci
Posted: Fri May 01, 2026 07:18 AM

Estimado José,

Análisis del problema

El diagnóstico es correcto: FWMariaRowSet (y su clase padre FWRowSet) realizan ordenamiento en memoria del array ::aData usando ASort() de Harbour, que no respeta la collation latin1_spanish_ci de MySQL. Esto ocurre en varios puntos del código:

Causa raíz

1. Durante el SetUp() inicial, el RowSet parsea la cláusula ORDER BY del SQL y crea bloques de ordenamiento internos:

Code (prg): Select all Collapse
::aOrder := ::SortStr2Cols( AfterAtNum( "ORDER BY", Upper( ::Source ) ) )
::MakeSortBlocks( ::aOrder )
``` [0-cite-0](#0-cite-0) 

Esto establece `::nOrder` y `::bSort`, lo que significa que el RowSet "sabe" que hay un orden activo.

**2. En `SortData()`**, se ejecuta el re-ordenamiento en memoria con comparación binaria:

```prg
ASort( ::aData, nFrom, nLast, ::bSort )
``` [0-cite-1](#0-cite-1) 

**3. En `Requery()`**, después de recargar datos, si `::bSort` no está vacío, se llama a `::SortData()`, destruyendo el orden que trajo MySQL:

```prg
if ! Empty( ::bSort )
   ::SortData()
endif
``` [0-cite-2](#0-cite-2) 

**4. `SetXBrowse()` asigna automáticamente `cSortOrder`** a cada columna (línea 988), lo que habilita el ordenamiento al hacer clic en cabeceras:

```prg
:cSortOrder := cCol
``` [0-cite-3](#0-cite-3) 

**5. En `FWRowSet::SetOrder()`** (la clase padre), para campos de texto usa `StrICmp()` que es case-insensitive pero **no es locale-aware** (no respeta reglas de ñ, tildes, etc.):

```prg
ASort( ::aData, 1, nLimit, { |x,y| StrICmp( x[ nFld ], y[ nFld ] ) < 0 } )
``` [0-cite-4](#0-cite-4) 

---

### Soluciones posibles

#### Solución 1: Evitar el re-ordenamiento interno (la más práctica)

Después de crear el RowSet y antes de asignarlo al XBrowse, limpie el orden interno para que el RowSet no re-ordene los datos que ya vienen correctamente ordenados desde MySQL:

```prg
oRs := oCn:RowSet( cSql )  // datos vienen con ORDER BY correcto

// Limpiar el orden interno para que no re-ordene
oRs:aOrder := { 0 }
oRs:bSort  := nil

// Configurar XBrowse SIN autosort
XBROWSER oRs SETUP ( oBrw:lAutoSort := .f. )

Y después de SetXBrowse o CreateFromCode, limpie el cSortOrder de cada columna para evitar que al hacer clic en cabeceras se re-ordene:

Code (prg): Select all Collapse
// Después de CreateFromCode()
AEval( oBrw:aCols, { |oCol| oCol:cSortOrder := "" } )

Solución 2: No usar AUTOSORT y limpiar cSortOrder

Si construye el browse manualmente:

Code (prg): Select all Collapse
oRs := oCn:RowSet( cSql )

@ 0,0 XBROWSE oBrw OF oWnd ;
   COLUMNS "CAMPO1", "CAMPO2" ;
   LINES NOBORDER CELL

// NO usar AUTOSORT
// Limpiar cSortOrder de todas las columnas
AEval( oBrw:aCols, { |oCol| oCol:cSortOrder := "" } )

// Limpiar el sort interno del RowSet
oRs:aOrder := { 0 }
oRs:bSort  := nil

oBrw:CreateFromCode()

Solución 3: Re-ordenar desde el servidor al hacer clic en cabecera

Si necesita que el usuario pueda cambiar el orden haciendo clic en cabeceras pero respetando la collation, puede interceptar el evento de ordenamiento para hacer un Requery con un nuevo ORDER BY en lugar de ordenar en memoria:

Code (prg): Select all Collapse
// Después de configurar el browse:
oRs:aOrder := { 0 }
oRs:bSort  := nil
AEval( oBrw:aCols, { |oCol| oCol:cSortOrder := "" } )

// Si quiere re-habilitar sort por cabecera pero desde el servidor:
oBrw:bOnSort := { |oBrw, oCol| MyServerSort( oBrw, oCol ) }

Donde MyServerSort modifica el SQL con el nuevo ORDER BY y hace Requery() (asegurándose de limpiar bSort después del requery).


---

Resumen

El problema no es de XBrowse directamente, sino de FWMariaRowSet que:

  1. Parsea el ORDER BY del SQL y crea bloques de ordenamiento en memoria
  2. Usa ASort() con comparación binaria/StrICmp() que no respeta latin1_spanish_ci
  3. Re-aplica ese ordenamiento en Requery() y cuando se hace clic en cabeceras

La solución más directa es limpiar oRs:aOrder, oRs:bSort y los cSortOrder de las columnas del browse para que no se aplique ningún ordenamiento en memoria y se respete el orden que trae el ORDER BY de MySQL.

regards, saludos

Antonio Linares
www.fivetechsoft.com
Posts: 54
Joined: Sat Dec 10, 2016 08:58 PM
Re: XBrowse con MySQL - no respeta Collation Latin1_spanish_ci
Posted: Fri May 01, 2026 01:36 PM

Estimado Antonio

Hola. Gracias por la pronta y completa respuesta, haré lo que indicas y probaré.

Es una pena que el ordenamiento por cabecera sin tener que recargar no respete el collation en este caso; pero por algo será, y después de todo si la consulta está bien elaborada tampoco es tan lento realmente 'reordenar' las filas en el navegador.

Quizás podría aplicar esta solución de recargar solo para las columnas de texto, conservando el reordenamiento actual para las de fechas y números ¿desde tu perspectiva y experiencia te parece conveniente?

Gracias nuevamente. Saludos.

José Concha Leiva - Chile
"Querer, saber y hacer, es poder"
HB MSVSC + FWH 24.04 + MySQL/MaríaDB/DBFCDX (64 bits)
https://zenitx.com
Posts: 44158
Joined: Thu Oct 06, 2005 05:47 PM
Re: XBrowse con MySQL - no respeta Collation Latin1_spanish_ci
Posted: Fri May 01, 2026 03:17 PM

Estimado José,

No tengo experiencia en este tema, me he limitado a consultar DeepWiki sobre el repositorio de FWH.

Quien realmente conocía este tema es nuestro querido Rao, que ya no está entre nosotros

regards, saludos

Antonio Linares
www.fivetechsoft.com

Continue the discussion