Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gosqlite
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
gosqlite
Commits
eb69bb64
Commit
eb69bb64
authored
Apr 19, 2013
by
gwenn
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix Conn.LastError & somes tests.
parent
434394c3
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
404 additions
and
285 deletions
+404
-285
backup_test.go
backup_test.go
+5
-1
bench_test.go
bench_test.go
+49
-33
example_test.go
example_test.go
+5
-0
sqlite.go
sqlite.go
+5
-1
sqlite_test.go
sqlite_test.go
+18
-250
stmt_test.go
stmt_test.go
+322
-0
No files found.
backup_test.go
View file @
eb69bb64
...
@@ -14,16 +14,20 @@ func TestBackup(t *testing.T) {
...
@@ -14,16 +14,20 @@ func TestBackup(t *testing.T) {
defer
checkClose
(
dst
,
t
)
defer
checkClose
(
dst
,
t
)
src
:=
open
(
t
)
src
:=
open
(
t
)
defer
checkClose
(
src
,
t
)
defer
checkClose
(
src
,
t
)
fill
(
src
,
1000
)
fill
(
nil
,
src
,
1000
)
bck
,
err
:=
NewBackup
(
dst
,
"main"
,
src
,
"main"
)
bck
,
err
:=
NewBackup
(
dst
,
"main"
,
src
,
"main"
)
checkNoError
(
t
,
err
,
"couldn't init backup: %#v"
)
checkNoError
(
t
,
err
,
"couldn't init backup: %#v"
)
cbs
:=
make
(
chan
BackupStatus
)
cbs
:=
make
(
chan
BackupStatus
)
defer
close
(
cbs
)
go
func
()
{
go
func
()
{
for
{
for
{
s
:=
<-
cbs
s
:=
<-
cbs
t
.
Logf
(
"Backup progress %#v
\n
"
,
s
)
t
.
Logf
(
"Backup progress %#v
\n
"
,
s
)
if
s
.
Remaining
==
0
{
break
}
}
}
}()
}()
err
=
bck
.
Run
(
10
,
0
,
cbs
)
err
=
bck
.
Run
(
10
,
0
,
cbs
)
...
...
bench_test.go
View file @
eb69bb64
...
@@ -9,26 +9,35 @@ import (
...
@@ -9,26 +9,35 @@ import (
"testing"
"testing"
)
)
func
fill
(
db
*
Conn
,
n
int
)
{
func
panicOnError
(
b
*
testing
.
B
,
err
error
)
{
db
.
Exec
(
"DROP TABLE IF EXISTS test"
)
if
err
!=
nil
{
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, float_num REAL, int_num INTEGER, a_string TEXT)"
)
panic
(
err
)
s
,
_
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)"
)
}
}
func
fill
(
b
*
testing
.
B
,
db
*
Conn
,
n
int
)
{
panicOnError
(
b
,
db
.
Exec
(
"DROP TABLE IF EXISTS test"
))
panicOnError
(
b
,
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL, float_num REAL, int_num INTEGER, a_string TEXT)"
))
s
,
err
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (?, ?, ?)"
)
panicOnError
(
b
,
err
)
db
.
Begin
(
)
panicOnError
(
b
,
db
.
Begin
()
)
for
i
:=
0
;
i
<
n
;
i
++
{
for
i
:=
0
;
i
<
n
;
i
++
{
s
.
Exec
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
panicOnError
(
b
,
s
.
Exec
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
)
}
}
s
.
Finalize
(
)
panicOnError
(
b
,
s
.
Finalize
()
)
db
.
Commit
(
)
panicOnError
(
b
,
db
.
Commit
()
)
}
}
func
BenchmarkValuesScan
(
b
*
testing
.
B
)
{
func
BenchmarkValuesScan
(
b
*
testing
.
B
)
{
b
.
StopTimer
()
b
.
StopTimer
()
db
,
_
:=
Open
(
":memory:"
)
db
,
err
:=
Open
(
":memory:"
)
panicOnError
(
b
,
err
)
defer
db
.
Close
()
defer
db
.
Close
()
fill
(
db
,
1
)
fill
(
b
,
db
,
1
)
cs
,
_
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test"
)
cs
,
err
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test"
)
panicOnError
(
b
,
err
)
defer
cs
.
Finalize
()
defer
cs
.
Finalize
()
b
.
StartTimer
()
b
.
StartTimer
()
...
@@ -38,17 +47,19 @@ func BenchmarkValuesScan(b *testing.B) {
...
@@ -38,17 +47,19 @@ func BenchmarkValuesScan(b *testing.B) {
if
Must
(
cs
.
Next
())
{
if
Must
(
cs
.
Next
())
{
cs
.
ScanValues
(
values
)
cs
.
ScanValues
(
values
)
}
}
cs
.
Reset
(
)
panicOnError
(
b
,
cs
.
Reset
()
)
}
}
}
}
func
BenchmarkScan
(
b
*
testing
.
B
)
{
func
BenchmarkScan
(
b
*
testing
.
B
)
{
b
.
StopTimer
()
b
.
StopTimer
()
db
,
_
:=
Open
(
":memory:"
)
db
,
err
:=
Open
(
":memory:"
)
panicOnError
(
b
,
err
)
defer
db
.
Close
()
defer
db
.
Close
()
fill
(
db
,
1
)
fill
(
b
,
db
,
1
)
cs
,
_
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test"
)
cs
,
err
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test"
)
panicOnError
(
b
,
err
)
defer
cs
.
Finalize
()
defer
cs
.
Finalize
()
b
.
StartTimer
()
b
.
StartTimer
()
...
@@ -59,19 +70,21 @@ func BenchmarkScan(b *testing.B) {
...
@@ -59,19 +70,21 @@ func BenchmarkScan(b *testing.B) {
var
sstr
string
var
sstr
string
if
Must
(
cs
.
Next
())
{
if
Must
(
cs
.
Next
())
{
cs
.
Scan
(
&
fnum
,
&
inum
,
&
sstr
)
panicOnError
(
b
,
cs
.
Scan
(
&
fnum
,
&
inum
,
&
sstr
)
)
}
}
cs
.
Reset
(
)
panicOnError
(
b
,
cs
.
Reset
()
)
}
}
}
}
func
BenchmarkNamedScan
(
b
*
testing
.
B
)
{
func
BenchmarkNamedScan
(
b
*
testing
.
B
)
{
b
.
StopTimer
()
b
.
StopTimer
()
db
,
_
:=
Open
(
":memory:"
)
db
,
err
:=
Open
(
":memory:"
)
panicOnError
(
b
,
err
)
defer
db
.
Close
()
defer
db
.
Close
()
fill
(
db
,
1
)
fill
(
b
,
db
,
1
)
cs
,
_
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test"
)
cs
,
err
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test"
)
panicOnError
(
b
,
err
)
defer
cs
.
Finalize
()
defer
cs
.
Finalize
()
b
.
StartTimer
()
b
.
StartTimer
()
...
@@ -82,32 +95,35 @@ func BenchmarkNamedScan(b *testing.B) {
...
@@ -82,32 +95,35 @@ func BenchmarkNamedScan(b *testing.B) {
var
sstr
string
var
sstr
string
if
Must
(
cs
.
Next
())
{
if
Must
(
cs
.
Next
())
{
cs
.
NamedScan
(
"float_num"
,
&
fnum
,
"int_num"
,
&
inum
,
"a_string"
,
&
sstr
)
panicOnError
(
b
,
cs
.
NamedScan
(
"float_num"
,
&
fnum
,
"int_num"
,
&
inum
,
"a_string"
,
&
sstr
)
)
}
}
cs
.
Reset
(
)
panicOnError
(
b
,
cs
.
Reset
()
)
}
}
}
}
func
BenchmarkInsert
(
b
*
testing
.
B
)
{
func
BenchmarkInsert
(
b
*
testing
.
B
)
{
db
,
_
:=
Open
(
":memory:"
)
db
,
err
:=
Open
(
":memory:"
)
panicOnError
(
b
,
err
)
defer
db
.
Close
()
defer
db
.
Close
()
fill
(
db
,
b
.
N
)
fill
(
b
,
db
,
b
.
N
)
}
}
func
BenchmarkNamedInsert
(
b
*
testing
.
B
)
{
func
BenchmarkNamedInsert
(
b
*
testing
.
B
)
{
db
,
_
:=
Open
(
":memory:"
)
db
,
err
:=
Open
(
":memory:"
)
panicOnError
(
b
,
err
)
defer
db
.
Close
()
defer
db
.
Close
()
db
.
Exec
(
"DROP TABLE IF EXISTS test"
)
panicOnError
(
b
,
db
.
Exec
(
"DROP TABLE IF EXISTS test"
)
)
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL,"
+
panicOnError
(
b
,
db
.
Exec
(
"CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL,"
+
" float_num REAL, int_num INTEGER, a_string TEXT)"
)
" float_num REAL, int_num INTEGER, a_string TEXT)"
)
)
s
,
_
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string)"
+
s
,
err
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string)"
+
" VALUES (:f, :i, :s)"
)
" VALUES (:f, :i, :s)"
)
panicOnError
(
b
,
err
)
defer
s
.
Finalize
()
defer
s
.
Finalize
()
db
.
Begin
(
)
panicOnError
(
b
,
db
.
Begin
()
)
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
for
i
:=
0
;
i
<
b
.
N
;
i
++
{
s
.
NamedBind
(
"f"
,
float64
(
i
)
*
float64
(
3.14
),
"i"
,
i
,
"s"
,
"hello"
)
panicOnError
(
b
,
s
.
NamedBind
(
":f"
,
float64
(
i
)
*
float64
(
3.14
),
":i"
,
i
,
":s"
,
"hello"
)
)
s
.
Next
(
)
Must
(
s
.
Next
()
)
}
}
db
.
Commit
(
)
panicOnError
(
b
,
db
.
Commit
()
)
}
}
example_test.go
View file @
eb69bb64
...
@@ -164,12 +164,17 @@ func ExampleNewBackup() {
...
@@ -164,12 +164,17 @@ func ExampleNewBackup() {
defer
bck
.
Close
()
defer
bck
.
Close
()
cbs
:=
make
(
chan
sqlite
.
BackupStatus
)
cbs
:=
make
(
chan
sqlite
.
BackupStatus
)
defer
close
(
cbs
)
ack
:=
make
(
chan
bool
)
ack
:=
make
(
chan
bool
)
defer
close
(
ack
)
go
func
()
{
go
func
()
{
for
{
for
{
s
:=
<-
cbs
s
:=
<-
cbs
fmt
.
Printf
(
"backup progress (remaining: %d)
\n
"
,
s
.
Remaining
)
fmt
.
Printf
(
"backup progress (remaining: %d)
\n
"
,
s
.
Remaining
)
ack
<-
true
ack
<-
true
if
s
.
Remaining
==
0
{
break
}
}
}
}()
}()
err
=
bck
.
Run
(
100
,
250000
,
cbs
)
err
=
bck
.
Run
(
100
,
250000
,
cbs
)
...
...
sqlite.go
View file @
eb69bb64
...
@@ -157,7 +157,11 @@ func (c *Conn) LastError() error {
...
@@ -157,7 +157,11 @@ func (c *Conn) LastError() error {
if
c
==
nil
{
if
c
==
nil
{
return
errors
.
New
(
"nil sqlite database"
)
return
errors
.
New
(
"nil sqlite database"
)
}
}
return
&
ConnError
{
c
:
c
,
code
:
Errno
(
C
.
sqlite3_errcode
(
c
.
db
)),
msg
:
C
.
GoString
(
C
.
sqlite3_errmsg
(
c
.
db
))}
errorCode
:=
C
.
sqlite3_errcode
(
c
.
db
)
if
errorCode
==
C
.
SQLITE_OK
{
return
nil
}
return
&
ConnError
{
c
:
c
,
code
:
Errno
(
errorCode
),
msg
:
C
.
GoString
(
C
.
sqlite3_errmsg
(
c
.
db
))}
}
}
// Database connection handle
// Database connection handle
...
...
sqlite_test.go
View file @
eb69bb64
...
@@ -27,7 +27,9 @@ func open(t *testing.T) *Conn {
...
@@ -27,7 +27,9 @@ func open(t *testing.T) *Conn {
//db.SetSynchronous("", 0)
//db.SetSynchronous("", 0)
//db.Profile(profile, t)
//db.Profile(profile, t)
//db.Trace(trace, t)
//db.Trace(trace, t)
//db.SetAuthorizer(authorizer, t)
if
testing
.
Verbose
()
{
db
.
SetAuthorizer
(
authorizer
,
t
)
}
return
db
return
db
}
}
...
@@ -35,10 +37,6 @@ func checkClose(db *Conn, t *testing.T) {
...
@@ -35,10 +37,6 @@ func checkClose(db *Conn, t *testing.T) {
checkNoError
(
t
,
db
.
Close
(),
"Error closing database: %s"
)
checkNoError
(
t
,
db
.
Close
(),
"Error closing database: %s"
)
}
}
func
checkFinalize
(
s
*
Stmt
,
t
*
testing
.
T
)
{
checkNoError
(
t
,
s
.
Finalize
(),
"Error finalizing statement: %s"
)
}
func
createTable
(
db
*
Conn
,
t
*
testing
.
T
)
{
func
createTable
(
db
*
Conn
,
t
*
testing
.
T
)
{
err
:=
db
.
Exec
(
"DROP TABLE IF EXISTS test;"
+
err
:=
db
.
Exec
(
"DROP TABLE IF EXISTS test;"
+
"CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL,"
+
"CREATE TABLE test (id INTEGER PRIMARY KEY NOT NULL,"
+
...
@@ -145,6 +143,7 @@ func TestInsert(t *testing.T) {
...
@@ -145,6 +143,7 @@ func TestInsert(t *testing.T) {
if
!
Must
(
cs
.
Next
())
{
if
!
Must
(
cs
.
Next
())
{
t
.
Fatal
(
"no result for count"
)
t
.
Fatal
(
"no result for count"
)
}
}
assertEquals
(
t
,
"column & data count not equal: %d versus %d"
,
columnCount
,
cs
.
DataCount
())
var
i
int
var
i
int
checkNoError
(
t
,
cs
.
Scan
(
&
i
),
"error scanning count: %s"
)
checkNoError
(
t
,
cs
.
Scan
(
&
i
),
"error scanning count: %s"
)
assertEquals
(
t
,
"count should be %d, but it is %d"
,
1000
,
i
)
assertEquals
(
t
,
"count should be %d, but it is %d"
,
1000
,
i
)
...
@@ -154,145 +153,6 @@ func TestInsert(t *testing.T) {
...
@@ -154,145 +153,6 @@ func TestInsert(t *testing.T) {
assert
(
t
,
"Statement not reset"
,
!
cs
.
Busy
())
assert
(
t
,
"Statement not reset"
,
!
cs
.
Busy
())
}
}
func
TestInsertWithStatement
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
createTable
(
db
,
t
)
s
,
serr
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (:f, :i, :s)"
)
checkNoError
(
t
,
serr
,
"prepare error: %s"
)
if
s
==
nil
{
t
.
Fatal
(
"statement is nil"
)
}
defer
checkFinalize
(
s
,
t
)
assert
(
t
,
"update statement should not be readonly"
,
!
s
.
ReadOnly
())
paramCount
:=
s
.
BindParameterCount
()
assertEquals
(
t
,
"bind parameter count error: expected %d but got %d"
,
3
,
paramCount
)
firstParamName
,
berr
:=
s
.
BindParameterName
(
1
)
checkNoError
(
t
,
berr
,
"error binding: %s"
)
assertEquals
(
t
,
"bind parameter name error: expected %s but got %s"
,
":f"
,
firstParamName
/*, berr*/
)
lastParamIndex
,
berr
:=
s
.
BindParameterIndex
(
":s"
)
checkNoError
(
t
,
berr
,
"error binding: %s"
)
assertEquals
(
t
,
"bind parameter index error: expected %d but got %d"
,
3
,
lastParamIndex
/*, berr*/
)
columnCount
:=
s
.
ColumnCount
()
assertEquals
(
t
,
"column count error: expected %d but got %d"
,
0
,
columnCount
)
db
.
Begin
()
for
i
:=
0
;
i
<
1000
;
i
++
{
c
,
ierr
:=
s
.
ExecDml
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
checkNoError
(
t
,
ierr
,
"insert error: %s"
)
assertEquals
(
t
,
"insert error: expected %d changes but got %d"
,
1
,
c
)
assert
(
t
,
"Statement not reset"
,
!
s
.
Busy
())
}
checkNoError
(
t
,
db
.
Commit
(),
"Error: %s"
)
cs
,
_
:=
db
.
Prepare
(
"SELECT COUNT(*) FROM test"
)
defer
checkFinalize
(
cs
,
t
)
assert
(
t
,
"select statement should be readonly"
,
cs
.
ReadOnly
())
if
!
Must
(
cs
.
Next
())
{
t
.
Fatal
(
"no result for count"
)
}
var
i
int
checkNoError
(
t
,
cs
.
Scan
(
&
i
),
"error scanning count: %s"
)
assertEquals
(
t
,
"count should be %d, but it is %d"
,
1000
,
i
)
rs
,
_
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test where a_string like ? ORDER BY int_num LIMIT 2"
,
"hel%"
)
defer
checkFinalize
(
rs
,
t
)
columnCount
=
rs
.
ColumnCount
()
assertEquals
(
t
,
"column count error: expected %d but got %d"
,
3
,
columnCount
)
secondColumnName
:=
rs
.
ColumnName
(
1
)
assertEquals
(
t
,
"column name error: expected %s but got %s"
,
"int_num"
,
secondColumnName
)
if
Must
(
rs
.
Next
())
{
var
fnum
float64
var
inum
int64
var
sstr
string
rs
.
Scan
(
&
fnum
,
&
inum
,
&
sstr
)
assertEquals
(
t
,
"expected %f but got %f"
,
float64
(
0
),
fnum
)
assertEquals
(
t
,
"expected %d but got %d"
,
int64
(
0
),
inum
)
assertEquals
(
t
,
"expected %q but got %q"
,
"hello"
,
sstr
)
}
if
Must
(
rs
.
Next
())
{
var
fnum
float64
var
inum
int64
var
sstr
string
rs
.
NamedScan
(
"a_string"
,
&
sstr
,
"float_num"
,
&
fnum
,
"int_num"
,
&
inum
)
assertEquals
(
t
,
"expected %f but got %f"
,
float64
(
3.14
),
fnum
)
assertEquals
(
t
,
"expected %d but got %d"
,
int64
(
1
),
inum
)
assertEquals
(
t
,
"expected %q but got %q"
,
"hello"
,
sstr
)
}
assert
(
t
,
"expected full scan"
,
999
==
rs
.
Status
(
StmtStatusFullScanStep
,
false
))
assert
(
t
,
"expected one sort"
,
1
==
rs
.
Status
(
StmtStatusSort
,
false
))
assert
(
t
,
"expected no auto index"
,
0
==
rs
.
Status
(
StmtStatusAutoIndex
,
false
))
}
func
TestScanColumn
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
s
,
err
:=
db
.
Prepare
(
"select 1, null, 0"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
checkFinalize
(
s
,
t
)
if
!
Must
(
s
.
Next
())
{
t
.
Fatal
(
"no result"
)
}
var
i1
,
i2
,
i3
int
null
:=
Must
(
s
.
ScanByIndex
(
0
,
&
i1
))
assert
(
t
,
"expected not null value"
,
!
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
1
,
i1
)
null
=
Must
(
s
.
ScanByIndex
(
1
,
&
i2
))
assert
(
t
,
"expected null value"
,
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
0
,
i2
)
null
=
Must
(
s
.
ScanByIndex
(
2
,
&
i3
))
assert
(
t
,
"expected not null value"
,
!
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
0
,
i3
)
}
func
TestNamedScanColumn
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
s
,
err
:=
db
.
Prepare
(
"select 1 as i1, null as i2, 0 as i3"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
checkFinalize
(
s
,
t
)
if
!
Must
(
s
.
Next
())
{
t
.
Fatal
(
"no result"
)
}
var
i1
,
i2
,
i3
int
null
:=
Must
(
s
.
ScanByName
(
"i1"
,
&
i1
))
assert
(
t
,
"expected not null value"
,
!
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
1
,
i1
)
null
=
Must
(
s
.
ScanByName
(
"i2"
,
&
i2
))
assert
(
t
,
"expected null value"
,
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
0
,
i2
)
null
=
Must
(
s
.
ScanByName
(
"i3"
,
&
i3
))
assert
(
t
,
"expected not null value"
,
!
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
0
,
i3
)
}
func
TestScanCheck
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
s
,
err
:=
db
.
Prepare
(
"select 'hello'"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
checkFinalize
(
s
,
t
)
if
!
Must
(
s
.
Next
())
{
t
.
Fatal
(
"no result"
)
}
var
i
int
_
,
err
=
s
.
ScanByIndex
(
0
,
&
i
)
if
serr
,
ok
:=
err
.
(
*
StmtError
);
ok
{
assertEquals
(
t
,
"expected %q but got %q"
,
""
,
serr
.
Filename
())
assertEquals
(
t
,
"expected %q but got %q"
,
ErrSpecific
,
serr
.
Code
())
assertEquals
(
t
,
"expected %q but got %q"
,
s
.
SQL
(),
serr
.
SQL
())
}
else
{
t
.
Errorf
(
"Expected StmtError but got %s"
,
reflect
.
TypeOf
(
err
))
}
}
/*
/*
func TestLoadExtension(t *testing.T) {
func TestLoadExtension(t *testing.T) {
db := open(t)
db := open(t)
...
@@ -304,70 +164,6 @@ func TestLoadExtension(t *testing.T) {
...
@@ -304,70 +164,6 @@ func TestLoadExtension(t *testing.T) {
}
}
*/
*/
func
TestScanNull
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
s
,
err
:=
db
.
Prepare
(
"select null"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
checkFinalize
(
s
,
t
)
if
!
Must
(
s
.
Next
())
{
t
.
Fatal
(
"no result"
)
}
var
pi
*
int
=
new
(
int
)
null
:=
Must
(
s
.
ScanByIndex
(
0
,
&
pi
))
assert
(
t
,
"expected null value"
,
null
)
assertEquals
(
t
,
"expected nil (%p) but got %p"
,
(
*
int
)(
nil
),
pi
)
var
ps
*
string
=
new
(
string
)
null
=
Must
(
s
.
ScanByIndex
(
0
,
&
ps
))
assert
(
t
,
"expected null value"
,
null
)
assertEquals
(
t
,
"expected nil (%p) but got %p"
,
(
*
string
)(
nil
),
ps
)
}
func
TestScanNotNull
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
s
,
err
:=
db
.
Prepare
(
"select 1"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
checkFinalize
(
s
,
t
)
if
!
Must
(
s
.
Next
())
{
t
.
Fatal
(
"no result"
)
}
var
pi
*
int
=
new
(
int
)
null
:=
Must
(
s
.
ScanByIndex
(
0
,
&
pi
))
assert
(
t
,
"expected not null value"
,
!
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
1
,
*
pi
)
var
ps
*
string
=
new
(
string
)
null
=
Must
(
s
.
ScanByIndex
(
0
,
&
ps
))
assert
(
t
,
"expected not null value"
,
!
null
)
assertEquals
(
t
,
"expected %s but got %s"
,
"1"
,
*
ps
)
}
func
TestCloseTwice
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
s
,
err
:=
db
.
Prepare
(
"SELECT 1"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
err
=
s
.
Finalize
()
checkNoError
(
t
,
err
,
"finalize error: %s"
)
err
=
s
.
Finalize
()
checkNoError
(
t
,
err
,
"finalize error: %s"
)
err
=
db
.
Close
()
checkNoError
(
t
,
err
,
"close error: %s"
)
err
=
db
.
Close
()
checkNoError
(
t
,
err
,
"close error: %s"
)
}
func
TestStmtMisuse
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
s
,
err
:=
db
.
Prepare
(
"MISUSE"
)
assert
(
t
,
"error expected"
,
s
==
nil
&&
err
!=
nil
)
err
=
s
.
Finalize
()
assert
(
t
,
"error expected"
,
err
!=
nil
)
}
func
TestOpenSameMemoryDb
(
t
*
testing
.
T
)
{
func
TestOpenSameMemoryDb
(
t
*
testing
.
T
)
{
db1
,
err
:=
Open
(
"file:dummy.db?mode=memory&cache=shared"
,
OpenUri
,
OpenReadWrite
,
OpenCreate
,
OpenFullMutex
)
db1
,
err
:=
Open
(
"file:dummy.db?mode=memory&cache=shared"
,
OpenUri
,
OpenReadWrite
,
OpenCreate
,
OpenFullMutex
)
checkNoError
(
t
,
err
,
"open error: %s"
)
checkNoError
(
t
,
err
,
"open error: %s"
)
...
@@ -382,24 +178,6 @@ func TestOpenSameMemoryDb(t *testing.T) {
...
@@ -382,24 +178,6 @@ func TestOpenSameMemoryDb(t *testing.T) {
checkNoError
(
t
,
err
,
"exists error: %s"
)
checkNoError
(
t
,
err
,
"exists error: %s"
)
}
}
func
TestStmtWithClosedDb
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
db
.
SetCacheSize
(
0
)
s
,
err
:=
db
.
Prepare
(
"select 1"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
s
.
Finalize
()
err
=
db
.
Close
()
checkNoError
(
t
,
err
,
"close error: %s"
)
err
=
s
.
Finalize
()
assert
(
t
,
"error expected"
,
err
!=
nil
)
//println(err.Error())
}
func
TestConnExecWithSelect
(
t
*
testing
.
T
)
{
func
TestConnExecWithSelect
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
defer
checkClose
(
db
,
t
)
...
@@ -413,36 +191,26 @@ func TestConnExecWithSelect(t *testing.T) {
...
@@ -413,36 +191,26 @@ func TestConnExecWithSelect(t *testing.T) {
}
}
}
}
func
Test
StmtExecWithSelect
(
t
*
testing
.
T
)
{
func
Test
ConnInitialState
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
defer
checkClose
(
db
,
t
)
autoCommit
:=
db
.
GetAutocommit
()
s
,
err
:=
db
.
Prepare
(
"select 1"
)
assert
(
t
,
"autocommit expected to be active by default"
,
autoCommit
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
totalChanges
:=
db
.
TotalChanges
()
defer
s
.
Finalize
()
assertEquals
(
t
,
"expected total changes: %d, actual: %d"
,
0
,
totalChanges
)
err
:=
db
.
LastError
()
err
=
s
.
Exec
()
assertEquals
(
t
,
"expected last error: %v, actual: %v"
,
nil
,
err
)
assert
(
t
,
"error expected"
,
err
!=
nil
)
readonly
,
err
:=
db
.
Readonly
(
"main"
)
if
serr
,
ok
:=
err
.
(
*
StmtError
);
ok
{
checkNoError
(
t
,
err
,
"Readonly status error: %s"
)
assertEquals
(
t
,
"expected %q but got %q"
,
Row
,
serr
.
Code
())
assert
(
t
,
"readonly expected to be unset by default"
,
!
readonly
)
}
else
{
t
.
Errorf
(
"Expected StmtError but got %s"
,
reflect
.
TypeOf
(
err
))
}
}
}
func
Test
StmtSelectWithInsert
(
t
*
testing
.
T
)
{
func
Test
ConnSettings
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
defer
checkClose
(
db
,
t
)
err
:=
db
.
Exec
(
"CREATE TABLE test (data TEXT)"
)
db
.
EnableLoadExtension
(
false
)
checkNoError
(
t
,
err
,
"exec error: %s"
)
err
:=
db
.
SetRecursiveTriggers
(
"main"
,
true
)
checkNoError
(
t
,
err
,
"SetRecursiveTriggers error: %s"
)
s
,
err
:=
db
.
Prepare
(
"INSERT INTO test VALUES ('...')"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
s
.
Finalize
()
exists
,
err
:=
s
.
SelectOneRow
()
checkNoError
(
t
,
err
,
"select error: %s"
)
assert
(
t
,
"no row expected"
,
!
exists
)
}
}
func
assertEquals
(
t
*
testing
.
T
,
format
string
,
expected
,
actual
interface
{})
{
func
assertEquals
(
t
*
testing
.
T
,
format
string
,
expected
,
actual
interface
{})
{
...
...
stmt_test.go
0 → 100644
View file @
eb69bb64
// Copyright 2010 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package
sqlite_test
import
(
.
"github.com/gwenn/gosqlite"
"reflect"
"testing"
)
func
checkFinalize
(
s
*
Stmt
,
t
*
testing
.
T
)
{
checkNoError
(
t
,
s
.
Finalize
(),
"Error finalizing statement: %s"
)
}
func
TestInsertWithStatement
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
createTable
(
db
,
t
)
s
,
serr
:=
db
.
Prepare
(
"INSERT INTO test (float_num, int_num, a_string) VALUES (:f, :i, :s)"
)
checkNoError
(
t
,
serr
,
"prepare error: %s"
)
if
s
==
nil
{
t
.
Fatal
(
"statement is nil"
)
}
defer
checkFinalize
(
s
,
t
)
assert
(
t
,
"update statement should not be readonly"
,
!
s
.
ReadOnly
())
paramCount
:=
s
.
BindParameterCount
()
assertEquals
(
t
,
"bind parameter count error: expected %d but got %d"
,
3
,
paramCount
)
firstParamName
,
berr
:=
s
.
BindParameterName
(
1
)
checkNoError
(
t
,
berr
,
"error binding: %s"
)
assertEquals
(
t
,
"bind parameter name error: expected %s but got %s"
,
":f"
,
firstParamName
/*, berr*/
)
lastParamIndex
,
berr
:=
s
.
BindParameterIndex
(
":s"
)
checkNoError
(
t
,
berr
,
"error binding: %s"
)
assertEquals
(
t
,
"bind parameter index error: expected %d but got %d"
,
3
,
lastParamIndex
/*, berr*/
)
columnCount
:=
s
.
ColumnCount
()
assertEquals
(
t
,
"column count error: expected %d but got %d"
,
0
,
columnCount
)
db
.
Begin
()
for
i
:=
0
;
i
<
1000
;
i
++
{
c
,
ierr
:=
s
.
ExecDml
(
float64
(
i
)
*
float64
(
3.14
),
i
,
"hello"
)
checkNoError
(
t
,
ierr
,
"insert error: %s"
)
assertEquals
(
t
,
"insert error: expected %d changes but got %d"
,
1
,
c
)
assert
(
t
,
"Statement not reset"
,
!
s
.
Busy
())
}
checkNoError
(
t
,
db
.
Commit
(),
"Error: %s"
)
cs
,
_
:=
db
.
Prepare
(
"SELECT COUNT(*) FROM test"
)
defer
checkFinalize
(
cs
,
t
)
assert
(
t
,
"select statement should be readonly"
,
cs
.
ReadOnly
())
if
!
Must
(
cs
.
Next
())
{
t
.
Fatal
(
"no result for count"
)
}
var
i
int
checkNoError
(
t
,
cs
.
Scan
(
&
i
),
"error scanning count: %s"
)
assertEquals
(
t
,
"count should be %d, but it is %d"
,
1000
,
i
)
rs
,
_
:=
db
.
Prepare
(
"SELECT float_num, int_num, a_string FROM test where a_string like ? ORDER BY int_num LIMIT 2"
,
"hel%"
)
defer
checkFinalize
(
rs
,
t
)
columnCount
=
rs
.
ColumnCount
()
assertEquals
(
t
,
"column count error: expected %d but got %d"
,
3
,
columnCount
)
secondColumnName
:=
rs
.
ColumnName
(
1
)
assertEquals
(
t
,
"column name error: expected %s but got %s"
,
"int_num"
,
secondColumnName
)
if
Must
(
rs
.
Next
())
{
var
fnum
float64
var
inum
int64
var
sstr
string
rs
.
Scan
(
&
fnum
,
&
inum
,
&
sstr
)
assertEquals
(
t
,
"expected %f but got %f"
,
float64
(
0
),
fnum
)
assertEquals
(
t
,
"expected %d but got %d"
,
int64
(
0
),
inum
)
assertEquals
(
t
,
"expected %q but got %q"
,
"hello"
,
sstr
)
}
if
Must
(
rs
.
Next
())
{
var
fnum
float64
var
inum
int64
var
sstr
string
rs
.
NamedScan
(
"a_string"
,
&
sstr
,
"float_num"
,
&
fnum
,
"int_num"
,
&
inum
)
assertEquals
(
t
,
"expected %f but got %f"
,
float64
(
3.14
),
fnum
)
assertEquals
(
t
,
"expected %d but got %d"
,
int64
(
1
),
inum
)
assertEquals
(
t
,
"expected %q but got %q"
,
"hello"
,
sstr
)
}
assert
(
t
,
"expected full scan"
,
999
==
rs
.
Status
(
StmtStatusFullScanStep
,
false
))
assert
(
t
,
"expected one sort"
,
1
==
rs
.
Status
(
StmtStatusSort
,
false
))
assert
(
t
,
"expected no auto index"
,
0
==
rs
.
Status
(
StmtStatusAutoIndex
,
false
))
}
func
TestScanColumn
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
s
,
err
:=
db
.
Prepare
(
"select 1, null, 0"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
checkFinalize
(
s
,
t
)
if
!
Must
(
s
.
Next
())
{
t
.
Fatal
(
"no result"
)
}
var
i1
,
i2
,
i3
int
null
:=
Must
(
s
.
ScanByIndex
(
0
,
&
i1
))
assert
(
t
,
"expected not null value"
,
!
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
1
,
i1
)
null
=
Must
(
s
.
ScanByIndex
(
1
,
&
i2
))
assert
(
t
,
"expected null value"
,
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
0
,
i2
)
null
=
Must
(
s
.
ScanByIndex
(
2
,
&
i3
))
assert
(
t
,
"expected not null value"
,
!
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
0
,
i3
)
}
func
TestNamedScanColumn
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
s
,
err
:=
db
.
Prepare
(
"select 1 as i1, null as i2, 0 as i3"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
checkFinalize
(
s
,
t
)
if
!
Must
(
s
.
Next
())
{
t
.
Fatal
(
"no result"
)
}
var
i1
,
i2
,
i3
int
null
:=
Must
(
s
.
ScanByName
(
"i1"
,
&
i1
))
assert
(
t
,
"expected not null value"
,
!
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
1
,
i1
)
null
=
Must
(
s
.
ScanByName
(
"i2"
,
&
i2
))
assert
(
t
,
"expected null value"
,
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
0
,
i2
)
null
=
Must
(
s
.
ScanByName
(
"i3"
,
&
i3
))
assert
(
t
,
"expected not null value"
,
!
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
0
,
i3
)
}
func
TestScanCheck
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
s
,
err
:=
db
.
Prepare
(
"select 'hello'"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
checkFinalize
(
s
,
t
)
if
!
Must
(
s
.
Next
())
{
t
.
Fatal
(
"no result"
)
}
var
i
int
_
,
err
=
s
.
ScanByIndex
(
0
,
&
i
)
if
serr
,
ok
:=
err
.
(
*
StmtError
);
ok
{
assertEquals
(
t
,
"expected %q but got %q"
,
""
,
serr
.
Filename
())
assertEquals
(
t
,
"expected %q but got %q"
,
ErrSpecific
,
serr
.
Code
())
assertEquals
(
t
,
"expected %q but got %q"
,
s
.
SQL
(),
serr
.
SQL
())
}
else
{
t
.
Errorf
(
"Expected StmtError but got %s"
,
reflect
.
TypeOf
(
err
))
}
}
func
TestScanNull
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
s
,
err
:=
db
.
Prepare
(
"select null"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
checkFinalize
(
s
,
t
)
if
!
Must
(
s
.
Next
())
{
t
.
Fatal
(
"no result"
)
}
var
pi
*
int
=
new
(
int
)
null
:=
Must
(
s
.
ScanByIndex
(
0
,
&
pi
))
assert
(
t
,
"expected null value"
,
null
)
assertEquals
(
t
,
"expected nil (%p) but got %p"
,
(
*
int
)(
nil
),
pi
)
var
ps
*
string
=
new
(
string
)
null
=
Must
(
s
.
ScanByIndex
(
0
,
&
ps
))
assert
(
t
,
"expected null value"
,
null
)
assertEquals
(
t
,
"expected nil (%p) but got %p"
,
(
*
string
)(
nil
),
ps
)
}
func
TestScanNotNull
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
s
,
err
:=
db
.
Prepare
(
"select 1"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
checkFinalize
(
s
,
t
)
if
!
Must
(
s
.
Next
())
{
t
.
Fatal
(
"no result"
)
}
var
pi
*
int
=
new
(
int
)
null
:=
Must
(
s
.
ScanByIndex
(
0
,
&
pi
))
assert
(
t
,
"expected not null value"
,
!
null
)
assertEquals
(
t
,
"expected %d but got %d"
,
1
,
*
pi
)
var
ps
*
string
=
new
(
string
)
null
=
Must
(
s
.
ScanByIndex
(
0
,
&
ps
))
assert
(
t
,
"expected not null value"
,
!
null
)
assertEquals
(
t
,
"expected %s but got %s"
,
"1"
,
*
ps
)
}
/*
func TestScanError(t *testing.T) {
db := open(t)
defer checkClose(db, t)
s, err := db.Prepare("select 1")
checkNoError(t, err, "prepare error: %s")
defer checkFinalize(s, t)
if !Must(s.Next()) {
t.Fatal("no result")
}
var pi *int
null, err := s.ScanByIndex(0, &pi)
t.Errorf("(%t,%s)", null, err)
}*/
func
TestCloseTwice
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
s
,
err
:=
db
.
Prepare
(
"SELECT 1"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
err
=
s
.
Finalize
()
checkNoError
(
t
,
err
,
"finalize error: %s"
)
err
=
s
.
Finalize
()
checkNoError
(
t
,
err
,
"finalize error: %s"
)
err
=
db
.
Close
()
checkNoError
(
t
,
err
,
"close error: %s"
)
err
=
db
.
Close
()
checkNoError
(
t
,
err
,
"close error: %s"
)
}
func
TestStmtMisuse
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
s
,
err
:=
db
.
Prepare
(
"MISUSE"
)
assert
(
t
,
"error expected"
,
s
==
nil
&&
err
!=
nil
)
err
=
s
.
Finalize
()
assert
(
t
,
"error expected"
,
err
!=
nil
)
}
func
TestStmtWithClosedDb
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
db
.
SetCacheSize
(
0
)
s
,
err
:=
db
.
Prepare
(
"select 1"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
assertEquals
(
t
,
"expected Conn: %p, actual: %p"
,
db
,
s
.
Conn
())
defer
s
.
Finalize
()
err
=
db
.
Close
()
checkNoError
(
t
,
err
,
"close error: %s"
)
err
=
s
.
Finalize
()
assert
(
t
,
"error expected"
,
err
!=
nil
)
//println(err.Error())
}
func
TestStmtExecWithSelect
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
s
,
err
:=
db
.
Prepare
(
"select 1"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
s
.
Finalize
()
err
=
s
.
Exec
()
assert
(
t
,
"error expected"
,
err
!=
nil
)
if
serr
,
ok
:=
err
.
(
*
StmtError
);
ok
{
assertEquals
(
t
,
"expected %q but got %q"
,
Row
,
serr
.
Code
())
}
else
{
t
.
Errorf
(
"Expected StmtError but got %s"
,
reflect
.
TypeOf
(
err
))
}
}
func
TestStmtSelectWithInsert
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
err
:=
db
.
Exec
(
"CREATE TABLE test (data TEXT)"
)
checkNoError
(
t
,
err
,
"exec error: %s"
)
s
,
err
:=
db
.
Prepare
(
"INSERT INTO test VALUES ('...')"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
s
.
Finalize
()
exists
,
err
:=
s
.
SelectOneRow
()
checkNoError
(
t
,
err
,
"select error: %s"
)
assert
(
t
,
"no row expected"
,
!
exists
)
}
func
TestNamedBind
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
err
:=
db
.
Exec
(
"CREATE TABLE test (data BLOB, byte INT)"
)
checkNoError
(
t
,
err
,
"exec error: %s"
)
is
,
err
:=
db
.
Prepare
(
"INSERT INTO test (data, byte) VALUES (:blob, :b)"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
bc
:=
is
.
BindParameterCount
()
assertEquals
(
t
,
"expected %d parameters but got %d"
,
2
,
bc
)
for
i
:=
1
;
i
<=
bc
;
i
++
{
_
,
err
:=
is
.
BindParameterName
(
i
)
checkNoError
(
t
,
err
,
"bind parameter name error: %s"
)
}
blob
:=
[]
byte
{
'h'
,
'e'
,
'l'
,
'l'
,
'o'
}
var
byt
byte
=
'!'
err
=
is
.
NamedBind
(
":b"
,
byt
,
":blob"
,
blob
)
checkNoError
(
t
,
err
,
"named bind error: %s"
)
_
,
err
=
is
.
Next
()
checkNoError
(
t
,
err
,
"named bind step error: %s"
)
checkFinalize
(
is
,
t
)
s
,
err
:=
db
.
Prepare
(
"SELECT data as bs, byte as b FROM test"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
checkFinalize
(
s
,
t
)
if
!
Must
(
s
.
Next
())
{
t
.
Fatal
(
"no result"
)
}
var
bs
[]
byte
var
b
byte
err
=
s
.
NamedScan
(
"b"
,
&
b
,
"bs"
,
&
bs
)
checkNoError
(
t
,
err
,
"named scan error: %s"
)
assertEquals
(
t
,
"expected blob: %v, actual: %s"
,
len
(
blob
),
len
(
bs
))
assertEquals
(
t
,
"expected byte: %c, actual: %c"
,
byt
,
b
)
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment