Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Add custom postgres installation support #797

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

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

robertjpayne
Copy link

@robertjpayne robertjpayne commented Jan 9, 2025

  • Add a "Custom…" option to the versions dropdown
  • When selecting "Custom…" prompt for selection of custom postgres installation

Code wise the AppKit bindings to versions needed to move to an object that could track a display name as well as additional info about the version once selected.

I'm not overly happy about the in-place modification after choosing a custom path but it works and keeps the change set smaller.

@robertjpayne
Copy link
Author

robertjpayne commented Jan 9, 2025

Screenshot 2025-01-09 at 10 44 42 PM

Here is a screenshot of this PR in action:

– It adds all the bundled built-in versions at the top
– It adds any custom versions used for already created servers (in dev mode it thinks versions in the /Applications/Postgres.app are custom)
– It adds a "Custom…" version option at the bottom to allow browsing for a custom Postgres installation.

The one thing this breaks is the var path is hard swapped every time you select a different version instead of trying to just update the var-\(version) portion as custom installations wont have a numerical version available.

@jakob
Copy link
Member

jakob commented Jan 10, 2025

I'm not a huge fan of this implementation. It mixes paths and display names in the menu.

Maybe we should have a text field labelled "Binaries" under the popup, wich shows the path. If you select a bundled version it is disabled (informative only), if you select "custom" it becomes editable.

* Restart from base
* Add a "Custom…" option to bottom of available binaries
* Add "Binaries" text field which shows the binPath of selected version and is only enabled/editable if "Custom…" is selected
* Update launchers to include a LC_ALL environment variable as many custom installs will have `--enable-nls` installed
@robertjpayne robertjpayne force-pushed the feature/custom-server-binary-path branch from 11cdda1 to 9eef7aa Compare January 10, 2025 09:33
@robertjpayne
Copy link
Author

robertjpayne commented Jan 10, 2025

@jakob That's a good idea and makes the implementation much cleaner. I've force pushed over the top with these changes. Attached some screenshots.

Only other thing is that postgres requires a LC_ALL environment variable if it's been compiled with --enable-nls. I'm going to go on a stretch and assume because the bundled versions are not using that flag they are set to en_US by default and it should do no harm to launch with LC_ALL added?

Screenshot 2025-01-10 at 10 33 54 PM Screenshot 2025-01-10 at 10 34 11 PM

@jakob
Copy link
Member

jakob commented Jan 10, 2025

Only other thing is that postgres requires a LC_ALL environment variable if it's been compiled with --enable-nls.

Oh, that is annoying. I wonder if we can find a start command that works for all PostgreSQL versions.

The next issue is probably the initdb command. But people can just use initdb from the command line instead.

Another potential gotcha is that Postgres.app always runs PostgreSQL using the current user. I think this matches Homebrew, but EnterpriseDB uses a separate user account. So if people try to use Postgres.app to control the EnterpriseDB server, that might lead to unexpected results.

I don't think any of these are deal breakers, but we should think about these issues before merging this feature.

@jakob
Copy link
Member

jakob commented Jan 10, 2025

Another potential issue that I see is that the Homebrew path seems to contain the minor version of PostgreSQL. So after an update the binaries path would need to be changed? Right now there is no way to change the binary path in the UI, you would need to remove and re-add the server to change it.

Another issue: Postgres.app has some logic to fix incorrect binary paths that can happen when you move the app (eg. if you create a server when the app is launched from the disk image). We need to make sure that logic doesn't attempt to "fix" custom paths.

@robertjpayne
Copy link
Author

@jakob I think the feature should be aimed at "use the binaries at Y" but let "Postgres.app" manage it like it would manage it's bundled in versions.

My particular use case is just using Homebrew binaries to get access to pgxnclient and custom extensions.

If we wanted to go beyond this would probably need to allow configuring servers in preferences with a full list of options like binary path, users, environment flags, arguments etc…

@robertjpayne
Copy link
Author

Hmm yea those are some more interesting issues I didn't consider. Particularly I'm not sure what Homebrew does on minor version upgrade (and it doesn't appear easy to simulate that!).

I guess tricky because there is no way to "remedy" it by editing the added server, you have to delete and re-create.

@tbussmann
Copy link
Member

tbussmann commented Jan 10, 2025

This is what I meant with discussion before implementation :)

There are several issues that need to be ruled out to decide if and how we can deal with external binaries, not just the layout of the user interface. Some that come to mind:

  • What about the auth_permission_dialog extension? external binaries are unlikely to have this installed. Disabling it for custom binaries only would make the generic switch in the preferences a bit confusing.
  • What commands to use to start, stop and especially initialise a 'foreign' cluster? I'm not sure the existing defaults of Postgres.app work well for people who have a need for an advanced feature like the one we're designing here.
  • How do I deal with externally started servers? There is a good chance that they are not running on the port configured within Postgres.App. Postgres.App passes the port configured in the UI when the server is started, while others are likely to modify the postgresql.conf file.
  • There is no guarantee that we will be able to connect to an external server, as we don't know the users and authentication configured. Fortunately, we have already implemented some heuristics and a graceful state if the connection is not possible.
  • Things like the need for certain environment variables that need to be present when running an NLS cluster.
  • How do we deal with updates to the 'foreign' binaries?
  • We need to make sure that this does not conflict with the logic we have to deal with servers configured with binaries of Postgres.App in different locations / copies and running multiple instances of the app.
  • Support for custom binaries adds complexity to planned features such as automatic extension updates, major version upgrades, externally loadable Python and extensions, backup and restore.
  • There are certainly more details to consider.

I'm not against the idea, it's something that advanced users could certainly benefit from. But it is difficult to find a way that both satisfies these needs and maintains the simplicity of Postgres.App for the average user. We usually try hard to hide complexity.

@tbussmann
Copy link
Member

My particular use case is just using Homebrew binaries to get access to pgxnclient and custom extensions.

If this is the main motivation, maybe we should try to tackle this directly? Custom extensions can be built against our binaries and pgxnclient can also be installed on top of Postgres.App. I have been thinking about including it in the bundle for some time. There are still open issues with updates and code signing. Recent discussions about the future of the extension ecosystem, portability and a PGXNv2 sound promising.

@anthonydb
Copy link

anthonydb commented Jan 10, 2025

Hi, folks, I'm author of a book on SQL who also teaches a lot of beginners how to get started with PostgreSQL. In my book, for Mac users, I recommend PostgresApp. I've been following this discussion and think I have a sense of what you're trying to do. One small thought:

One of the best things about PostgresApp is that, like a lot of things in the macOS world, it "just works" and is so simple to get going. I hope that even if you implement these changes, you'll keep the current setup experience as streamlined as it is.

Thanks for offering such a great product. IMO the best way to experience PostgreSQL setup!

@jakob
Copy link
Member

jakob commented Jan 13, 2025

I am pretty sure we could find reasonable answers for all the questions that @tbussmann brought up, but we really have to figure out if this use case is important enough.

I use Postgres.app with custom binaries myself, so I can see the appeal of this feature. To use custom binaries, I just manually change the user defaults with Prefs Editor. Maybe we should just add a link to that app in the Postgres.app documentation?

Copy link
Member

@jakob jakob left a comment

Choose a reason for hiding this comment

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

I reviewed the code changes. (This does not mean we'll merge it, whether this feature should be merged is a separate discussion)

@@ -60,7 +79,16 @@ class AddServerViewController: NSViewController, MainWindowModelConsumer {

@IBAction func createServer(_ sender: AnyObject?) {
guard self.view.window!.makeFirstResponder(nil) else { NSSound.beep(); return }
guard availableBinaries.indices.contains(selectedVersionIdx) else {

let isValid = if availableBinaries.indices.contains(selectedVersionIdx) {
Copy link
Member

Choose a reason for hiding this comment

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

This check isn't necessary anymore, since the array is no longer accessed in this function.


let isValid = if availableBinaries.indices.contains(selectedVersionIdx) {
true
} else if FileManager().fileExists(atPath: binPath.appending("/postgres")) {
Copy link
Member

Choose a reason for hiding this comment

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

This check is a good idea, but we should probably present an error message instead of beeping.

Previously, the only way to trigger this error was if you made a debug build without binaries, and the beep was to avoid a crash. Now the error is much more likely to occur if you mistype the binary path, so we should let the user know that the problem is that no binaries were found at the path.

varPath = FileManager().applicationSupportDirectoryPath().appending("/var-\(availableBinaries[selectedVersionIdx].version)")
} else {
binPath = customBinPath
Copy link
Member

Choose a reason for hiding this comment

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

I don't think setting this to the home directory makes sense. I'd just leave it at the last value instead

@@ -13,17 +13,29 @@ class AddServerViewController: NSViewController, MainWindowModelConsumer {
@objc dynamic var mainWindowModel: MainWindowModel!
@objc dynamic var name: String = "New Server"
@objc dynamic var port: UInt = 5432
@objc dynamic var binPath: String = ""
@objc dynamic var binPathEditable: Bool = false
Copy link
Member

Choose a reason for hiding this comment

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

An alternative might be to hide the "Binaries" field instead of disabling it when a built-in version is selected. That would reduce the complexity of the form for 99% of users who don't care where their binaries are.

@tbussmann
Copy link
Member

Just to add another perspective to the discussion: There seems to be an application specifically designed for managing 'foreign' PostgreSQL binaries on macOS: PostgresPrefs It hasn't received a lot of maintenance recently but maybe worth a look?

@jakob jakob mentioned this pull request Mar 7, 2025
10 tasks
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.

4 participants