{"id":13700952,"url":"https://github.com/oelmekki/pgrebase","last_synced_at":"2025-04-07T06:06:47.613Z","repository":{"id":66839699,"uuid":"73548275","full_name":"oelmekki/pgrebase","owner":"oelmekki","description":"Easy postgres codebase injection - aka postgres non data live reload","archived":false,"fork":false,"pushed_at":"2023-07-08T09:02:12.000Z","size":9569,"stargazers_count":337,"open_issues_count":2,"forks_count":14,"subscribers_count":10,"default_branch":"master","last_synced_at":"2025-03-31T04:07:02.232Z","etag":null,"topics":["go","golang","plpgsql","postgres","postgresql"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/oelmekki.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-11-12T11:18:44.000Z","updated_at":"2024-12-17T10:32:27.000Z","dependencies_parsed_at":"2024-06-20T08:19:06.919Z","dependency_job_id":"ca4b05ad-c97a-4e7d-ad9e-97b6712e568c","html_url":"https://github.com/oelmekki/pgrebase","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oelmekki%2Fpgrebase","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oelmekki%2Fpgrebase/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oelmekki%2Fpgrebase/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/oelmekki%2Fpgrebase/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/oelmekki","download_url":"https://codeload.github.com/oelmekki/pgrebase/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247601447,"owners_count":20964864,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","golang","plpgsql","postgres","postgresql"],"created_at":"2024-08-02T20:01:10.847Z","updated_at":"2025-04-07T06:06:47.590Z","avatar_url":"https://github.com/oelmekki.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"# PgRebase\n\n\u003e Note to Github user: development is now happening [on Gitlab](https://gitlab.com/oelmekki/pgrebase),\n\u003e Github's repository is just a mirror. Please open any issue on Gitlab\n\u003e rather than Github.\n\nPgRebase is a tool that allows you to easily handle your postgres codebase for\nfunctions, triggers and views.\n\n## Why\n\nIf you started outsourcing data manipulation to your database through\npostgresql cool features, you probably realized this is painful. Postgresql's\nfunctions, triggers and views are not your usual codebase, they\nlive in postgres, and you often have to drop them if you want to edit them, eg\nwhen you change a function signature. You could edit them directly in psql, but\nthen it's migrating servers / other devs installation that becomes difficult.\n\nThe classic tool for this is the migration software, asking you to manage\nmigration files. This is great for handling tables, not so great to make\nfrequent changes to your functions. Can we do better?\n\n\n## What\n\nPgRebase allows you to manage your functions/triggers/views as plain files in\nfilesystem. You put them in a `sql/` directory, one file per\nfunction/trigger/type/view.\n\n```\n$ tree sql/\nsql/\n├── functions/\n│   └── assign_user_to_team.sql\n├── triggers/\n│   └── user_updated_at.sql\n└── views/\n    └── user_json.sql\n```\n\nNo need to add drop statement in those files, PgRebase will take care of it.\n\nIn watch mode (useful for development), just save your file, pgrebase will\nupdate your database. In normal mode (useful for deployment), pgrebase will\nrecreate all functions/triggers/views found in your filesystem directory.\n\nYou can now work with postgres codebase live reload, then call pgrebase just\nafter your migration task in your deployment pipeline.\n\n\n## Install\n\n```\ngo get gitlab.com/oelmekki/pgrebase\n```\n\nBinary will be in `$GO_PATH/bin/pgrebase`. This is a static binary, so it's\nsafe to copy it in your project (providing any system calling it is from the\nsame architecture).\n\n\n## Usage\n\n```\n$ export DATABASE_URL=postgres://user:pass@host/db\n\n$ ./pgrebase sql/\nLoaded 10 functions\nLoaded 25 views\nLoaded 5 triggers - 1 trigger with error\n  error while loading sql/triggers/user_updated_at.sql\n  column users.updated_at does not exist\n\n\n$ ./pgrebase -w sql/\nLoaded 10 functions\nLoaded 25 views\nLoaded 6 triggers\nWatching filesystem for changes...\nFS changed. Building.\n```\n\nWhen working in development environment, you'll probably want to use watch mode\n(`-w`) to have your changes automatically loaded.\n\nFor deployment, add `pgrebase` to your repos and call it after your usual\nmigrations step:\n\n```\nDATABASE_URL=your_config ./pgrebase ./sql\n```\n\nPgRebase can also be used as a library rather than a command tool. See the `core`\nsubpackage.\n\n## Handling dependencies\n\nYou can specify dependencies for files using require statement, provided those\nfiles are of the same kind. That is, function files can specify dependencies on\nother function files, type files can define dependencies on other type files,\netc.\n\nHere is an example about how to do it. Let's say your `sql/functions/foo.sql`\nfiles depends on `sql/functions/whatever/bar.sql`:\n\n```\n$ cat sql/functions/foo.sql\n-- require \"whatever/bar.sql\"\nCREATE FUNCTION foo()\n[...]\n```\n\nFilenames are always relative to your target directory (`sql/` in that\nexample), and within in, to the code kind (`functions/` here).\n\nDo not try to do funky things like adding `./` or `../`, this is no path\nresolution, it just tries to match filenames.\n\nYou can add multiple require lines:\n\n```\n-- require \"common.sql\"\n-- require \"hello/world.sql\"\n-- require \"whatever/bar.sql\"\nCREATE FUNCTION foo()\n[...]\n```\n\nThere is no advanced debugging for circular dependencies for now, so be sure\nnot to get too wild, here (or else, you will have a \"maybe there's circular\ndependencies?\" message and you will have to figure it out for yourself).\n\n\n## Caveats\n\n* pgrebase doesn't keep any state about your codebase and does not delete what\n  is in your database and is not in your codebase. This means that if you want\n  to remove a trigger/type/view/function, deleting its file is not enough. You\n  have to use your usual way to migrate db and remove it.\n\n* trigger files should contain both trigger creation and the function it uses.\n  This is to avoid dropping function still used by trigger (if processing\n  functions first) or create trigger before its function (if triggers are\n  processed first)\n\n* files should only contain the definition of the view/function/type/trigger\n  they're named after (with the exception of trigger files declaring the\n  function they use). Hazardous results will ensue if it's not the case: only\n  the first definition will be dropped, but the whole file will be loaded in\n  pg.\n\n* pgrebase single top concern is to not delete any data. This means that no\n  DROP will CASCADE. This means that if your database structure depends on\n  anything defined in pgrebase codebase, it will fail to reload it when it\n  implies dropping it (that is, most of the time). In other terms, do not\n  use pgrebase managed functions as default value for your tables' fields.\n\n## Any issue?\n\nPgrebase is a fairly recent project. I already use it on production and it works\nfine for me, but given I'm probably its only user for now, it's probably biased\ntoward how I write my sql code. If you find any problem while parsing your sql\ncode, please [let me know](https://gitlab.com/oelmekki/pgrebase/-/issues)!\n\n\n## Credits\n\nPgRebase was born after discussing with Derek Sivers about moving business logic\nto the database. Make sure to read [his research](https://sivers.org/pg), it's\nawesome!\n\n## License\n\n\u003cp xmlns:dct=\"http://purl.org/dc/terms/\"\u003e\n  \u003ca rel=\"license\"\n     href=\"http://creativecommons.org/publicdomain/zero/1.0/\"\u003e\n    \u003cimg src=\"http://i.creativecommons.org/p/zero/1.0/88x31.png\" style=\"border-style: none;\" alt=\"CC0\" /\u003e\n  \u003c/a\u003e\n  \u003cbr /\u003e\n  To the extent possible under law,\n  \u003ca rel=\"dct:publisher\"\n     href=\"https://gitlab.com/oelmekki/pgrebase\"\u003e\n    \u003cspan property=\"dct:title\"\u003eOlivier El Mekki\u003c/span\u003e\u003c/a\u003e\n  has waived all copyright and related or neighboring rights to\n  \u003cspan property=\"dct:title\"\u003ePgRebase\u003c/span\u003e.\n\u003c/p\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foelmekki%2Fpgrebase","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foelmekki%2Fpgrebase","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foelmekki%2Fpgrebase/lists"}