Best practices to perform a JOIN with SQLX, Squirrel

Viewed 1292

I have this model.

// Incident is a security incident.
type Incident struct {
    ID          string                 `json:"id" bson:"_id"`
    Title       string                 `json:"title" bson:"title"`
    Description string                 `json:"description" bson:"description"`
    Issue       *Issue                 `json:"issue" bson:"issue"`
    CreatedAt   time.Time              `json:"created_at" bson:"created_at"`
    ModifiedAt  time.Time              `json:"modified_at" bson:"modified_at"`
}

// Issue is a security issue.
type Issue struct {
    ID                         string                 `json:"id" bson:"_id"`
    Title                      string                 `json:"title" bson:"title"`
    IncidentID                 string                 `json:"incident_id"`
    Description                string                 `json:"description" bson:"description"`
}

Each Incident has one Issue.

When I insert an Incident into Postgres, I only add the issue_id.

type incident struct {
    ID          string    `db:"id"`
    CustomerID  string    `db:"customer_id"`
    InternalID  string    `db:"internal_id"`
    Title       string    `db:"title"`
    IssueID     string    `db:"issue_id"`
    Description string    `db:"description"`
    CreatedAt   time.Time `db:"created_at"`
    ModifiedAt  time.Time `db:"modified_at"`
}

func toIncident(model *models.Incident) (*incident, error) {
    // Create the SQL
    incident := &sqlIncident{
        ID:          model.ID,
        CustomerID:  model.CustomerID,
        InternalID:  model.InternalID,
        Title:       model.Title,
        Description: model.Description,
        IssueID:     "",
        CreatedAt:   model.CreatedAt,
        ModifiedAt:  model.ModifiedAt,
    }

    // Add the issue ID
    if model.Issue != nil {
        incident.IssueID = model.Issue.ID
    }

    return incident, nil
}

I would like to be able to do the reverse operation with a JOIN on the Issue when I get() or list() incidents.

I am using "github.com/Masterminds/squirrel" and "github.com/jmoiron/sqlx".

This code below would be the code to get an Incident.

    // Prepare query
    query := squirrel.Select(*).
        From(r.GetTableName()).
        PlaceholderFormat(squirrel.Dollar).
        Join("????????")

    // Build the SQL query
    q, args, err := query.ToSql()
    if err != nil {
        return fmt.Errorf("postgresql: unable to build query: %w", err)
    }

    // Get the session repo
    session := r.GetSession().(*sqlx.DB)

    // Prepare the statement
    stmt, err := session.PreparexContext(ctx, q)
    if err != nil {
        return fmt.Errorf("postgresql: unable to prepapre query: %w", err)
    }

    // Do the query
    err = stmt.SelectContext(ctx, result, args...)
    if err == sql.ErrNoRows {
        return repositories.ErrNoResult
    } else if err != nil {
        return fmt.Errorf("postgresql: unable to execute query: %w", err)
    }

How can I perform this correctly please ?

I am feeling that I am doing this wrong with the issue_id field that seems to be useless, and that I should add the definition of the Issue in my incident SQL structure, something like this below.

type incident struct {
    ID          string    `db:"id"`
    CustomerID  string    `db:"customer_id"`
    InternalID  string    `db:"internal_id"`
    Title       string    `db:"title"`
    Issue       issue     `db:"issue"`
    Description string    `db:"description"`
    CreatedAt   time.Time `db:"created_at"`
    ModifiedAt  time.Time `db:"modified_at"`
}

But I can't see the next steps.

0 Answers
Related