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

Postgres support #5355

Draft
wants to merge 63 commits into
base: develop
Choose a base branch
from

Conversation

NodudeWasTaken
Copy link
Contributor

@NodudeWasTaken NodudeWasTaken commented Oct 8, 2024

Hello, this is an attempt at implementing postgres support.
If you want to test this branch, you can add these changes to your config.yml:

database: postgresql://username:password@localhost/dbname

There are alot of changes, highlights:

  • Seperate migrations for postgresql
  • Abstractions around the database class
  • Several SQL changes, particularly no lastinsertid and removal of the distinctids selector
    lastInsertId is a SQLite specific feature, other databases need you to specify "returning id". Which our version of SQLite supports, but goqu doesnt mark it as supported, so we create our own custom definition.
    Call regexp as a function, as postgresql doesnt support named operators.
  • Blob changes to make it cross-db compatible

Some particularly egregious changes or missing things are are:

  • Backups for postgresql
    We create new "databases" for this, test this functionality.
  • No migration script
    There is no script for migrating from sqlite to postgresql.
  • Lack of testing
    We have PGSQL_TEST string which should be able to test postgresql,
    PGSQL_TEST='postgresql://username:password@localhost/dbname_for_testing' go test -tags "sqlite_stat4 sqlite_math_functions integration" ./...
    There are probably bugs i haven't found, but it works for both sqlite and postgresql in my testing.
  • SQL Definitions for postgresql
    In particular fingerprints where changed from blob to text, since its mostly strings or numbers, and you cannot insert numbers into bytea (postgresql blob), where you could with text.
    I dont know that timestamp (postgresql) follows the same rules as datetime (sqlite).
    Also others.
  • Rebind
    For supporting postgresql we use rebind to convert unnamed parameters (the ?), to named ($1 etc.).
    This should theoretically always work, but is ugly.
  • "Missing" SQL functionality
    While i have create the extension, it does not automatically install, and i dont know that its cross-compatible across postgresql versions.

To look at (help me):

  • Number of concurrent reader/writers
  • Warn if extension missing
  • UI setup for postgresql
  • Testing for pgsql
  • Backup functionality
  • Code cleanup, some of it is ugly

Postgresql C/CGo extension to support missing functionality (basename, phash_distance, regexp):
https://github.com/NodudeWasTaken/stash_pge

You can use dbeaver for testing the database, its nice for browsing various databases like sqlite and postgresql.
To support disable foreign keys we do (if anybody knows a better way, let me know):
"SET session_replication_role = replica;"
which requires extra postgres user permissions, just a note.

This is mainly a request for comments, or help, mainly help finishing this.

Fixes #3892

Comment on lines 49 to 62
if disableForeignKeys {
_, err = conn.Exec("SET session_replication_role = replica;")

if err != nil {
return nil, fmt.Errorf("conn.Exec(): %w", err)
}
}
if !writable {
_, err = conn.Exec("SET default_transaction_read_only = ON;")

if err != nil {
return nil, fmt.Errorf("conn.Exec(): %w", err)
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would suggest not supporting "disable foreign key" and "read-only" in Postgres in the application layer.

They exist for SQLite because of limitations in the DB, such as some messiness with foreign keys. For connecting to Postgres as read-only, I'd strongly recommend that admins create a user with read-only permissions to the DB, rather than doing that in Stash

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that this is ugly and should be removed.
But that would necessitate adding another connection string.
Im gonna have to think about it.

Or simply add "database_string_ro" 🤣

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you absolutely need to tell Stash to make this RO, you could add a query stirng parameter to the connection string.

Something like ?readonly=1 to the URL... and then we remove it

Copy link
Contributor

@its-josh4 its-josh4 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some initial review/feedback from me

pkg/sqlite/repository.go Outdated Show resolved Hide resolved
pkg/sqlite/repository.go Outdated Show resolved Hide resolved
pkg/sqlite/repository.go Outdated Show resolved Hide resolved
pkg/sqlite/sql.go Show resolved Hide resolved
pkg/sqlite/scene_filter.go Outdated Show resolved Hide resolved
pkg/sqlite/migrationsPostgres/1_initial.up.sql Outdated Show resolved Hide resolved
pkg/sqlite/migrationsPostgres/1_initial.up.sql Outdated Show resolved Hide resolved
pkg/sqlite/migrationsPostgres/1_initial.up.sql Outdated Show resolved Hide resolved
pkg/sqlite/migrationsPostgres/1_initial.up.sql Outdated Show resolved Hide resolved
Comment on lines +280 to +281
performer_id integer,
scene_id integer,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should these be non-nullable?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ehh, they are written like that in the original schema, and they are foreign keys that reference other tables.
So i think its fine

internal/manager/init.go Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Feature] Support Postgres as DB backend
2 participants