I'm new with Go and GORM. After generating my DB for testing, I don't see that the One To Many relationship is properly represented in Postgres.
I have created a couple of models to be migrated into Postgres, for example, these 2 specifically:
type PgPiece struct {
ID string `gorm:"primary_key"`
Name string
MinPrice float64
Likes int
Description string
Materials string
Techniques string
Width float64
Height float64
Length float64
Hours int
CreatedAt *time.Time
ModifiedAt *time.Time
IsFavorite bool
EstimatedValue float64
Owner PgUser `gorm:"foreignkey:OwnerID"`
OwnerID string
Author PgUser `gorm:"foreignkey:AuthorID"`
AuthorID string
Favorites []PgUser `gorm:"many2many:user_favorite_piece"`
Images []PgPieceImage `gorm:"foreignkey:piece_id"`
}
type PgPieceImage struct {
ID string `gorm:"primary_key"`
Url string
Position int
Width int
Height int
CreatedAt *time.Time
Piece PgPiece `gorm:"foreignkey:PieceRef"`
PieceRef string `gorm:"column:piece_id"`
}
And as result I see this in postgres for PgPieceImage
CREATE TABLE public.piece_image
(
id text COLLATE pg_catalog."default" NOT NULL,
url text COLLATE pg_catalog."default",
"position" integer,
width integer,
height integer,
created_at timestamp with time zone,
piece_id text COLLATE pg_catalog."default",
CONSTRAINT piece_image_pkey PRIMARY KEY (id)
)
WITH (
OIDS = FALSE
)
TABLESPACE pg_default;
ALTER TABLE public.piece_image
OWNER to freddy;
Why there is non FOREIGN CONSTRAINT there?
Related
I'm running a SELECT using WHERE on gorm but the results are comming with the columns store_name and type empty(""). I have the following struct on Go:
type Store struct {
ID uint
StoreName string
Type string
Code string `gorm:"unique"`
Active bool
CreatedAt *time.Time
UpdatedAt *time.Time
}
The following database on Postgres:
CREATE TABLE IF NOT EXISTS stores
(
id BIGSERIAL PRIMARY KEY,
store_name TEXT NOT NULL,
type TEXT NOT NULL,
code TEXT NOT NULL UNIQUE,
active BOOLEAN DEFAULT true,
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ
);
Im running this select right here:
var store Store
result := db.First(&stores).Where("code = ?", code)
if err := result.Error; err != nil {
return nil, err
}
return &stores, nil
Does anyone know what I may be doing wrong? All columns are returned on the SELECT except for the columns StoreName and Type. Thank you so much in advance!
You need to set the field tag if field name differs from DB column name.
Example:
StoreName string `gorm:"column:store_name"`
See this document: https://gorm.io/docs/models.html
I am using Prisma version 3.8.1. Prisma client does not mark the User.oauthData property as nullable in TS. Can someone help? Prisma schema and generated SQL files below:
// This is your Prisma schema file,
// learn more about it in the docs: https://pris.ly/d/prisma-schema
generator client {
provider = "prisma-client-js"
binaryTargets = ["native", "rhel-openssl-1.0.x"]
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model Account {
id BigInt #id
createdAt DateTime #db.Timestamptz(3) #default(now())
updatedAt DateTime #db.Timestamptz(3) #updatedAt
name String
users User[]
}
model User {
id BigInt #id
createdAt DateTime #db.Timestamptz(3) #default(now())
updatedAt DateTime #db.Timestamptz(3) #updatedAt
accountId BigInt
account Account #relation(fields: [accountId], references: [id])
fullName String
email String
oauthData Json?
}
-- CreateTable
CREATE TABLE "Account" (
"id" BIGINT NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3) NOT NULL,
"name" TEXT NOT NULL,
CONSTRAINT "Account_pkey" PRIMARY KEY ("id")
);
-- CreateTable
CREATE TABLE "User" (
"id" BIGINT NOT NULL,
"createdAt" TIMESTAMPTZ(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
"updatedAt" TIMESTAMPTZ(3) NOT NULL,
"accountId" BIGINT NOT NULL,
"fullName" TEXT NOT NULL,
"email" TEXT NOT NULL,
"oauthData" JSONB,
CONSTRAINT "User_pkey" PRIMARY KEY ("id")
);
-- AddForeignKey
ALTER TABLE "User" ADD CONSTRAINT "User_accountId_fkey" FOREIGN KEY ("accountId") REFERENCES "Account"("id") ON DELETE RESTRICT ON UPDATE CASCADE;
I am using Prisma version 3.8.1. Prisma client does not mark the User.oauthData property as nullable in TS. Can someone help? Prisma schema and generated SQL files below:
When working with JSONB fields, there are two types of null allowed: JSON null and DB null.
This is explained in more detail in the Prisma docs for working with JSON fields.
To avoid this ambiguity between the two types of null allowed by the database, we allow one of the following two values:
Prisma.DbNull: The value in the database is a NULL.
Prisma.JsonNull: value in the database contains a JSON value that is null.
This is what those two null values look like in the database (same schema as the one you shared):
prisma-script> select id, "oauthData" from "User"
+---------+-------------+
| id | oauthData |
|---------+-------------|
| 124124 | null |
| 1241241 | <null> |
+---------+-------------+
You can also see this in the generated type for the model User
I have enum filed in the table. When I do a SELECT query with the help of Select() method, I get:
sql: Scan error on column index 1, name "u.duration": converting driver.Value type []uint8 ("MORE") to a int: invalid syntax
my DB structure
CREATE TYPE duration_type AS ENUM ('TWO_MONTHS', 'SIX_MONTHS', 'ONE_YEAR','MORE');
CREATE TABLE shake_hands
(
id uuid,
duration duration_type NOT NULL,
phone_number TEXT,
email_address TEXT,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
);
my structs
type DurationType int
type ShakesHands struct {
ID uuid.UUID `db:"id"`
PhoneNumber string `db:"phone_number"`
Duration DurationType
Email *string `db:"email_address"`
ModelIds []string
}
Anything else need to be pasted here?
I'm using gorm to manage my struct to database mappings.
Right now, I have an existing schema that I'm trying to wrap in an api.
The issue is that in one of my structs, I have a many2many join through another table which doesn't use the default column names.
golang code
type AuthUser struct {
ID *int
Username *string `sql:"size:30"`
FirstName *string `sql:"size:30"`
LastName *string `sql:"size:30"`
Email *string `sql:"size:75"`
IsActive *bool
IsStaff *bool
IsSuperuser *bool
DateJoined *time.Time
LastLogin *time.Time
//ReviewsGroups ReviewsGroups `gorm:"foreignkey:group_id;associationforeignkey:user_id;many2many:reviews_group_users"`
//ReviewsGroups ReviewsGroups `gorm:"many2many:reviews_group_users"`
ReviewsGroups []ReviewsGroup `gorm:"many2many:reviews_group_users"`
}
type ReviewsGroups []ReviewsGroup
func (app *AppEnv) FindAuthUser(username string) (*AuthUser, error) {
var user AuthUser
//var groups []ReviewsGroup
//err := app.DB.Where(&AuthUser{Username: &username}).First(&user).Related(&groups).Error
err := app.DB.Preload("ReviewsGroups").Where(&AuthUser{Username: &username}).First(&user).Error
return &user, err
}
join table
rb=> \d reviews_group_users
Table "public.reviews_group_users"
Column | Type | Modifiers
----------+---------+------------------------------------------------------------------
id | integer | not null default nextval('reviews_group_users_id_seq'::regclass)
group_id | integer | not null
user_id | integer | not null
Indexes:
"reviews_group_users_pkey" PRIMARY KEY, btree (id)
"reviews_group_users_group_id_user_id_key" UNIQUE CONSTRAINT, btree (group_id, user_id)
"reviews_group_users_group_id" btree (group_id)
"reviews_group_users_user_id" btree (user_id)
Foreign-key constraints:
"group_id_refs_id_0f32ed01" FOREIGN KEY (group_id) REFERENCES reviews_group(id) DEFERRABLE INITIALLY DEFERRED
"reviews_group_users_user_id_fkey" FOREIGN KEY (user_id) REFERENCES auth_user(id) DEFERRABLE INITIALLY DEFERRED
resulting query output
[2015-10-30 09:31:32] [1.16ms] SELECT * FROM "auth_user" WHERE ("username" = 'theuser') ORDER BY "auth_user"."id" ASC LIMIT 1
[2015-10-30 09:31:32] [1.85ms] SELECT * FROM "reviews_group" INNER JOIN reviews_group_users ON reviews_group_users."reviews_group_id" = "reviews_group"."id" WHERE (auth_user_id in ('13'))
[2015-10-30 09:31:32] pq: column reviews_group_users.reviews_group_id does not exist
Any help is appreciated.
Thanks!
I think I can refer you to this answer => gorm Many2Many Custom table
Split the relationship into 3 tables or 3 structs if you like. AuthUser, ReviewGroup, and Group.
In your auth user you do the same as you would do with a one-to-many relationship and the same for group.
example:
type AuthUser struct {
ID *int
Username *string `sql:"size:30"`
FirstName *string `sql:"size:30"`
LastName *string `sql:"size:30"`
Email *string `sql:"size:75"`
IsActive *bool
IsStaff *bool
IsSuperuser *bool
DateJoined *time.Time
LastLogin *time.Time
ReviewsGroups []ReviewsGroup `gorm:"foreignKey:User_id;references:ID;"`
}
type Group struct {
ID uint `gorm:"primaryKey"`
param string
ReviewsGroups []ReviewsGroup
}
type ReviewGroup struct {
User_id uint `gorm:"primaryKey"`
User AuthUser `gorm:"foreignKey:ID;references:User_id"` // not necessary unless you want to be able to navigate via this model
Group_id uint `gorm:"primaryKey"`
Group AuthUser `gorm:"foreignKey:ID;references:Group_id"` // not necessary unless you want to be able to navigate via this model
param string
}
Hope it helps!
I am having trouble generating my tables in PostgreSQL from Grails. I have simple Email and EmailAttachment domain classes with a hasMany and belongsTo relationship. This setup worked well on our production server (AS400 DB2), but when I try to run my program on PostgreSQL (the new dev environment), the Email class does not have the attachment_id column.
Email.groovy:
class Email {
static hasMany = [attachments:EmailAttachment]
Integer id
Integer version = 0
String subject
String recipients
String sender
Date sentDate
String plainTextMessage
Set attachments
static mapping = {
datasources(['DEFAULT'])
table name:'error_email', schema: Appointment.schema
sort sentDate:'desc'
}
static constraints = {
subject nullable:true
version nullable:true
recipients nullable:true
sender nullable:true
sentDate nullable:true
plainTextMessage nullable:true
attachments nullable:true
}
def String toString(){
return subject
}
}
EmailAttachment.groovy:
class EmailAttachment {
static belongsTo = [email:ErrorEmail]
ErrorEmail email
String filename
byte[] content
static mapping = {
datasources(['DEFAULT'])
table name:'error_email_attachment', schema: Appointment.schema
}
static constraints = {
filename nullable:true
content nullable:true
}
}
Also, here are the relevant lines from schema-export:
alter table program.email_attachment drop constraint FK2E592AFD1D80E229;
drop table program.email cascade;
drop table program.email_attachment cascade;
drop sequence hibernate_sequence;
create table program.email (id int4 not null, version int4, plain_text_message varchar(255), recipients varchar(255), sender varchar(255), sent_date timestamp, subject varchar(255), primary key (id));
create table program.email_attachment (id int8 not null, version int8 not null, content bytea, email_id int4 not null, filename varchar(255), primary key (id));
alter table program.email_attachment add constraint FK2E592AFD1D80E229 foreign key (email_id) references program.error_email;
create sequence hibernate_sequence;
I've tried specifying joinTable: attachments joinTable:[name: 'email_table', column: 'attachment_id', key: 'id'] to no avail, as well as leaving it out, and trying other collection types for attachment. Thanks in advance for your time and brain cells.
The email doesn't have an attachment_id column because it's the one side of the one-to-many. The many side, attachment in this case, has a reference to its owning email in the email_id int4 not null column. Given an email with id 42 you (and Grails/GORM/Hibernate) can find all of the attachments by querying for all rows in that table with email_id=42.