Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create models for the database types (for goqu) #15

Open
Tracked by #5
CrescentKohana opened this issue Apr 5, 2022 · 5 comments
Open
Tracked by #5

Create models for the database types (for goqu) #15

CrescentKohana opened this issue Apr 5, 2022 · 5 comments
Assignees

Comments

@CrescentKohana
Copy link
Member

CrescentKohana commented Apr 5, 2022

We could probably use the types Jet generated as a base: pkg/types/model.

@CrescentKohana CrescentKohana changed the title Create types for the database (for goqu) Create models for the database types (for goqu) Apr 6, 2022
@CrescentKohana CrescentKohana added the enhancement New feature or request label Apr 6, 2022
@CrescentKohana CrescentKohana added goqu-rework and removed enhancement New feature or request labels Apr 6, 2022
@CrescentKohana CrescentKohana self-assigned this Apr 7, 2022
@karmek-k
Copy link
Collaborator

Going to work on this right now.

@CrescentKohana
Copy link
Member Author

CrescentKohana commented Apr 12, 2022

Going to work on this right now.

Great! I have some preliminary stuff done in #25.

I ran into an issue with the Combined model and was not able get goqu to scan stuff correctly into this model:

type CombinedLibrary struct {
	Library
	Galleries []Gallery `db:"gallery"`
}

Expected:

[
  {
    "ID": 1,
    "Path": "test/",
    "Layout": "structured",
    "Galleries": [ <Gallery Object>, <Gallery Object>, ... ]
  },
  ...
]

Actual:

[
  {
    "ID": 1,
    "Path": "test/",
    "Layout": "structured",
    "Galleries": null
  },
  ...
]

@karmek-k
Copy link
Collaborator

karmek-k commented Apr 12, 2022

I've just added db tags to all models (https://github.com/karmek-k/server/commit/6d136735f8dab2d873e95d8c4b4179e5aea688c9).

Regarding the CombinedLibrary issue, how are you scanning data from the db? Are you using GetLibraries?

Btw, PostgreSQL supports arrays as a column type, but MySQL does not.

@CrescentKohana
Copy link
Member Author

Regarding the CombinedLibrary issue, how are you scanning data from the db? Are you using GetLibraries?

Yes, I tried to use GetLibraries with the ways listed on gogu docs.

Btw, PostgreSQL supports arrays as a column type, but MySQL does not.

Libraries are in one-to-many relationship with Galleries, and are being mapped/scanned to array here. No array columns used nor needed.

@CrescentKohana
Copy link
Member Author

CrescentKohana commented Apr 12, 2022

Actually I got it to work in really verbose way and there would probably be issues if two or more tables had columns named same.

Basically I had to make a new type which has all the columns on the same level, and scan them manually with Scanner() to a map which would then be converted into to struct we actually want.

There has to be a better way though. Even the documentation is saying this:

goqu also supports scanning into multiple structs. In the example below we define a Role and User struct that could both be used individually to scan into. However, you can also create a new struct that adds both structs as fields that can be populated in a single query.

type LibraryRow struct {
	ID              int32     `db:"id"`
	Path            string    `db:"path"`
	Layout          string    `db:"layout"`
	UUID            string    `db:"uuid"`
	LibraryID       int32     `db:"library_id"`
	ArchivePath     string    `db:"archive_path"`
	Title           string    `db:"title"`
	TitleNative     *string   `db:"title_native"`
	TitleTranslated *string   `db:"title_translated"`
	Category        *string   `db:"category"`
	Series          *string   `db:"series"`
	Released        *string   `db:"released"`
	Language        *string   `db:"language"`
	Translated      *bool     `db:"translated"`
	Nsfw            bool      `db:"nsfw"`
	Hidden          bool      `db:"hidden"`
	ImageCount      *int32    `db:"image_count"`
	ArchiveSize     *int32    `db:"archive_size"`
	ArchiveHash     *string   `db:"archive_hash"`
	Thumbnail       *string   `db:"thumbnail"`
	CreatedAt       time.Time `db:"created_at"`
	UpdatedAt       time.Time `db:"updated_at"`
}

func GetLibraries() ([]model.CombinedLibrary, error) {
	scanner, err := database.QB().
		From("library").
		Join(
			goqu.T("gallery"),
			goqu.On(goqu.I("gallery.library_id").Eq(goqu.I("library.id"))),
		).
		Executor().
		Scanner()

	if err != nil {
		log.Error(err)
		return nil, err
	}

	defer func(scanner exec.Scanner) {
		if err := scanner.Close();  err != nil {
			log.Error(err)
		}
	}(scanner)

	librariesMap := make(map[int32]model.CombinedLibrary)
	for scanner.Next() {
		lr := LibraryRow{}
		if err = scanner.ScanStruct(&lr); err != nil {
			log.Error(err)
			return nil, err
		}

		var gallery = model.Gallery{UUID: lr.UUID,
			Title:           lr.Title,
			TitleNative:     lr.TitleNative,
			TitleTranslated: lr.TitleTranslated,
			Category:        lr.Category,
			Series:          lr.Series,
			Released:        lr.Released,
			Language:        lr.Language,
			Translated:      lr.Translated,
			Nsfw:            lr.Nsfw,
			Hidden:          lr.Hidden,
			ImageCount:      lr.ImageCount,
			ArchiveSize:     lr.ArchiveSize,
			ArchiveHash:     lr.ArchiveHash,
			Thumbnail:       lr.Thumbnail,
			CreatedAt:       lr.CreatedAt,
			UpdatedAt:       lr.UpdatedAt,
		}

		value, ok := librariesMap[lr.ID]
		if ok {
			value.Galleries = append(value.Galleries, gallery)
			librariesMap[lr.ID] = value
		} else {
			librariesMap[lr.ID] = model.CombinedLibrary{
				Library: model.Library{
					ID:     lr.ID,
					Path:   lr.Path,
					Layout: lr.Layout,
				},
				Galleries: []model.Gallery{gallery},
			}
		}
	}

	librariesSlice := make([]model.CombinedLibrary, 0, len(librariesMap))
	for _, val := range librariesMap {
		librariesSlice = append(librariesSlice, val)
	}

	return librariesSlice, nil
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants