github.com/ncruces/go-sqlite3@v0.15.1-0.20240520133447-53eef1510ff0/ext/unicode/unicode_test.go (about)

     1  package unicode
     2  
     3  import (
     4  	"errors"
     5  	"reflect"
     6  	"testing"
     7  
     8  	"github.com/ncruces/go-sqlite3"
     9  	_ "github.com/ncruces/go-sqlite3/embed"
    10  	_ "github.com/ncruces/go-sqlite3/tests/testcfg"
    11  )
    12  
    13  func TestRegister(t *testing.T) {
    14  	t.Parallel()
    15  
    16  	db, err := sqlite3.Open(":memory:")
    17  	if err != nil {
    18  		t.Fatal(err)
    19  	}
    20  	defer db.Close()
    21  
    22  	exec := func(fn string) string {
    23  		stmt, _, err := db.Prepare(`SELECT ` + fn)
    24  		if err != nil {
    25  			t.Fatal(err)
    26  		}
    27  		defer stmt.Close()
    28  
    29  		if stmt.Step() {
    30  			return stmt.ColumnText(0)
    31  		}
    32  		t.Fatal(stmt.Err())
    33  		return ""
    34  	}
    35  
    36  	Register(db)
    37  
    38  	tests := []struct {
    39  		test string
    40  		want string
    41  	}{
    42  		{`upper('hello')`, "HELLO"},
    43  		{`lower('HELLO')`, "hello"},
    44  		{`upper('привет')`, "ПРИВЕТ"},
    45  		{`lower('ПРИВЕТ')`, "привет"},
    46  		{`upper('istanbul')`, "ISTANBUL"},
    47  		{`upper('istanbul', 'tr-TR')`, "İSTANBUL"},
    48  		{`lower('Dünyanın İlk Borsası', 'tr-TR')`, "dünyanın ilk borsası"},
    49  		{`upper('Dünyanın İlk Borsası', 'tr-TR')`, "DÜNYANIN İLK BORSASI"},
    50  		{`'Hello' REGEXP 'ell'`, "1"},
    51  		{`'Hello' REGEXP 'el.'`, "1"},
    52  		{`'Hello' LIKE 'hel_'`, "0"},
    53  		{`'Hello' LIKE 'hel%'`, "1"},
    54  		{`'Hello' LIKE 'h_llo'`, "1"},
    55  		{`'Hello' LIKE 'hello'`, "1"},
    56  		{`'Привет' LIKE 'ПРИВЕТ'`, "1"},
    57  		{`'100%' LIKE '100|%' ESCAPE '|'`, "1"},
    58  	}
    59  
    60  	for _, tt := range tests {
    61  		t.Run(tt.test, func(t *testing.T) {
    62  			if got := exec(tt.test); got != tt.want {
    63  				t.Errorf("exec(%q) = %q, want %q", tt.test, got, tt.want)
    64  			}
    65  		})
    66  	}
    67  
    68  	err = db.Close()
    69  	if err != nil {
    70  		t.Fatal(err)
    71  	}
    72  }
    73  
    74  func TestRegister_collation(t *testing.T) {
    75  	t.Parallel()
    76  
    77  	db, err := sqlite3.Open(":memory:")
    78  	if err != nil {
    79  		t.Fatal(err)
    80  	}
    81  	defer db.Close()
    82  
    83  	Register(db)
    84  
    85  	err = db.Exec(`CREATE TABLE words (word VARCHAR(10))`)
    86  	if err != nil {
    87  		t.Fatal(err)
    88  	}
    89  
    90  	err = db.Exec(`INSERT INTO words (word) VALUES ('côte'), ('cote'), ('coter'), ('coté'), ('cotée'), ('côté')`)
    91  	if err != nil {
    92  		t.Fatal(err)
    93  	}
    94  
    95  	err = db.Exec(`SELECT icu_load_collation('fr_FR', 'french')`)
    96  	if err != nil {
    97  		t.Fatal(err)
    98  	}
    99  
   100  	stmt, _, err := db.Prepare(`SELECT word FROM words ORDER BY word COLLATE french`)
   101  	if err != nil {
   102  		t.Fatal(err)
   103  	}
   104  	defer stmt.Close()
   105  
   106  	got, want := []string{}, []string{"cote", "coté", "côte", "côté", "cotée", "coter"}
   107  
   108  	for stmt.Step() {
   109  		got = append(got, stmt.ColumnText(0))
   110  	}
   111  	if err := stmt.Err(); err != nil {
   112  		t.Fatal(err)
   113  	}
   114  
   115  	if !reflect.DeepEqual(got, want) {
   116  		t.Error("not equal")
   117  	}
   118  
   119  	err = stmt.Close()
   120  	if err != nil {
   121  		t.Fatal(err)
   122  	}
   123  
   124  	err = db.Close()
   125  	if err != nil {
   126  		t.Fatal(err)
   127  	}
   128  }
   129  
   130  func TestRegister_error(t *testing.T) {
   131  	t.Parallel()
   132  
   133  	db, err := sqlite3.Open(":memory:")
   134  	if err != nil {
   135  		t.Fatal(err)
   136  	}
   137  	defer db.Close()
   138  
   139  	Register(db)
   140  
   141  	err = db.Exec(`SELECT upper('hello', 'enUS')`)
   142  	if err == nil {
   143  		t.Error("want error")
   144  	}
   145  	if !errors.Is(err, sqlite3.ERROR) {
   146  		t.Errorf("got %v, want sqlite3.ERROR", err)
   147  	}
   148  
   149  	err = db.Exec(`SELECT lower('hello', 'enUS')`)
   150  	if err == nil {
   151  		t.Error("want error")
   152  	}
   153  	if !errors.Is(err, sqlite3.ERROR) {
   154  		t.Errorf("got %v, want sqlite3.ERROR", err)
   155  	}
   156  
   157  	err = db.Exec(`SELECT 'hello' REGEXP '\'`)
   158  	if err == nil {
   159  		t.Error("want error")
   160  	}
   161  	if !errors.Is(err, sqlite3.ERROR) {
   162  		t.Errorf("got %v, want sqlite3.ERROR", err)
   163  	}
   164  
   165  	err = db.Exec(`SELECT 'hello' LIKE 'HELLO' ESCAPE '\\'`)
   166  	if err == nil {
   167  		t.Error("want error")
   168  	}
   169  	if !errors.Is(err, sqlite3.ERROR) {
   170  		t.Errorf("got %v, want sqlite3.ERROR", err)
   171  	}
   172  
   173  	err = db.Exec(`SELECT icu_load_collation('enUS', 'error')`)
   174  	if err == nil {
   175  		t.Error("want error")
   176  	}
   177  	if !errors.Is(err, sqlite3.ERROR) {
   178  		t.Errorf("got %v, want sqlite3.ERROR", err)
   179  	}
   180  
   181  	err = db.Exec(`SELECT icu_load_collation('enUS', '')`)
   182  	if err != nil {
   183  		t.Error(err)
   184  	}
   185  
   186  	err = db.Close()
   187  	if err != nil {
   188  		t.Fatal(err)
   189  	}
   190  }
   191  
   192  func Test_like2regex(t *testing.T) {
   193  	t.Parallel()
   194  
   195  	const prefix = `(?is)\A`
   196  	const sufix = `\z`
   197  	tests := []struct {
   198  		pattern string
   199  		escape  rune
   200  		want    string
   201  	}{
   202  		{`a`, -1, `a`},
   203  		{`a.`, -1, `a\.`},
   204  		{`a%`, -1, `a.*`},
   205  		{`a\`, -1, `a\\`},
   206  		{`a_b`, -1, `a.b`},
   207  		{`a|b`, '|', `ab`},
   208  		{`a|_`, '|', `a_`},
   209  	}
   210  	for _, tt := range tests {
   211  		t.Run(tt.pattern, func(t *testing.T) {
   212  			want := prefix + tt.want + sufix
   213  			if got := like2regex(tt.pattern, tt.escape); got != want {
   214  				t.Errorf("like2regex() = %q, want %q", got, want)
   215  			}
   216  		})
   217  	}
   218  }