B4J Code Snippet [B4J] SQLite Uppercase and Lowercase for Greek Letters - The Solution

Yeap, that's right - just found solution how you will manage the Greek Letters with SQLITE !

The solution is to turn them all in latin! But how will search the database ?

Here we are...

First of all you are goind to initialize the database...


sql.InitializeSQLite(File.DirApp, "datadb.db", False)
sql.ExecNonQuery("PRAGMA case_sensitive_like = ON;") ' ASCII case sensitive

CreateGreekLatinLower(sql)



B4X:
Public Sub CreateGreekLatinLower (SQLObj As SQL)
    Try
        Dim sqljo As JavaObject = SQLObj
        Dim conn As JavaObject = sqljo.GetField("connection")
     
        ' We extract the hidden 'ba' field from 'Me' dynamically
        Dim joMe As JavaObject = Me
        Dim actualBA As Object = joMe.GetField("ba")
        ' ----------------
     
        ' Now pass the actual object, not the string
        Me.As(JavaObject).RunMethod("registerGreekFunction", Array(conn, actualBA, "greeklower_cb"))
     
        Log("SQLite Function GREEKLATINLOWER registered successfully.")
    Catch
        Log("Error registering function: " & LastException.Message)
    End Try
End Sub

' Callback method - Called by the Java bridge
' IMPORTANT: This must be Public so the Java bridge can see it
Public Sub greeklower_cb (Input As String) As String
    If Input = "" Then Return ""
 
    ' Assuming 'b' is your object that handles Greek transformation
    ' Replace with your actual logic
    Return GreekToLatin(Input).ToLowerCase
End Sub


Public Sub GreekToLatin(greekText As String) As String
    Dim result As String = greekText


    result = result.Replace("Εί", "I")
    result = result.Replace("Οί", "I")
    result = result.Replace("Αί", "E")

    result = result.Replace("Ει", "I")
    result = result.Replace("Οι", "I")
    result = result.Replace("Αι", "E")
 
    result = result.Replace("ΕΙ", "I")
    result = result.Replace("ΟΙ", "I")
    result = result.Replace("ΑΙ", "E")

    result = result.Replace("ει", "i")
    result = result.Replace("οι", "i")
    result = result.Replace("αι", "e")
 
 
    ' ===== UPPERCASE WITH ACCENTS =====
    result = result.Replace("Ά", "A")
    result = result.Replace("Έ", "E")
    result = result.Replace("Ή", "I")
    result = result.Replace("Ί", "I")
    result = result.Replace("Ϊ", "I")
    result = result.Replace("Ϋ", "Y")
    result = result.Replace("Ό", "O")
    result = result.Replace("Ύ", "Y")
    result = result.Replace("Ώ", "O")
 
    ' ===== LOWERCASE WITH ACCENTS =====
    result = result.Replace("ά", "a")
    result = result.Replace("έ", "e")
    result = result.Replace("ή", "i")
    result = result.Replace("ί", "i")
    result = result.Replace("ϊ", "i")
    result = result.Replace("ϋ", "y")
    result = result.Replace("ό", "o")
    result = result.Replace("ύ", "y")
    result = result.Replace("ώ", "o")
 
    ' ===== UPPERCASE WITHOUT ACCENTS =====
    result = result.Replace("Α", "A")
    result = result.Replace("Β", "B")
    result = result.Replace("Γ", "G")
    result = result.Replace("Δ", "D")
    result = result.Replace("Ε", "E")
    result = result.Replace("Ζ", "Z")
    result = result.Replace("Η", "I")
    result = result.Replace("Θ", "TH")
    result = result.Replace("Ι", "I")
    result = result.Replace("Κ", "K")
    result = result.Replace("Λ", "L")
    result = result.Replace("Μ", "M")
    result = result.Replace("Ν", "N")
    result = result.Replace("Ξ", "KS")
    result = result.Replace("Ο", "O")
    result = result.Replace("Π", "P")
    result = result.Replace("Ρ", "R")
    result = result.Replace("Σ", "S")
    result = result.Replace("Τ", "T")
    result = result.Replace("Υ", "Y")
    result = result.Replace("Φ", "F")
    result = result.Replace("Χ", "CH")
    result = result.Replace("Ψ", "PS")
    result = result.Replace("Ω", "O")
 
    ' ===== LOWERCASE WITHOUT ACCENTS =====
    result = result.Replace("α", "a")
    result = result.Replace("β", "b")
    result = result.Replace("γ", "g")
    result = result.Replace("δ", "d")
    result = result.Replace("ε", "e")
    result = result.Replace("ζ", "z")
    result = result.Replace("η", "i")
    result = result.Replace("θ", "th")
    result = result.Replace("ι", "i")
    result = result.Replace("κ", "k")
    result = result.Replace("λ", "l")
    result = result.Replace("μ", "m")
    result = result.Replace("ν", "n")
    result = result.Replace("ξ", "ks")
    result = result.Replace("ο", "o")
    result = result.Replace("π", "p")
    result = result.Replace("ρ", "r")
    result = result.Replace("σ", "s")
    result = result.Replace("ς", "s")  ' Final sigma
    result = result.Replace("τ", "t")
    result = result.Replace("υ", "y")
    result = result.Replace("φ", "f")
    result = result.Replace("χ", "ch")
    result = result.Replace("ψ", "ps")
    result = result.Replace("ω", "o")
 
    Return result
end sub

#If JAVA
import java.sql.*;
import org.sqlite.Function;

public static void registerGreekFunction(Connection conn, final anywheresoftware.b4a.BA ba, final String subName) throws SQLException {
    Function.create(conn, "GREEKLATINLOWER", new Function() {
        @Override
        protected void xFunc() throws SQLException {
            try {
                // value_text(0) gets the first argument passed to the function
                String input = value_text(0);
             
                // Call the B4J Sub
                Object result = ba.raiseEvent(this, subName, new Object[] { input });
             
                // FIX: The method name is result(), not result_text()
                result(result == null ? "" : result.toString());
            } catch (Exception e) {
                // Fallback result on error
                result("");
                e.printStackTrace();
            }
        }
    });
}
#End If

what actually do GREEKLATINLOWER: let's say we have the Greek word: "Θεραπεία" - will turn at: "therapeia"
So... what's next - how will use it ? - now the fun part:

B4X:
dim sqlquery as string="SELECT * FROM MyTable WHERE GREEKLATINLOWER(myfield) LIKE ? ORDER BY myfield2;"
dim mysearch as string="%θεραπει%"
Dim cursor As ResultSet = Main.sql.ExecQuery2(sqlquery, mysearch)
Do While cursor.NextRow
....
* You can even mix greek-latin - perhaps αΣuS - > asus

If you are happy with my solution do not forget me!
 
Last edited:

aeric

Expert
Licensed User
Longtime User
Would it better or faster to use a Map for the key-value pairs?
 

aeric

Expert
Licensed User
Longtime User
Refactored by Gemini:
B4X:
Public Sub GreekToLatin (greekText As String) As String
    If greekText = "" Then Return ""
   
    Dim result As String = greekText
   
    ' We define the Map. Note: B4X Map doesn't guarantee order,
    ' so we list diphthongs first and then single letters.
    Dim mappings As Map
    mappings.Initialize
   
    ' ===== DIPHTHONGS FIRST =====
    ' (To ensure "ει" is caught before "ε" and "ι" individually)
    Dim diphthongs As Map = CreateMap("Εί": "I", "Οί": "I", "Αί": "E", "Ει": "I", "Οι": "I", "Αι": "E", "ΕΙ": "I", "ΟΙ": "I", "ΑΙ": "E", "ει": "i", "οι": "i", "αι": "e")
   
    ' ===== ACCENTS =====
    Dim accents As Map = CreateMap("Ά": "A", "Έ": "E", "Ή": "I", "Ί": "I", "Ϊ": "I", "Ϋ": "Y", "Ό": "O", "Ύ": "Y", "Ώ": "O", "ά": "a", "έ": "e", "ή": "i", "ί": "i", "ϊ": "i", "ϋ": "y", "ό": "o", "ύ": "y", "ώ": "o")
   
    ' ===== SINGLE LETTERS =====
    Dim singles As Map = CreateMap("Α": "A", "Β": "B", "Γ": "G", "Δ": "D", "Ε": "E", "Ζ": "Z", "Η": "I", "Θ": "TH", "Ι": "I", "Κ": "K", "Λ": "L", "Μ": "M", "Ν": "N", "Ξ": "KS", "Ο": "O", "Π": "P", "Ρ": "R", "Σ": "S", "Τ": "T", "Υ": "Y", "Φ": "F", "Χ": "CH", "Ψ": "PS", "Ω": "O")
    Dim singlesLow As Map = CreateMap("α": "a", "β": "b", "γ": "g", "δ": "d", "ε": "e", "ζ": "z", "η": "i", "θ": "th", "ι": "i", "κ": "k", "λ": "l", "μ": "m", "ν": "n", "ξ": "ks", "ο": "o", "π": "p", "ρ": "r", "σ": "s", "ς": "s", "τ": "t", "υ": "y", "φ": "f", "χ": "ch", "ψ": "ps", "ω": "o")

    ' Process them in order of priority
    result = ReplaceFromMap(result, diphthongs)
    result = ReplaceFromMap(result, accents)
    result = ReplaceFromMap(result, singles)
    result = ReplaceFromMap(result, singlesLow)
   
    Return result
End Sub

' Helper routine to keep the main sub clean
Private Sub ReplaceFromMap (Text As String, M As Map) As String
    For Each k As String In M.Keys
        Text = Text.Replace(k, M.Get(k))
    Next
    Return Text
End Sub

Take note, your GreekToLatin sub missing Return result at the end of sub.
 

Magma

Expert
Licensed User
Longtime User
ya! didn't copy-paste (also end sub if you see is lowercase.... put it by hand ) Thanks!
 

Magma

Expert
Licensed User
Longtime User
well...

I ve asked AI which method will be faster for this...

1. my method: no hash lookup - only serial replacing - so compiler doing inlining/optimization
2. aeric's method: (if-condition) / hash lookup +15~20% (slower)
3. containskey: comes last - Branching (if-condition) / hash lookup (this will be faster only if wasn't one or two characters searching) (+20%~ slower)

Also if creating map in different sub (for only one time creation) the result is again 5% slower than the 1st...

Hmm interesting... sometimes simple solutions are faster... (but all these said by AI)
 
Cookies are required to use this site. You must accept them to continue using the site. Learn more…