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
dbfe8195
Commit
dbfe8195
authored
Apr 30, 2013
by
gwenn
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add type aliases to persist time in specific format.
parent
da998cb4
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
103 additions
and
10 deletions
+103
-10
date_test.go
date_test.go
+58
-0
stmt.go
stmt.go
+44
-9
stmt_test.go
stmt_test.go
+1
-1
No files found.
date_test.go
View file @
dbfe8195
...
...
@@ -71,3 +71,61 @@ func TestScan(t *testing.T) {
t
.
Error
(
"Unexpected zero julian day"
)
}
}
func
TestBindTimeAsString
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
err
:=
db
.
Exec
(
"CREATE TABLE test (time TEXT)"
)
checkNoError
(
t
,
err
,
"exec error: %s"
)
is
,
err
:=
db
.
Prepare
(
"INSERT INTO test (time) VALUES (?)"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
now
:=
time
.
Now
()
//id1, err := is.Insert(YearMonthDay(now))
//checkNoError(t, err, "error inserting YearMonthDay: %s")
id2
,
err
:=
is
.
Insert
(
TimeStamp
(
now
))
checkNoError
(
t
,
err
,
"error inserting TimeStamp: %s"
)
// The format used to persist has a max precision of 1ms.
now
=
now
.
Truncate
(
time
.
Millisecond
)
var
tim
time
.
Time
//err = db.OneValue("SELECT /*date(*/time/*)*/ FROM test where ROWID = ?", &tim, id1)
//checkNoError(t, err, "error selecting YearMonthDay: %s")
//assertEquals(t, "Year MonthDay: %d vs %d", now.Year(), tim.Year())
//assertEquals(t, "YearMonth Day: %d vs %d", now.YearDay(), tim.YearDay())
err
=
db
.
OneValue
(
"SELECT /*datetime(*/time/*)*/ FROM test where ROWID = ?"
,
&
tim
,
id2
)
checkNoError
(
t
,
err
,
"error selecting TimeStamp: %s"
)
assertEquals
(
t
,
"TimeStamp: %s vs %s"
,
now
,
tim
)
}
func
TestBindTimeAsNumeric
(
t
*
testing
.
T
)
{
db
:=
open
(
t
)
defer
checkClose
(
db
,
t
)
err
:=
db
.
Exec
(
"CREATE TABLE test (time NUMERIC)"
)
checkNoError
(
t
,
err
,
"exec error: %s"
)
is
,
err
:=
db
.
Prepare
(
"INSERT INTO test (time) VALUES (?)"
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
now
:=
time
.
Now
()
id1
,
err
:=
is
.
Insert
(
UnixTime
(
now
))
checkNoError
(
t
,
err
,
"error inserting UnixTime: %s"
)
id2
,
err
:=
is
.
Insert
(
JulianTime
(
now
))
checkNoError
(
t
,
err
,
"error inserting JulianTime: %s"
)
checkFinalize
(
is
,
t
)
// And the format used to persist has a max precision of 1s.
now
=
now
.
Truncate
(
time
.
Second
)
var
tim
time
.
Time
err
=
db
.
OneValue
(
"SELECT /*datetime(*/ time/*, 'unixepoch')*/ FROM test where ROWID = ?"
,
&
tim
,
id1
)
checkNoError
(
t
,
err
,
"error selecting UnixTime: %s"
)
assertEquals
(
t
,
"Year: %s vs %s"
,
now
,
tim
)
err
=
db
.
OneValue
(
"SELECT /*julianday(*/time/*)*/ FROM test where ROWID = ?"
,
&
tim
,
id2
)
checkNoError
(
t
,
err
,
"error selecting JulianTime: %s"
)
assertEquals
(
t
,
"Year: %s vs %s"
,
now
,
tim
)
}
stmt.go
View file @
dbfe8195
...
...
@@ -310,6 +310,21 @@ func (s *Stmt) Bind(args ...interface{}) error {
return
nil
}
// UnixTime is an alias used to persist time as int64 (max precision is 1s and timezone is lost) (default)
type
UnixTime
time
.
Time
// JulianTime is an alias used to persist time as float64 (max precision is 1s and timezone is lost)
type
JulianTime
time
.
Time
// YearMonthDay is an alias used to persist time as 'YYYY-MM-DD' string
//type YearMonthDay time.Time
// TimeOfDay is an alias used to persist time as 'HH:MM:SS.SSS' string
//type TimeOfDay time.Time versus Duration
// TimeStamp is an alias used to persist time as '2006-01-02T15:04:05.999Z07:00' string
type
TimeStamp
time
.
Time
// BindByIndex binds value to the specified host parameter of the prepared statement.
// The leftmost SQL parameter has an index of 1.
func
(
s
*
Stmt
)
BindByIndex
(
index
int
,
value
interface
{})
error
{
...
...
@@ -339,10 +354,22 @@ func (s *Stmt) BindByIndex(index int, value interface{}) error {
p
=
&
value
[
0
]
}
rv
=
C
.
my_bind_blob
(
s
.
stmt
,
i
,
unsafe
.
Pointer
(
p
),
C
.
int
(
len
(
value
)))
case
time
.
Time
:
// At least three representations are possible: string (YYYY-MM-DD HH:MM:SS.SSS), int64 (unix time), float64 (julian day)
// rv = C.my_bind_text(s.stmt, i, value.format("2006-01-02 15:04:05.000"))
case
JulianTime
:
rv
=
C
.
sqlite3_bind_double
(
s
.
stmt
,
i
,
C
.
double
(
JulianDay
(
time
.
Time
(
value
))))
/*case YearMonthDay:
cs, l := cstring((time.Time)(value).Format("2006-01-02"))
rv = C.my_bind_text(s.stmt, i, cs, l)
case TimeOfDay:
cs, l := cstring((time.Time)(value).Format("15:04:05.000"))
rv = C.my_bind_text(s.stmt, i, cs, l)
*/
case
TimeStamp
:
cs
,
l
:=
cstring
((
time
.
Time
)(
value
)
.
Format
(
"2006-01-02T15:04:05.999Z07:00"
))
rv
=
C
.
my_bind_text
(
s
.
stmt
,
i
,
cs
,
l
)
case
UnixTime
:
rv
=
C
.
sqlite3_bind_int64
(
s
.
stmt
,
i
,
C
.
sqlite3_int64
((
time
.
Time
)(
value
)
.
Unix
()))
case
time
.
Time
:
rv
=
C
.
sqlite3_bind_int64
(
s
.
stmt
,
i
,
C
.
sqlite3_int64
(
value
.
Unix
()))
// rv = C.sqlite3_bind_double(s.stmt, i, JulianDay(value))
case
ZeroBlobLength
:
rv
=
C
.
sqlite3_bind_zeroblob
(
s
.
stmt
,
i
,
C
.
int
(
value
))
default
:
...
...
@@ -831,6 +858,8 @@ func (s *Stmt) ScanBlob(index int) (value []byte, isNull bool) {
}
// ScanTime scans result value from a query.
// If time is persisted as string without timezone, UTC is used.
// If time is persisted as numeric, local is used.
// The leftmost column/index is number 0.
// Returns true when column is null.
func
(
s
*
Stmt
)
ScanTime
(
index
int
)
(
value
time
.
Time
,
isNull
bool
,
err
error
)
{
...
...
@@ -862,20 +891,26 @@ func (s *Stmt) ScanTime(index int) (value time.Time, isNull bool, err error) {
}
else
{
layout
=
"2006-01-02 15:04:05"
}
default
:
// YYYY-MM-DDTHH:MM:SS.SSS or parse error
case
23
:
// YYYY-MM-DDTHH:MM:SS.SSS
if
txt
[
10
]
==
'T'
{
layout
=
"2006-01-02T15:04:05.999"
}
else
{
layout
=
"2006-01-02 15:04:05.999"
}
default
:
// YYYY-MM-DDTHH:MM:SS.SSSZhh:mm or parse error
if
len
(
txt
)
>
10
&&
txt
[
10
]
==
'T'
{
layout
=
"2006-01-02T15:04:05.
0
00"
layout
=
"2006-01-02T15:04:05.
999Z07:
00"
}
else
{
layout
=
"2006-01-02 15:04:05.
0
00"
layout
=
"2006-01-02 15:04:05.
999Z07:
00"
}
}
value
,
err
=
time
.
Parse
(
layout
,
txt
)
value
,
err
=
time
.
Parse
(
layout
,
txt
)
// UTC except when timezone is specified
case
Integer
:
unixepoch
:=
int64
(
C
.
sqlite3_column_int64
(
s
.
stmt
,
C
.
int
(
index
)))
value
=
time
.
Unix
(
unixepoch
,
0
)
value
=
time
.
Unix
(
unixepoch
,
0
)
// local time
case
Float
:
jd
:=
float64
(
C
.
sqlite3_column_double
(
s
.
stmt
,
C
.
int
(
index
)))
value
=
JulianDayTo
UTC
(
jd
)
value
=
JulianDayTo
LocalTime
(
jd
)
// local time
default
:
panic
(
"The column type is not one of SQLITE_INTEGER, SQLITE_FLOAT, SQLITE_TEXT, or SQLITE_NULL"
)
}
...
...
stmt_test.go
View file @
dbfe8195
...
...
@@ -361,8 +361,8 @@ func TestInsertMisuse(t *testing.T) {
checkNoError
(
t
,
err
,
"exec error: %s"
)
is
,
err
:=
db
.
Prepare
(
"INSERT INTO test (data, bool) VALUES (?, ?)"
)
defer
checkFinalize
(
is
,
t
)
checkNoError
(
t
,
err
,
"prepare error: %s"
)
defer
checkFinalize
(
is
,
t
)
_
,
err
=
is
.
Insert
()
assert
(
t
,
"missing bind parameters expected"
,
err
!=
nil
)
...
...
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