Skip to content

Support for multiple/composite primary keys on new relation tag pg:"rel:" #1757

@vilipwong

Description

@vilipwong

As previously discussed in Discord, there are problems in query generation when using multiple primary keys

A quick fix has been done in 5882d9f to address the issue i raised. However it occur for other relations as well, rel:has-one,has-many etc, more details below:

Expected Behavior

I should be able to retrieve ProjectDocument with Project relation with relation tag has-one, has-many,belongs-to

Current Behavior

encounter panic: pg: ProjectDocument has-one Project: ProjectDocument must have column project_company_id (use fk:custom_column tag on Project field to specify custom column)

Steps to Reproduce

CREATE TABLE projects
(
  id              VARCHAR(128) ,
  company_id              VARCHAR(128) ,
  PRIMARY KEY (company_id, id)
);
CREATE TABLE documents
(
    id                           VARCHAR(128) ,
    company_id              VARCHAR(128) ,
    PRIMARY KEY (company_id, id)
);
CREATE TABLE project_documents
(
    company_id              VARCHAR(128) ,
    project_id              VARCHAR(128) ,
    document_id              VARCHAR(128) ,
    PRIMARY KEY(company_id, project_id, document_id),
    FOREIGN KEY (company_id, project_id) REFERENCES projects (company_id, id),
    FOREIGN KEY (company_id, document_id) REFERENCES documents (company_id, id)
);
package main

import (
    "fmt"

    "github.com/caarlos0/env"
    pg "github.com/go-pg/pg/v10"
    "github.com/go-pg/pg/v10/orm"
)

// DB Configuration
type DB struct {
    Address      string `env:"DB_ADDRESS,required"`
    Port         string `env:"DB_PORT,required"`
    Username     string `env:"DB_USERNAME,required"`
    Password     string `env:"DB_PASSWORD,required"`
    DatabaseName string `env:"DB_NAME,required"`

    EnableLogging bool `env:"DB_ENABLE_LOGGING"`
}

// New up DB config
func New() (*DB, error) {
    d := &DB{}
    err := env.Parse(d)
    return d, err
}

// Connect to DB
func (d *DB) Connect() (*pg.DB, error) {
    opts := &pg.Options{
        User:     d.Username,
        Password: d.Password,
        Database: d.DatabaseName,
        Addr:     d.Address + ":" + d.Port,
    }
    db := pg.Connect(opts)

    _, err := db.Exec("SELECT")
    return db, err
}

func main() {
    qwe := &ProjectDocument{
        ID:        "bsvt22v0cr8rnl249230",
        CompanyID: "a9543f45-5ea3-4bcb-81c6-1cba6c278f6d",
    }

    c, _ := New()
    db, _ := c.Connect()

    err := db.Model(qwe).
        WherePK().
        Relation("Project").
        Select()

    fmt.Println("@@@ res", err)

}

type Project struct {
    ID        string     `json:"id" pg:",pk"`
    CompanyID string     `json:"companyID" pg:",pk"`
    Documents []Document `pg:",many2many:project_documents" json:"documents,omitempty"`
}

type Document struct {
    ID        string `json:"id" pg:",pk"`
    CompanyID string `json:"companyID" pg:",pk"`
    Name      string `json:"name"`
}

type ProjectDocument struct {
    CompanyID  string    `json:"companyID" pg:",pk"`
    ProjectID  string    `json:"projectID" pg:",pk"`
    Project    *Project  `json:"project" pg:"rel:has-one"`
    DocumentID string    `json:"documentID" pg:",pk"`
    Document   *Document `json:"document"`
}

func init() {
    orm.RegisterTable((*ProjectDocument)(nil))
}

Context (Environment)

I am trying to link projects into project documents with a tenant key company_id using citus, thus all of the tables have multiple primary keys

Detailed Description

Possible Implementation

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions