What is it CHECK constraint failed: subject <> ''? - sql

What is it CHECK constraint failed: subject <> '' ?
I get an error with stmt, err_execontext := s.db.ExecContext(ctx, insert, subject, description).
How can I solve this?
type TODOService struct {
db *sql.DB
}
// NewTODOService returns new TODOService.
func NewTODOService(db *sql.DB) *TODOService {
return &TODOService{
db: db,
}
}
// CreateTODO creates a TODO on DB.
func (s *TODOService) CreateTODO(ctx context.Context, subject, description string) (*model.TODO, error) {
const (
insert = `INSERT INTO todos(subject, description) VALUES(?, ?)`
confirm = `SELECT subject, description, created_at, updated_at FROM todos WHERE id = ?`
)
stmt, err_execontext := s.db.ExecContext(ctx, insert, subject, description)
if err_execontext != nil {
log.Fatal("server/todo.go 31行目", err_execontext)
}
created_id, err_iserid := stmt.LastInsertId()
if err_iserid != nil {
log.Fatal("server/todo.go 35行目", err_iserid)
}
var todo model.TODO
err := s.db.QueryRowContext(ctx, confirm, created_id).Scan(&todo.Subject, &todo.Description, &todo.CreatedAt, &todo.UpdatedAt)
switch {
case err == sql.ErrNoRows:
log.Fatalf("no todo with id %d", created_id)
case err != nil:
log.Fatal(err)
}
return &todo, err
}
type TODOHandler struct {
svc *service.TODOService
}
// NewTODOHandler returns TODOHandler based http.Handler.
func NewTODOHandler(svc *service.TODOService) *TODOHandler {
return &TODOHandler{
svc: svc,
}
}
// Create handles the endpoint that creates the TODO.
func (h *TODOHandler) Create(ctx context.Context, req *model.CreateTODORequest) (*model.CreateTODOResponse, error) {
created_todo, err := h.svc.CreateTODO(ctx, req.Subject, req.Description)
if err != nil {
log.Fatal("Failed to", err)
}
return &model.CreateTODOResponse{TODO: *created_todo}, nil
}
type (
// A TODO expresses ...
TODO struct{
ID int `json:"id"`
Subject string `json:"subject"`
Description string `json:"description"`
CreatedAt time.Time `json:"createdAt"`
UpdatedAt time.Time `json:"UpdatedAt"`
}
// A CreateTODORequest expresses ...
CreateTODORequest struct{
Subject string `json:"subject"`
Description string `json:"description"`
}
// A CreateTODOResponse expresses ...
CreateTODOResponse struct{
TODO TODO `json:"todo"`
}
)
What is it CHECK constraint failed: subject <> '' ?
I get an error with stmt, err_execontext := s.db.ExecContext(ctx, insert, subject, description).
How can I solve this?
CREATE TABLE IF NOT EXISTS todos (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
subject TEXT NOT NULL,
description TEXT NOT NULL DEFAULT '',
created_at DATETIME NOT NULL DEFAULT (DATETIME('now')),
updated_at DATETIME NOT NULL DEFAULT (DATETIME('now')),
CHECK(subject <> '')
);
CREATE TRIGGER IF NOT EXISTS trigger_todos_updated_at AFTER UPDATE ON todos
BEGIN
UPDATE todos SET updated_at = DATETIME('now') WHERE id == NEW.id;
END;

Related

Storing and Retrieving Lat Long Values Stored as Geography Point Type in Database GoLang

I am trying to save to my database, latitude and longitude values as the geography point datatype and i want to be able to retrieve the values accordingly. I have implemented the following
my model device.go looks like this
device.go
package models
import (
"bytes"
"database/sql/driver"
"encoding/binary"
"encoding/hex"
"fmt"
"time"
"gorm.io/gorm"
)
type GeoPoint struct {
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
}
func (p *GeoPoint) String() string {
return fmt.Sprintf("SRID=4326;POINT(%v %v)", p.Lng, p.Lat)
}
// Scan implements the sql.Scanner interface.
func (p *GeoPoint) Scan(val interface{}) error {
b, err := hex.DecodeString(string(val.(string)))
if err != nil {
return err
}
r := bytes.NewReader(b)
var wkbByteOrder uint8
if err := binary.Read(r, binary.LittleEndian, &wkbByteOrder); err != nil {
return err
}
var byteOrder binary.ByteOrder
switch wkbByteOrder {
case 0:
byteOrder = binary.BigEndian
case 1:
byteOrder = binary.LittleEndian
default:
return fmt.Errorf("invalid byte order %d", wkbByteOrder)
}
var wkbGeometryType uint32
if err := binary.Read(r, byteOrder, &wkbGeometryType); err != nil {
return err
}
if err := binary.Read(r, byteOrder, p); err != nil {
return err
}
return nil
}
// Value impl.
func (p GeoPoint) Value() (driver.Value, error) {
return p.String(), nil
}
type Device struct {
gorm.Model
Id int `json:"id" gorm:"primaryKey"`
UserId int `json:"user_id" gorm:"uniqueIndex"`
LatestLocation GeoPoint `json:"latest_location" gorm:"type:geography(POINT, 4326)"`
CreatedAt time.Time
UpdatedAt time.Time
}
I am able to save data to the database and this is how it looks like in the database
But when i want to retrieve the record with the latitude and longitude, I get wrong data records and i am not sure why.
this is my code
location.go
package apisLocation
import (
"fmt"
db "atm/pkg/configs/database"
models "atm/pkg/models"
"strconv"
"github.com/gofiber/fiber/v2"
)
func GetLocation(c *fiber.Ctx) error {
userId, err := strconv.Atoi(c.Params("userId"))
if err != nil {
return c.Status(400).JSON(err.Error())
}
if checkIfUserExists(userId) {
return c.Status(400).JSON(fiber.Map{"error": "User does not exist"})
}
var device models.Device
db.DB.Db.Find(&device, models.Device{UserId: userId})
return c.Status(200).JSON(fiber.Map{"location": device.LatestLocation})
}
func checkIfUserExists(userId int) bool {
var device models.Device
db.DB.Db.Find(&device, models.Device{UserId: userId})
return device.Id == 0
}
when i run the GetLocation method, the response i get is not accurate, i get a value of this
"location": {
"lat": 1.7689674224598998e+71,
"lng": -3.639753837714837e+173
},
which isn't the lat and long that is saved in the database.
I think somehow when it is being decoded, something changes but i am not sure how to fix this issue.
Any help is appreciated
I found a solution to your problem here https://github.com/go-pg/pg/issues/829#issuecomment-505882885
The problem in your code was just declaring your wkbGeometryType as uint32, not uint64.

How to handle nullable Postgres JSONB data and parse it as JSON

DB Records
---------------------------------------------------------
| id | test_json |
---------------------------------------------------------
| 1 | NULL |
---------------------------------------------------------
| 2 | { "firstName": "Hello", "lastName": "World" } |
---------------------------------------------------------
I have JSONB column in postgres which can be NULL. I want to read this records DB in golang and send it to the client.
I'm getting below error on SQL scan:
sql: Scan error on column index 2, name "test_json": unsupported Scan, storing driver.Value type []uint8 into type *models.TestJSONNullable
exit status 1
I'm using echo web server.
package models
import (
"fmt"
"github.com/lib/pq"
"encoding/json"
)
type TestJson struct {
First_name *string `json:"firstName"`
Last_name *string `json:"lastName"`
}
type TestJSONNullable struct {
Valid bool
}
func (i *TestJSONNullable) UnmarshalJSON(data []byte) error {
if string(data) == "null" {
i.Valid = false
return nil
}
// The key isn't set to null
var temp *TestJson
if err := json.Unmarshal(data, &temp); err != nil {
return err
}
i.Valid = true
return nil
}
type Test01 struct {
Id string `json:"id"`
Test_json *TestJSONNullable `json:"testJson"`
}
func (db *DB) TestRecords () ([]*Test01, error) {
rows, err := db.Query("SELECT id, test_json FROM table_1 where success = true")
if err != nil {
log.Fatal(err)
return nil, err
}
defer rows.Close()
recs := []*Test01{}
for rows.Next() {
r := new(Test01)
err := rows.Scan(&r.Id, &r.Test_json)
if err != nil {
log.Fatal(err)
return nil, err
}
recs = append(recs, r)
}
if err = rows.Err(); err != nil {
log.Fatal(err)
return nil, err
}
return recs, nil
}
Here's another solution: You can implement a nullable type for raw JSON data, similar to sql.NullString, and use it as a scan destination. In this scenario, you will first check whether the value is null, and then unmarshal it only if it's not null. For instance, the NullRawMessage type from github.com/soroushj/sqlt is a nullable json.RawMessage which can be used for this purpose.
Here's an example:
package main
import (
"database/sql"
"log"
_ "github.com/lib/pq"
"github.com/soroushj/sqlt"
)
func main() {
db, err := sql.Open("postgres", "dbname=dbname user=user password=password sslmode=disable")
if err != nil {
log.Fatal(err)
}
row := db.QueryRow(`SELECT test_json FROM my_table WHERE id = $1`, 1)
testJSON := sqlt.NullRawMessage{}
err = row.Scan(&testJSON)
if err != nil {
log.Fatal(err)
}
if testJSON.Valid {
// test_json is not null
// Unmarshal testJSON.RawMessage
} else {
// test_json is null
}
}
After doing some research i found the solution.
type TestJSONMap map[string]interface{}
func (t TestJSONMap) Value() (driver.Value, error) {
j, err := json.Marshal(t)
return j, err
}
func (p *TestJSONMap) Scan(val interface{}) error {
value, ok := val.([]byte)
if !ok {
return errors.New("Type assertion .([]byte) failed.")
}
var i interface{}
err := json.Unmarshal(value, &i)
if err != nil {
return err
}
*p, ok = i.(map[string]interface{})
if !ok {
return errors.New("Type assertion .(map[string]interface{}) failed.")
}
return nil
}
type Test01 struct {
Id string `json:"id"`
Test_json *TestJSONMap `json:"testJson"`
}
Got help from https://coussej.github.io/2016/02/16/Handling-JSONB-in-Go-Structs/
Instead of using struct to store values, You can use map.
type TestJson struct {
First_name *string `json:"firstName"`
Last_name *string `json:"lastName"`
}
You can use interface as
var TestJson interface{}
err := json.Unmarshal(b, &TestJson)
On the other side you can also use Dynamic creation of structs as well.
Something like
m := map[string]interface{}{
"key": "value",
}
And rather than having TestJSONNullable it would be better to have Switch case while saving data.
switch v := TestJson.(type) {
case int:
case float64:
case string:
default:
// i isn't one of the types above
}
Look into this for more details--> https://godoc.org/encoding/json#Unmarshal

beego api post insert data

First of all. I use postman to POST data. How to take data from the postman key.
It works by using this way (in my code I set it by myself).
I want to get firstname, lastname, email in form-data.
I want to use as below.
func InsertOneUser(user User) *User {
o := orm.NewOrm()
qs := o.QueryTable(new(User))
i, _ := qs.PrepareInsert()
var u User
user.FirstName = "firstname" <----- this
user.LastName = "lastname" <----- this
user.Email = "something#yahoo.com" <----- this
user.Password, _ = hashPassword(user.Password)
user.RegDate = time.Now()
id, err := i.Insert(&user)
return &u
}
You need beego.Controller in func. if func has beego.Controller, there are two ways(key, parseform).
package main
import (
"fmt"
"github.com/astaxie/beego"
)
type User struct {
Firstname string `form:"firstname"`
Lastname string `form:"lastname"`
Email string `form:"email"`
}
type MainController struct {
beego.Controller
}
func (this *MainController) Post() {
// using key
firstname := this.GetString("firstname")
lastname := this.GetString("lastname")
email := this.GetString("email")
// using Parseform
u := User{}
if err := this.ParseForm(&u); err != nil {
fmt.Println(err)
}
fmt.Println(u)
this.Ctx.WriteString(fmt.Sprintf("%s %s %s", firstname, lastname, email))
}
func main() {
beego.Router("/api/v1/user", &MainController{})
beego.Run()
}

Convert query result from struct to string for another Golang package

I have searched for a solution on the net and in SO, but found nothing that apply to return values. It is a simple sql query with several rows that I want to return. Error handling not included:
func Fetch(query string) (string) {
type User struct{
id string
name string
}
rows, err := db.Query(query)
users := make([]*User, 0)
for rows.Next() {
user := new(User)
err := rows.Scan(&user.id, &user.name)
users = append(users, user)
}
return(users)
}
I get this error when compiling:
cannot use users (type []*User) as type string in return argument
How should I do to get a correct return value?
The expected input is
JD John Doe --OR-- {id:"JD",name:"John Doe"}
Add this to your code:
type userSlice []*User
func (us userSlice) String() string{
var s []string
for _, u := range us {
if u != nil {
s = append(s, fmt.Sprintf("%s %s", u.id, u.name))
}
}
return strings.Join(s, "\n")
}
type User struct{
id string
name string
}
In your Fetch function replace the last return statement like this:
func Fetch(query string) (string) {
// Note that we declare the User type outside the function.
rows, err := db.Query(query)
users := make([]*User, 0)
for rows.Next() {
user := new(User)
err := rows.Scan(&user.id, &user.name)
users = append(users, user)
}
return(userSlice(users).String()) // Replace this line in your code
}
If you have to return a String you can use the encoding/json package to serialize your user object, but you have to use fields that begin with capital letters for them to be exported. See the full example:
import (
"encoding/json"
)
func Fetch(query string) (string) {
type User struct{
Id string // <-- CHANGED THIS LINE
Name string // <-- CHANGED THIS LINE
}
rows, err := db.Query(query)
users := make([]*User, 0)
for rows.Next() {
user := new(User)
err := rows.Scan(&user.id, &user.name)
users = append(users, user)
}
return(ToJSON(users)) // <-- CHANGED THIS LINE
}
func ToJSON(obj interface{}) (string) {
res, err := json.Marshal(obj)
if err != nil {
panic("error with json serialization " + err.Error())
}
return string(res)
}

Are there any solution for SELECT * FROM in golang SQL drivers [duplicate]

Basically after doing a query I'd like to take the resulting rows and produce a []map[string]interface{}, but I do not see how to do this with the API since the Rows.Scan() function needs a specific number of parameters matching the requested number of columns (and possibly the types as well) to correctly obtain the data.
Again, I'd like to generalize this call and take any query and turn it into a []map[string]interface{}, where the map contains column names mapped to the values for that row.
This is likely very inefficient, and I plan on changing the structure later so that interface{} is a struct for a single data point.
How would I do this using just the database/sql package, or if necessary the database/sql/driver package?
Look at using sqlx, which can do this a little more easily than the standard database/sql library:
places := []Place{}
err := db.Select(&places, "SELECT * FROM place ORDER BY telcode ASC")
if err != nil {
fmt.Printf(err)
return
}
You could obviously replace []Place{} with a []map[string]interface{}, but where possible it is better to use a struct if you know the structure of your database. You won't need to undertake any type assertions as you might on an interface{}.
I haven't used it (yet), but I believe the "common" way to do what you are asking (more or less) is to use gorp.
You can create a struct that maintains the map key to the position of the []interface{} slice. By doing this, you do not need to create a predefined struct. For example:
IDOrder: 0
IsClose: 1
IsConfirm: 2
IDUser: 3
Then, you can use it like this:
// create a fieldbinding object.
var fArr []string
fb := fieldbinding.NewFieldBinding()
if fArr, err = rs.Columns(); err != nil {
return nil, err
}
fb.PutFields(fArr)
//
outArr := []interface{}{}
for rs.Next() {
if err := rs.Scan(fb.GetFieldPtrArr()...); err != nil {
return nil, err
}
fmt.Printf("Row: %v, %v, %v, %s\n", fb.Get("IDOrder"), fb.Get("IsConfirm"), fb.Get("IDUser"), fb.Get("Created"))
outArr = append(outArr, fb.GetFieldArr())
}
Sample output:
Row: 1, 1, 1, 2016-07-15 10:39:37 +0000 UTC
Row: 2, 1, 11, 2016-07-15 10:42:04 +0000 UTC
Row: 3, 1, 10, 2016-07-15 10:46:20 +0000 UTC
SampleQuery: [{"Created":"2016-07-15T10:39:37Z","IDOrder":1,"IDUser":1,"IsClose":0,"IsConfirm":1},{"Created":"2016-07-15T10:42:04Z","IDOrder":2,"IDUser":11,"IsClose":0,"IsConfirm":1},{"Created":"2016-07-15T10:46:20Z","IDOrder":3,"IDUser":10,"IsClose":0,"IsConfirm":1}]
Please see the full example below or at fieldbinding:
main.go
package main
import (
"bytes"
"database/sql"
"encoding/json"
"fmt"
)
import (
_ "github.com/go-sql-driver/mysql"
"github.com/junhsieh/goexamples/fieldbinding/fieldbinding"
)
var (
db *sql.DB
)
// Table definition
// CREATE TABLE `salorder` (
// `IDOrder` int(10) unsigned NOT NULL AUTO_INCREMENT,
// `IsClose` tinyint(4) NOT NULL,
// `IsConfirm` tinyint(4) NOT NULL,
// `IDUser` int(11) NOT NULL,
// `Created` datetime NOT NULL,
// `Changed` datetime NOT NULL,
// PRIMARY KEY (`IDOrder`),
// KEY `IsClose` (`IsClose`)
// ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
func main() {
var err error
// starting database server
db, err = sql.Open("mysql", "Username:Password#tcp(Host:Port)/DBName?parseTime=true")
if err != nil {
panic(err.Error()) // Just for example purpose. You should use proper error handling instead of panic
}
defer db.Close()
// SampleQuery
if v, err := SampleQuery(); err != nil {
fmt.Printf("%s\n", err.Error())
} else {
var b bytes.Buffer
if err := json.NewEncoder(&b).Encode(v); err != nil {
fmt.Printf("SampleQuery: %v\n", err.Error())
}
fmt.Printf("SampleQuery: %v\n", b.String())
}
}
func SampleQuery() ([]interface{}, error) {
param := []interface{}{}
param = append(param, 1)
sql := "SELECT "
sql += " SalOrder.IDOrder "
sql += ", SalOrder.IsClose "
sql += ", SalOrder.IsConfirm "
sql += ", SalOrder.IDUser "
sql += ", SalOrder.Created "
sql += "FROM SalOrder "
sql += "WHERE "
sql += "IsConfirm = ? "
sql += "ORDER BY SalOrder.IDOrder ASC "
rs, err := db.Query(sql, param...)
if err != nil {
return nil, err
}
defer rs.Close()
// create a fieldbinding object.
var fArr []string
fb := fieldbinding.NewFieldBinding()
if fArr, err = rs.Columns(); err != nil {
return nil, err
}
fb.PutFields(fArr)
//
outArr := []interface{}{}
for rs.Next() {
if err := rs.Scan(fb.GetFieldPtrArr()...); err != nil {
return nil, err
}
fmt.Printf("Row: %v, %v, %v, %s\n", fb.Get("IDOrder"), fb.Get("IsConfirm"), fb.Get("IDUser"), fb.Get("Created"))
outArr = append(outArr, fb.GetFieldArr())
}
if err := rs.Err(); err != nil {
return nil, err
}
return outArr, nil
}
fieldbinding package:
package fieldbinding
import (
"sync"
)
// NewFieldBinding ...
func NewFieldBinding() *FieldBinding {
return &FieldBinding{}
}
// FieldBinding is deisgned for SQL rows.Scan() query.
type FieldBinding struct {
sync.RWMutex // embedded. see http://golang.org/ref/spec#Struct_types
FieldArr []interface{}
FieldPtrArr []interface{}
FieldCount int64
MapFieldToID map[string]int64
}
func (fb *FieldBinding) put(k string, v int64) {
fb.Lock()
defer fb.Unlock()
fb.MapFieldToID[k] = v
}
// Get ...
func (fb *FieldBinding) Get(k string) interface{} {
fb.RLock()
defer fb.RUnlock()
// TODO: check map key exist and fb.FieldArr boundary.
return fb.FieldArr[fb.MapFieldToID[k]]
}
// PutFields ...
func (fb *FieldBinding) PutFields(fArr []string) {
fCount := len(fArr)
fb.FieldArr = make([]interface{}, fCount)
fb.FieldPtrArr = make([]interface{}, fCount)
fb.MapFieldToID = make(map[string]int64, fCount)
for k, v := range fArr {
fb.FieldPtrArr[k] = &fb.FieldArr[k]
fb.put(v, int64(k))
}
}
// GetFieldPtrArr ...
func (fb *FieldBinding) GetFieldPtrArr() []interface{} {
return fb.FieldPtrArr
}
// GetFieldArr ...
func (fb *FieldBinding) GetFieldArr() map[string]interface{} {
m := make(map[string]interface{}, fb.FieldCount)
for k, v := range fb.MapFieldToID {
m[k] = fb.FieldArr[v]
}
return m
}
If you really want a map, which is needed in some cases, have a look at dbr, but you need to use the fork (since the pr got rejected in the original repo). The fork seems more up to date anyway:
https://github.com/mailru/dbr
For info on how to use it:
https://github.com/gocraft/dbr/issues/83
package main
import (
"fmt"
"github.com/bobby96333/goSqlHelper"
)
func main(){
fmt.Println("hello")
conn,err :=goSqlHelper.MysqlOpen("user:password#tcp(127.0.0.1:3306)/dbname")
checkErr(err)
row,err := conn.QueryRow("select * from table where col1 = ? and col2 = ?","123","abc")
checkErr(err)
if *row==nil {
fmt.Println("no found row")
}else{
fmt.Printf("%+v",row)
}
}
func checkErr(err error){
if err!=nil {
panic(err)
}
}
output:
&map[col1:abc col2:123]