Automigrate in GORM database adds unwanted fields to SQL table - postgresql

When I create my tables in the gorm database, it adds columns to the table that I don't want. I'm not sure how it's adding these extra fields. This causes me to run into an error that says, "pq: null value in column "user_id" violates not-null constraint". "user_id" is the unwanted column that gets added. I'm using gorm and postgreSQL.
I have a many to many relationship for my two tables. My first table is created properly and my second table, stores, is created with the provided fields plus two unwanted fields: "user_id" and "stores_id". I've tried removing the many to many relationship to see if that was the issue, I've tried dropping the tables and recreating them with different fields. Regardless, I have not been able to get rid of the two extra columns.
The first (working) table:
type User struct {
gorm.Model
ID int `json:"u_id"`
Name string `json:"u_name"`
Stores []Store `gorm:"many2many:stores;" json:"stores"`
}
When I execute '\d users', I get the following columns: id, created_at, updated_at, deleted_at, name.
The second (problematic) table:
type Stores struct {
gorm.Model
ID int `json:"s_id"`
NUM int `gorm:"unique" json:"s_num"`
Users []User `gorm:"many2many:user" json:"users"`
}
When I execute '\d' stores, I get the following columns: user_id, vehicle_id, id, created_at, updated_at, deleted_at, num.
I'm executing the creation of these tables through the following code:
db.AutoMigrate(&User{})
db.AutoMigrate(&Store{})
On another note, if I add gorm:"primary_key";auto_increment" to my ID values in my structs, I get the error "pq: column "user_id" appears twice in primary key constraint". I was able to get around this by removing the primary_key and auto_increment attributes, running AutoMigrate() and then adding it back in and running AutoMigrate() again - this was totally fine and working.
I've also tried manually inserting a user_id and store_id. This works fine, except that I'd have to generate new ones every time because they require uniqueness. I understand that the error "pq: null value in column "user_id" violates not-null constraint" is caused by the fact that I'm not providing a user_id or store_id when I'm creating my store. I'm simply confused why a user_id and store_id column is being generated at all, and I'm hoping I can fix that.

This is what gorm.Model looks like
type Model struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
}
When we call gorm.Model inside a struct, it means we are add default fields of gorm.Model in our current struct.
type Stores struct {
gorm.Model
....
so your user model will look something like
ype User struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt *time.Time
ID int `json:"u_id"`
Name string `json:"u_name"`
Stores []Store `gorm:"many2many:stores;" json:"stores"`
}
that error mayne due to duplicate primary_key key. try to rename ID intjson:"u_id"`` to UserID. you need to update Stores too.

Fixed the duplicate ID errors by removing gorm.Model, as #(Akshaydeep Girl) pointed out what having gorm.Model entails. As for the random 'user_id' and 'store_id' that kept automatically being added, they were being added because of the many2many gorm relationship. I was able to remove those by switching the order of migration.
func DBMigrate(db *gorm.DB) *gorm.DB {
db.AutoMigrate(&Store{})
db.AutoMigrate(&User{})
return db
}
When I dropped both tables and re-compiled/ran my project with the new order of migration, the stores table was created without the random 'user_id' and 'store_id', and the users table didn't have those either.

Related

GORM - uniqueIndex with soft delete

I'm using Gorm's unique index to enforce a certain ordering of elements
type Element struct {
gorm.Model
ID int `gorm:"primary_key"`
Index int `gorm:"uniqueIndex:unique_order"`
ParentID int `gorm:"uniqueIndex:unique_order"`
}
The problem I'm running into is when I create and delete multiple elements I start to get an error like
ERROR: duplicate key value violates unique constraint "unique_order" (SQLSTATE 23505)
This is happening because Gorm soft deletes elements by setting deleted_at, but the rows still exist in the database and the unique index is still enforced.
I know I can get around this using a partial index in Postgres SQL, but I'm wondering if there's a way I can handle this with Gorm?

GORM Foreign Key Constraints with Multiple Tables With Same Primary Keys

I am new to using GORM and have inherited some code that is linked with postgresql.
In the "models" folder, there are 2 existing tables, using a single foreign key relationship on the 2nd table.
The foreign key doesn't specify which table the foreign key relationship is pointing to, however in this specific example there are only 2 tables.
Therefore, perhaps it can be assumed that the foreign key must point to the second table?
type Criteria struct {
Name string `gorm:"primaryKey; default:null; unique;not null" json:"name" uri:"criteria_name"`
Created_At time.Time `json:"article_url" uri:"-"`
Article_Url string `uri:"thing" test:"testing" gorm:"unique;not null" json:"test_Article_URL" uri:"-"`
Location string `json:"Location" uri:"pID" gorm:"primaryKey"`
}
type CriteriaVersions struct {
Name string `json:"name" gorm:"primaryKey" uri:"criteria_name" gorm:"foreignKey:Name,Location"`
Version_Number int `json:"number" gorm:"primaryKey" uri:"version_number"`
Source datatypes.JSON `json:"source" uri:"-"`
Created_At time.Time `json:"-" uri:"-"`
Diagnosed_Updated_At time.Time `json:"-" uri:"-"`
Location string `json:"practice" gorm:"primaryKey" uri:"Location"`
}
As can be seen, the foreign key doesn't specify what table it is pointing at.
So, if I added a new table with something like:
type Person struct {
Name string `gorm:"primaryKey"`
Location string `gorm:"primaryKey"`
}
What is linking the 2 first tables? As if I try and add a new Criteria Version, then this is still being validated against the Criterias table.
To clarify, I do not want to change the reference to point to the Doctors table, but I want to understand how it chooses which table to reference.
For example, if I have a table with:
Criterias
Name
Article_Url
Location
Name1
www.google.com
America
Name2
www.bing.com
Germany
and another table with:
Doctors
Name
Location
Doctor Who
Gallifrey
Doctor Do-Little
USA
Doctor Hibbert
Springfield
and I try to add a new Criteria Version containing:
name: "Doctor Who", location: "Gallifrey"
This is only validated against the Criterias table, and is therefore rejected:
ERROR: insert or update on table "criteria_versions" violates foreign key constraint "criteria_versions_name_fkey" (SQLSTATE 23503)
Whilst if I add a new Criteria Version containing:
name: "Name1", location: "America"
This does successfully add to my Criteria Versions table.
Any explanation is appreciated, as well as advice on making it more verbose (I think this is via using references, but I wanted to understand this bit first)!

How to get return value from insert query defined in #query annotation

I have two tables city and shape, where city has composite primary key as(City and country) and one auto generated Id value. This Id is foreign key for Shape.
So after insertion of data in city table, I want Id that was inserted to be used in shape table. I have used Spring boot with jpa and postgres
In CityRepository I have custom save method which will do nothing on conflict.
I have tried below code to get returned value. But I get Error
SqlExceptionHelper : A result was returned when none was expected.
How to get the returning value from insert query?
#Modifying
#Query(value="insert into public.city_info(city, country) values(:city,:country) on conflict do nothing returning city_id",nativeQuery = true)
#Transactional
Integer save(#Param("city")String city,#Param("country") String country);
I'm afraid but that's not possible with JPA.
If you look at the JPA Query API:
int executeUpdate()
Execute an update or delete statement.
Returns: the number of entities updated or deleted
There is no other return value possible.

How to use mattes/migrate in golang?

I've been trying to use the mattes/migrate package but I can't seem to get it to actually do anything. The database runs on postgres and I interact with it through sqlx.
I've gone through the readme on github, and applied the following code:
// use synchronous versions of migration functions ...
allErrors, ok := migrate.UpSync("postgres://<my_url_string>", "./app/database/migrations")
if !ok {
fmt.Println("Oh no ...")
// do sth with allErrors slice
}
My schema is initiated like this:
//sqlx's initiated DB is imported in the database package
func SyncSchemas() {
database.DB.MustExec(schema)
}
var schema =
`CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE IF NOT EXISTS examples (
created_at TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT NOW(),
deleted_at text DEFAULT NULL,
id UUID PRIMARY KEY UNIQUE NOT NULL DEFAULT uuid_generate_v4()
);`
type Example struct {
ID string `json:"id" db:"id"`
CreatedAt time.Time `json:"created_at" db:"created_at"`
DeletedAt *time.Time `json:"deleted_at" db:"deleted_at"`
}
It runs without error, but that's all it seems to be doing at the moment. Shouldn't it keep track of my schemas or something? I previously used gorm as my ORM, and there I just had to run autoMigrate() on a schema and it automatically created and applied migrations as I changed the schema. I would like the same functionality with mattes/migrate, but I can't seem to find an example or tutorial which shows how to use it.
How am I supposed to do this?
One suggestion in whenever you code in Golang is to check the errors do it in this way
if allErrors, ok := migrate.UpSync("postgres://<my_url_string>", "./migrations"); !ok {
fmt.Println("Oh no ...", ok)
// do sth with allErrors slice
}
As I don't know what is your error at least in this way you can check what your error is.

How to use Entity Framework 6 to update many-to-many relationship?

Someone else asked a similar question here: How can I use EF6 to update a many to many table
I mention that up front because I couldn't get any of the solutions given to work.
I also studied the solution give on Code Project: http://www.codeproject.com/Tips/893609/CRUD-Many-to-Many-Entity-Framework, but this doesn't work for me either.
I'm trying to keep this as simple as possible.
I have two tables: dbo.Teacher and dbo.Student. Each has an "ID" column that servers as a primary key. I also have a third table called dbo.StudentTeacher which has exactly two columns, both are non-nullable and foreign keyed to the previous two tables; in other words, it establishes a many-to-many relationship between teachers and students. As expected, the EDMX designed shows only dbo.Student and dbo.Teacher and infers the relationship between them.
Here is a script for the above; there is nothing else in the database.
CREATE TABLE dbo.Teacher
(
Id INT NOT NULL PRIMARY KEY,
Name VARCHAR(MAX)
);
CREATE TABLE dbo.Student
(
Id INT NOT NULL PRIMARY KEY,
Name VARCHAR(MAX)
);
CREATE TABLE dbo.TeacherStudent
(
TeacherId INT NOT NULL FOREIGN KEY REFERENCES Teacher(Id),
StudentId INT NOT NULL FOREIGN KEY REFERENCES Student(Id)
);
INSERT INTO Teacher(Id, Name)
VALUES
(101, 'Tom');
INSERT INTO Student(Id, Name)
VALUES
(201, 'Sue'),
(202, 'Stan');
INSERT INTO TeacherStudent(TeacherId, StudentId)
VALUES
(101, 201);
Now that I've established my data structures, I want to accomplish a very simple task. From the script above, you can see that we have one teacher named "Tom" who has a student named "Sue". We also have a student named "Stan" with no teacher. My task is to modify the database so that Sue is no longer Tom's student and Stan becomes Tom's student.
To accomplish this, I wrote the following code:
class Program
{
static void Main(string[] args)
{
using (var entities = new TestEntities())
{
// There is only one teacher in the system.
Teacher teacher = entities.Teachers.Single();
// This teacher has a student #201: Sue.
// I want to replace her with student #202: Stan.
teacher.Students.Clear();
teacher.Students.Add(new Student() { Id = 202 });
entities.SaveChanges();
}
}
}
It looks very simple: clear the students associated with Tom and then add Stan as Tom's student. However, when I run the code, I get the following error: Unable to update the EntitySet 'TeacherStudent' because it has a DefiningQuery and no <DeleteFunction> element exists in the <ModificationFunctionMapping> element to support the current operation.
I tried simplifying the problem by trying to just remove Sue from being Tom's student without adding Stan, and I get the exact same error message.
As I understand, this error normally occurs when Entity Framework doesn't have enough information to do what you want it to do, but I really can't see what's missing. There are two simple tables with a join table between them and I need to be able to change which rows are related to which other rows.
I should also note that if I'm not mistaken, the change that I wish to make in this example should affect only the dbo.TeacherStudent table; the other two tables should not be touched.
Okay, after some more Google-Fu, I figured it out.
Even tho the join table must have only two columns with each column foreign keyed to the two tables to be related, the join table still needs a primary key, which can be a composite of the two foreign keys.
Thus, dbo.TeacherStudent should be created with this:
CREATE TABLE dbo.TeacherStudent
(
TeacherId INT NOT NULL FOREIGN KEY REFERENCES Teacher(Id),
StudentId INT NOT NULL FOREIGN KEY REFERENCES Student(Id),
PRIMARY KEY(TeacherId, StudentId)
);