@ -0,0 +1,27 @@ | |||
Copyright (c) 2015, stephen mcquay | |||
All rights reserved. | |||
Redistribution and use in source and binary forms, with or without modification, | |||
are permitted provided that the following conditions are met: | |||
* Redistributions of source code must retain the above copyright notice, | |||
this list of conditions and the following disclaimer. | |||
* Redistributions in binary form must reproduce the above copyright notice, | |||
this list of conditions and the following disclaimer in the documentation | |||
and/or other materials provided with the distribution. | |||
* Neither the name of pgpoint nor the names of its contributors | |||
may be used to endorse or promote products derived from this software | |||
without specific prior written permission. | |||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR | |||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | |||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | |||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | |||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | |||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
@ -0,0 +1,55 @@ | |||
package point | |||
import ( | |||
"bytes" | |||
"database/sql/driver" | |||
"errors" | |||
"fmt" | |||
"strconv" | |||
_ "github.com/lib/pq" | |||
) | |||
type Point struct { | |||
Lat, Lng float64 | |||
} | |||
func (p Point) Value() (driver.Value, error) { | |||
tuple := fmt.Sprintf("(%f, %f)", p.Lat, p.Lng) | |||
return driver.Value([]byte(tuple)), nil | |||
} | |||
func (p *Point) Scan(src interface{}) error { | |||
var source []byte | |||
var err error | |||
switch src.(type) { | |||
case string: | |||
source = []byte(src.(string)) | |||
case []byte: | |||
source = src.([]byte) | |||
default: | |||
return errors.New("Incompatible type for Point") | |||
} | |||
lp := bytes.IndexRune(source, '(') | |||
c := bytes.IndexRune(source, ',') | |||
rp := bytes.IndexRune(source, ')') | |||
if lp == -1 || c == -1 || rp == -1 { | |||
return fmt.Errorf( | |||
"incorrect format from pg for Point: %s", | |||
source, | |||
) | |||
} | |||
p.Lat, err = strconv.ParseFloat(string(source[lp+1:c]), 64) | |||
if err != nil { | |||
return err | |||
} | |||
p.Lng, err = strconv.ParseFloat(string(source[c+1:rp]), 64) | |||
if err != nil { | |||
return err | |||
} | |||
return nil | |||
} |
@ -0,0 +1,43 @@ | |||
# point | |||
This sample module shows how to create a type that implements the required interfaces to be used as a custom type with [github.com/jmoiron/sqlx](github.com/jmoiron/sqlx) package. | |||
Sample db table: | |||
``` | |||
CREATE TABLE places (id SERIAL, name varchar(512), loc point); | |||
``` | |||
and then use as such (err omitted for brevity): | |||
``` | |||
type Location struct { | |||
Id int | |||
Name string | |||
Description string | |||
Loc Point // custom type | |||
} | |||
func main() { | |||
db, _ := sqlx.Connect( | |||
"postgres", | |||
"<your config here>", | |||
) | |||
loc := Location{} | |||
rows, _ := db.Queryx( | |||
`SELECT * FROM places`, | |||
) | |||
for rows.Next() { | |||
rows.StructScan(&loc) | |||
fmt.Printf("%+v", loc) | |||
} | |||
db.Exec( | |||
"INSERT INTO places(name, loc) VALUES ($1, $3):, | |||
"some name" | |||
Point{3.14, 6.28}, | |||
) | |||
} | |||
``` |