invalid sql type (slice) for postgres - postgresql

I want to AutoMigrate my Model but I get this error when running up:
invalid sql type (slice) for postgres
Here is my struct:
type Tracking struct {
ServerID int64
Tracks []map[string]interface{}
}
Im using gorm to work with the DB. (github.com/jinzhu/gorm)
The error comes from: AutoMigrate(&Tracking{})
Is there a solution to this?
Thanks already

The short answer is gorm and most SQL databases don't support slices as a data type. To work around this you need to tell gorm to set up a many to many relationship table.
Table1 <----> (Table1/Table2) <----> Table2
I was attempting the same thing, the gorm documentation advised the following and it worked for me:
type User struct {
gorm.Model
Languages []Language `gorm:"many2many:user_languages;"`
}
type Language struct {
gorm.Model
Name string
}
Taking a guess at yours I would do:
type Tracking struct {
ServerID int64
Tracks []Tracks `gorm:"many2many:tracking_tracks;"`
}
type Tracks struct {
gorm.Model
Text string
}
This sets up three tables as previously mentioned, your trackings table, your tracks table and a third one called tracking_tracks which will store the id to id relationship (many to many)
It's then important to note that for data you are querying from one table where there is a relationship with another table, you will need to Preload() those tables.
Using the gorm example you would do the following
var users []User
db.Preload("Languages").Find(&users)
Not doing this will return the users with the languages column empty.
If many to many doesn't suit you can try a has many or one to many relationship if that is more suitable https://gorm.io/docs/has_many.html

Related

How can I specify custom GraphQL types for a Postgres view in Hasura?

I have a view that I'm tracking in Hasura. I essentially query one table and left-join additional data from other tables onto it:
CREATE
OR REPLACE VIEW "public"."user_summary" AS
SELECT
u.id AS user_id,
u.display_name AS user_display_name,
s.display_name AS subscription_display_name
FROM
user u
LEFT JOIN subscription s ON (u.id = s.user_id)
However, the GraphQL schema that Hasura generates for this view looks like this:
type userSummary {
user_id: Int
user_display_name: String
subscription_display_name: String
}
Specifically, all of the types are optional. It might make sense for subscription_display_name to be missing — I'm using a left join because not all users have subscriptions — but a user ID and display name are always present and don't show up as optional in the types Hasura generates for them.
Is it possible to provide better types to Hasura for this view? Or separately, is there something I'm missing that causes all of these properties to be marked as optional?

Gorm model on update overwriting fields that I want to ignore

I'm using gorm(GoLang) with PostgreSQL.
recently I've decided to use association with gorm in order to save time and for best practice...
So the issue is that I want to update a model without overwriting all his fields.
for example' I have this structs:
type Car struct {
gorm.Model
CarModels []CarModel `json:"car_models"`
Foo string `json:"foo"`
}
type CarModel struct {
gorm.Model
Name string `json:"name"`
Bar string `json:"-"`
CarID uint `json:"car_id"`
}
The user can only see the car model name and car_id.
The user changed the car model name and asked to save it.
I want to save the changes to DB and Gorm db.Update()
so I save the Car model (not the CarModel !!!) because they are associated
And the issue is that field Bar is empty on DB... because I didn't return it to the client...
I've tried to find an answer here and on Gorm docs and didn't find any...
Does someone have any idea how to handle this problem?

Retrieving arbitrary data into nested object with ORM

I am attempting to develop an api in go, to allow the user to specify an arbitrary data structure, and easily set up endpoints that perform CRUD operations on an auto generated postgres database, based on the structure that they define.
For now, I have been using gorm, and am able to have a database automatically generated based on a user-defined set of structs, that support all types of relations (has one, one to many, etc.). I am also able to insert into the generated database, when JSON is sent in through the endpoints.
The issue I have discovered, is when I try to receive the data. It seems where many of the go ORMs fall short on, is mapping data from all tables back into the nested structs of the parent struct.
For example, if the user defines:
type Member struct {
ID string
FirstName string
Hometown Hometown `gorm:"ForeignKey:MemberRefer"`
}
type Hometown struct {
ID string
City string
Province string
MemberRefer string
}
The database creates the tables:
Members
id
first_name
Hometowns
id
city
province
member_refer
However, when retrieving the data, all that is mapped back is:
{
"id": "dc2bb591-506f-40a5-a141-bdc0c8410ba1",
"name": "Kevin Krishna",
"hometown": {
"id": "",
"city": "",
"province": ""
}
}
Does anyone know of a go orm that supports this kind of behaviour?
Thanks
5 sec google search showed me the answer:
Preloading associations
Now that you actually have them properly related, you can .Preload() get the nested object you want:
db.Preload("GoogleAccount").First(&user)
Get nested object in structure in gorm
https://www.google.com/search?q=gorm+nested+struct+golang

How to prevent duplicate id in creating objects from SPA? Or should I stay with the db?

I have a react app that fetches data from golang api which queries data from postgres database. One of my models is deeply nested JSON so I used JSONB datatype in postgres.
CREATE table rules (
id serial primary key,
rule jsonb
);
In golang, I have the structure
type Rule struct {
ID int `json:"id"`
Name string `json:"name"`
...succeeding fields are deeply nested data
}
And in the SPA I have the model
interface Rule {
id number
name string
....same as from the golang api model
}
To create a new Rule object in the SPA, I assign 0 to id. The newly created rule is sent to golang rest api. Then in the api, I first ask the postgres database for the next value for the serial id (using POSTGRES nextval), assign that acquired id into the Rule struct ID field,
nextValidId := <result of nextval>
rule.ID = nextValidId
JSON marshal the rule object then insert to db
ruleBytes, _ := json.Marshal(rule)
INSERT INTO rules_table VALUES (<nextValidId>, <ruleBytes>);
This way I avoided duplicate ids which may happen if an SPA is handling the Id generation. However, I find my method somewhat complicated already. I know I can generate ids from SPA too but how do I avoid duplicated ids without using the method I used above? or am I overthinking things?
Update1:
I also thought about adding another Rule struct in golang without the ID field so that I don't have to use nextval just to put the id inside the JSON, but is it a good programming design to have multiple models for inserting and retrieving from db and another model for response to the SPA?
Let the database generate the new id since that's exactly SERIAL types are for in PostgreSQL.
In golang, you can insert a new record and retrieve the generated id by using sql.DB.QueryRow(...) and .Scan() using an insert statement with a RETURNING clause, e.g.:
var newId int
query := "INSERT INTO rules (rule) VALUES ($1) RETURNING id"
err := db.QueryRow(query, newRule).Scan(&newId)
// TODO: check err
log.Printf("newId=%d", newId)

Can I rename GORM's "version" field? (Grails 2.2 + GORM MongoDB)

I've got a domain object that already has a property called versions, so I'd like to give a different name to the built-in version property (used in GORM for optimistic locking). For instance, I'd like to call it updateCount instead.
Note that I do want the semantics of optimistic locking; I just want to give the field another name. Here's what I've naively tried (and it didn't work):
class Item {
ObjectId id
static hasMany = [versions: ItemVersion]
static mapping = {
table 'item'
version column: 'updateCount' // <-- This was my attempt
}
}
I would definitely appreciate any help in...
Determining whether this is possible, and
If so, making it work :-)
Thanks!
First thing first. MongoDB (NoSQL) deals with Documents and Collections instead of Table and rows.
Being said that, the domain class should look like:
class Item {
ObjectId id
String itemName
static hasMany = [versions: ItemVersion]
static mapping = {
//Collection in Mongodb is to Table in relational world
collection 'item'
//attr in Mongodb is to column in relational world
itemName attr: 'item_name'
//After spending some time investigating it was found that
//attr for version does not make any difference
//The below would not work for implicit GORM variable "version"
//default attribute name is the variable name.
//version attr: 'updateCount'
}
}
In case you want to configure default property across the domains to switch on/off the versioning then have a look at Global Mapping Configuration.