column "name" of relation "users" does not exist - postgresql

Im trying to insert the user name to a posgres database but i got this error
Im Using heroku psql.
2022/03/01 03:52:54 pq: column "name" of relation "users" does not exist
m y code:
func createDB(db *sql.DB) {
// create users table if not exists
createTableUsers := "CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY,name TEXT);"
statement, err := db.Prepare(createTableUsers)
if err != nil {
log.Fatal(err)
}
statement.Exec()
log.Println("Created table users")
}
func insertData(db *sql.DB, id string, name string) {
log.Println("Inserting data")
insertUser := "INSERT INTO users (name) VALUES ($1) RETURNING id;"
err := db.QueryRow(insertUser, name).Scan(&id)
if err != nil {
log.Println(err)
}
fmt.Println("New record ID is:", id)
}

Related

failed to check if row with value exists In Postgres with Golang

I'am trying to create registration in my Telegram Bot with Golang and Postgres. When user writes "register", bot has to check if user's uuid already exists in DB, and if not to create row with his uuid.
Here is my function to check if uuid already exists in DB:
func IsUserInDB(uuid int64) (bool, error) {
var exists bool
query := fmt.Sprintf("SELECT EXISTS(SELECT 1 FROM users WHERE uuid = %d);", uuid)
err := Db.QueryRow(query).Scan(&exists)
return exists, err
}
Here is my function for adding user's uuid to DB:
func AddUserToDB(column string, row interface{}) error {
query := fmt.Sprintf("INSERT INTO users (%s) VALUES (%v);", column, row)
_, err := Db.Exec(query)
return err
}
And the logic for bot:
func (b *Bot) handleMessages(message *tgbotapi.Message) error {
switch message.Text {
case "register":
exists, err := data.IsUserInDB(message.From.ID)
if err != nil {
return err
}
if !exists {
err := data.AddUserToDB("uuid", message.From.ID)
return err
}
return nil
default:
msg := tgbotapi.NewMessage(message.Chat.ID, "unknown message...")
_, err := b.bot.Send(msg)
return err
}
}
First time, when I send "register", bot successfully adds user's id to db, but the problem happens if I try to send "register" 1 more time. IsUserInDB() returns me false and bot adds 1 more row with the same uuid. So, I think problem is with my IsUserInDb() function
Why not just a unique index on your users table?
CREATE UNIQUE INDEX unq_uuid ON users (uuid);
Then you don't have to check, you just try to insert and it will return an error if it already exists.

Go is querying from the wrong database when using multiple databases with godotenv

I'm trying to query from multiple databases. Each database is connected using the following function:
func connectDB(dbEnv str) *sql.DB{
// Loading environment variables from local.env file
err1 := godotenv.Load(dbEnv)
if err1 != nil {
log.Fatalf("Some error occured. Err: %s", err1)
}
dialect := os.Getenv("DIALECT")
host := os.Getenv("HOST")
dbPort := os.Getenv("DBPORT")
user := os.Getenv("USER")
dbName := os.Getenv("NAME")
password := os.Getenv("PASSWORD")
// Database connection string
dbURI := fmt.Sprintf("port=%s host=%s user=%s "+"password=%s dbname=%s sslmode=disable", dbPort, host, user, password, dbName)
// Create database object
db, err := sql.Open(dialect,dbURI)
if err != nil {
log.Fatal(err)
}
return db
}
type order struct{
OrderID string `json:"orderID"`
Name string `json:"name"`
}
type book struct{
OrderID string `json:"orderID"`
Name string `json:"name"`
}
func getOrders(db *sql.DB) []order {
var (
orderID string
name string
)
var allRows = []order{}
query := `
SELECT orderID, name
FROM orders.orders;
`
//Get rows using the query
rows, err := db.Query(query)
if err != nil { //Log if error
log.Fatal(err)
}
defer rows.Close()
// Add each row into the "allRows" slice
for rows.Next() {
err := rows.Scan(&orderID, &name, &date)
if err != nil {
log.Fatal(err)
}
//Create new order struct with the received data
row := order{
OrderID: orderID,
Name: name,
}
allRows = append(allRows, row)
}
//Log if error
err = rows.Err()
if err != nil {
log.Fatal(err)
}
return allRows
}
func getBooks(db *sql.DB) []book{
var (
bookID string
name string
)
var allRows = []book{}
query := `
SELECT bookID, name
FROM books.books;
`
//Get rows using the query
rows, err := db.Query(query)
if err != nil { //Log if error
log.Fatal(err)
}
defer rows.Close()
// Add each row into the "allRows" slice
for rows.Next() {
err := rows.Scan(&bookID, &name)
if err != nil {
log.Fatal(err)
}
//Create new book struct with the received data
row := book{
BookID: bookID,
Name: name,
}
allRows = append(allRows, row)
}
//Log if error
err = rows.Err()
if err != nil {
log.Fatal(err)
}
return allRows
}
func main() {
ordersDB:= connectDB("ordersDB.env")
booksDB:= connectDB("booksDB.env")
orders := getOrders(ordersDB)
books := getBooks(booksDB)
}
The issue is that when I use ordersDB first, the program only recognizes the table in ordersDB. And when I use booksDB first, the program only recognizes the table in booksDB.
When I try to query a table in booksDB after using ordersDB, it is giving me "relation "books.books" does not exist" error. When I try to query a table in ordersDB after using booksDB, it gives "relation "orders.orders" does not exist"
Is there a better way to connect to multiple databases?
You are using github.com/joho/godotenv to load the database configuration from the environment. Summarising (and cutting out a lot of detail) what you are doing is:
godotenv.Load("ordersDB.env")
host := os.Getenv("HOST")
// Connect to DB
godotenv.Load("booksDB.env")
host := os.Getenv("HOST")
// Connect to DB 2
However as stated in the docs "Existing envs take precedence of envs that are loaded later". This is also stated more clearly here "It's important to note that it WILL NOT OVERRIDE an env variable that already exists".
So your code will load in the first .env file, populate the environment variables, and connect to the database. You will then load the second .env file but, because the environmental variables are already set, they will not be changed and you will connect to the same database a second time.
As a work around you could use Overload. However it's probably better to reconsider your use of environmental variables (and perhaps use different variables for the second connection).

How to avoid duplicate row while gorm AutoMigrate

I want to insert to database from CSV file using gorm AutoMigrate and while inserting I want to avoid duplicate entry. How Can I achieve this? Please check the attached code.
type User struct {
gorm.Model
ID int64 `csv:"_" db:"id"`
FirstName string `csv:"First name" db:"first_name"`
LastName string `csv:"Last name" db:"last_name"`
Emails string `csv:"Emails" db:"emails"`
}
func main() {
file, err := os.Open(os.Args[1])
defer file.Close()
users := []User{}
err = gocsv.Unmarshal(file, &users)
db, err := gorm.Open(postgres.Open("host=xxx.xx.x.x user=database password=password dbname=database port=5432 sslmode=disable"))
err = db.AutoMigrate(&User{})
if err != nil {
panic(err)
}
result := db.Create(users)
if result.Error != nil {
panic(result.Error)
}
}
Example: Consider the below data
FIrst name
Last name
Emails
First
Name
first#example.com
Second
Name
second#example.com
Third
Name
Forth
Name
first#example.com
If we pass the above data, the first 3 rows should insert into the database i.e. we have to avoid duplicate email entries to the database. Thanks.
Note: If the email is empty then the row should be inserted into the database.
You have to sanitize "users" after err = gocsv.Unmarshal(file, &users)
Somethink like
func sanytize(arr []User) []User {
users := []User{}
mail := []string{}
for _, a := range arr {
if !contains(mail, a.Emails){
users = append(users, a)
}
mail = append(mail, a.Emails)
}
return users
}
func contains(arr []string, str string) bool {
for _, a := range arr {
if a == str {
return true
}
}
return false
}
....
err = gocsv.Unmarshal(file, &users)
users = sanytize(users)

PostgreSQL: "pq: column of relation does not exist" when executing query from code, but it works fine in console

I'm writing simple models for interacting with postgresql db in my api, and all of them work fine except one table. When i try to run tests i get an error:
=== RUN TestAddUser
time="2018-08-08T10:24:56+03:00" level=info msg="db connection" db: ="&{0xc4200c6dc0 postgres false 0xc4200912c0}"
--- FAIL: TestAddUser (0.00s)
require.go:794:
Error Trace: users_test.go:19
Error: Received unexpected error:
pq: column "user_name" of relation "users" does not exist
Error while trying to add new user
gitlab.com/inn4sci-go/Nesterenko/course/api/models.AddUser
/home/nestor/go/src/gitlab.com/inn4sci-go/Nesterenko/course/api/models/users.go:20
gitlab.com/inn4sci-go/Nesterenko/course/api/models/tests.TestAddUser
/home/nestor/go/src/gitlab.com/inn4sci-go/Nesterenko/course/api/models/tests/users_test.go:18
testing.tRunner
/usr/local/go/src/testing/testing.go:777
runtime.goexit
/usr/local/go/src/runtime/asm_amd64.s:2361
Test: TestAddUser
FAIL
Process finished with exit code 1
But if i run same query from psql console all works fine:
nestor=> INSERT INTO users (user_name, user_pass) VALUES ('wrerw','wrwer');
INSERT 0 1
nestor=>
Here the code of AddUser func and Users struct:
package models
import (
"github.com/pkg/errors"
"gitlab.com/inn4sci-go/Nesterenko/course/api/db"
)
type Users struct {
Id int `db:"id" json:"id"`
ProfileId int `db:"profile_id" json:"profileId"`
UserName string `db:"user_name" json:"nickname"`
UserPass string `db:"user_pass" json:"password"`
}
func AddUser(db db.DbInt, user Users) (int64, error) {
query := `INSERT INTO users (user_name, user_pass) VALUES (:user_name, :user_pass)`
res, err := db.GetDB().NamedExec(query, &user)
if err != nil {
return 0, errors.Wrap(err, "Error while trying to add new user")
}
id, err := res.LastInsertId()
if err != nil {
return 0, errors.Wrap(err, "Error while trying to obtain userId")
}
return id, nil
}
Here code of test func:
func TestAddUser(t *testing.T) {
mockDB := testutils.CreateFakeDBObj(t) //this func mocks db connection, and works fine in all test
user := models.Users{
UserName: "test",
UserPass: "test",
}
userId, err := models.AddUser(mockDB, user)
require.NoError(t, err)
logrus.WithField("User was successfully added with id = ", userId).Info("Users test")
}
And this is query for creating users table:
nestor=> CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, profile_id INTEGER REFERENCES profile(id), user_name TEXT UNIQUE NOT NULL, user_pass TEXT NOT NULL);
CREATE TABLE
nestor=> \dt users
List of relations
Schema | Name | Type | Owner
--------+-------+-------+-------
public | users | table | ihor
(1 row)
I suppose that i have got a mistake somewhere in AddUser func when trying to execute this query: INSERT INTO users (user_name, user_pass) VALUES (:user_name, :user_pass)
EDITED:
Establishing connection to db:
type MockingDBObj struct {
mock.Mock
}
func (m MockingDBObj) ConnectToDB(c configure.ConfigInt) error {
return nil
}
func (m MockingDBObj) GetDB() *sqlx.DB {
args := m.Called()
return args.Get(0).(*sqlx.DB)
}
func CreateFakeDBObj(t *testing.T) MockingDBObj {
mockObj := new(MockingDBObj)
host := "localhost"
port := 5432
user := "ihor"
password := "ihor"
dbname := "final_project"
psqlInfo := fmt.Sprintf("host=%s port=%d user=%s "+
"password=%s dbname=%s sslmode=disable",
host, port, user, password, dbname)
db, err := sqlx.Connect("postgres", psqlInfo)
require.NoError(t, err)
logrus.WithField("db: ", db).Info("db connection")
mockObj.On("GetDB").Return(db)
return *mockObj
}

Convert client UUID to SQL UUID

I'm using go and the package uuid to generate a uuid of type [16]byte. However when I try to insert that uuid into my postgres column of type uuid I get the error converting argument $1 type: unsupported type [16]uint8, a array. So apparently I should convert the uuid on the client before I insert it into the db. How should I do that? What type should I convert it to?
In short: What go data type will work with uuid in postgres?
Thanks to the link from #sberry, I found success. Here are snippets of the code for your benefit (with a PostgreSQL 9.5 database):
import (
"database/sql"
"net/http"
"github.com/google/uuid"
)
type Thing struct {
ID uuid.UUID `json:"-" sql:",type:uuid"`
Name string `json:"name"`
}
// For a database table created as such:
// CREATE TABLE things (
// id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
// name TEXT DEFAULT ''::text
// )
func selectThingssSQL() ([]Thing, error) {
things := make([]Thing, 0)
rows, err := db.Query("SELECT id, name FROM things")
if err != nil {
return nil, err
}
defer rows.Close()
for rows.Next() {
t := &Thing{}
if err := rows.Scan(&t.ID, &t.Name); err != nil {
return nil, err
}
things = append(things, *t)
}
return things, nil
}