{"id":20243448,"url":"https://github.com/lpil/pog","last_synced_at":"2025-04-05T01:04:03.249Z","repository":{"id":62429852,"uuid":"222302603","full_name":"lpil/pog","owner":"lpil","description":"🐘 A PostgreSQL database client for Gleam, based on PGO","archived":false,"fork":false,"pushed_at":"2025-01-16T19:00:12.000Z","size":137,"stargazers_count":181,"open_issues_count":11,"forks_count":16,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-04-02T10:43:36.207Z","etag":null,"topics":["erlang","gleam","postgresql","postgresql-client"],"latest_commit_sha":null,"homepage":"https://hexdocs.pm/pog","language":"Gleam","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lpil.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2019-11-17T19:46:29.000Z","updated_at":"2025-03-31T11:48:13.000Z","dependencies_parsed_at":"2023-11-07T02:23:15.258Z","dependency_job_id":"22d75729-fc34-49d8-a80d-1b832e0dbca0","html_url":"https://github.com/lpil/pog","commit_stats":null,"previous_names":["lpil/pgo","gleam-experiments/pgo","lpil/pog"],"tags_count":25,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpil%2Fpog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpil%2Fpog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpil%2Fpog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lpil%2Fpog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lpil","download_url":"https://codeload.github.com/lpil/pog/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247271515,"owners_count":20911587,"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":["erlang","gleam","postgresql","postgresql-client"],"created_at":"2024-11-14T09:01:49.198Z","updated_at":"2025-04-05T01:04:03.227Z","avatar_url":"https://github.com/lpil.png","language":"Gleam","funding_links":[],"categories":["Packages","Gleam"],"sub_categories":["Databases"],"readme":"# Pog\n\nA PostgreSQL database client for Gleam, based on [PGO][erlang-pgo].\n\n[erlang-pgo]: https://github.com/erleans/pgo\n\n```gleam\nimport pog\nimport gleam/dynamic/decode\nimport gleeunit/should\n\npub fn main() {\n  // Start a database connection pool.\n  // Typically you will want to create one pool for use in your program\n  let db =\n    pog.default_config()\n    |\u003e pog.host(\"localhost\")\n    |\u003e pog.database(\"my_database\")\n    |\u003e pog.pool_size(15)\n    |\u003e pog.connect\n\n  // An SQL statement to run. It takes one int as a parameter\n  let sql_query = \"\n  select\n    name, age, colour, friends\n  from\n    cats\n  where\n    id = $1\"\n\n  // This is the decoder for the value returned by the query\n  let row_decoder = {\n    use name \u003c- decode.field(0, decode.string)\n    use age \u003c- decode.field(1, decode.int)\n    use colour \u003c- decode.field(2, decode.string)\n    use friends \u003c- decode.field(3, decode.list(decode.string))\n    decode.success(#(name, age, colour, friends))\n  }\n\n  // Run the query against the PostgreSQL database\n  // The int `1` is given as a parameter\n  let assert Ok(response) =\n    pog.query(sql_query)\n    |\u003e pog.parameter(pog.int(1))\n    |\u003e pog.returning(row_decoder)\n    |\u003e pog.execute(db)\n\n  // And then do something with the returned results\n  response.count\n  |\u003e should.equal(2)\n  response.rows\n  |\u003e should.equal([\n    #(\"Nubi\", 3, \"black\", [\"Al\", \"Cutlass\"]),\n  ])\n}\n```\n\n## Installation\n\n```sh\ngleam add pog\n```\n\n## Support of connection URI\n\nConfiguring a Postgres connection is done by using `Config` type in `pog`.\nTo facilitate connection, and to provide easy integration with the rest of the\nPostgres ecosystem, `pog` provides handling of\n[connection URI as defined by Postgres](https://www.postgresql.org/docs/current/libpq-connect.html#LIBPQ-CONNSTRING-URIS).\nShape of connection URI is `postgresql://[username:password@][host:port][/dbname][?query]`.\nCall `pog.url_config` with your connection URI, and in case it's correct\nagainst the Postgres standard, your `Config` will be automatically generated!\n\nHere's an example, using [`envoy`](https://github.com/lpil/envoy) to read the\nconnection URI from the environment.\n\n```gleam\nimport envoy\nimport pog\n\n/// Read the DATABASE_URL environment variable.\n/// Generate the pog.Config from that database URL.\n/// Finally, connect to database.\npub fn read_connection_uri() -\u003e Result(pog.Connection, Nil) {\n  use database_url \u003c- result.try(envoy.get(\"DATABASE_URL\"))\n  use config \u003c- result.try(pog.url_config(database_url))\n  Ok(pog.connect(config))\n}\n```\n\n## About JSON\n\nIn Postgres, you can define a type `json` or `jsonb`. Such a type can be query\nin SQL, but Postgres returns it a simple string, and accepts it as a simple string!\nWhen writing or reading a JSON, you can simply use\n`pog.text(json.to_string(my_json))` and `decode.string` to respectively write\nand read them!\n\n## Timeout\n\nBy default, every pog query has a 5 seconds timeout, and every query taking more\nthan 5 seconds will automatically be aborted. That behaviour can be changed\nthrough the usage of `default_timeout` or `timeout`. `default_timeout` should be\nused on `Config`, and defines the timeout that will be used for every query\nusing that connection, while `timeout` handles timeout query by query. If you have\none query taking more time than your default timeout to complete, you can override\nthat behaviour specifically for that one.\n\n## Rows as maps\n\nBy default, `pgo` will return every selected value from your query as a tuple.\nIn case you want a different output, you can activate `rows_as_maps` in `Config`.\nOnce activated, every returned rows will take the form of a `Dict`.\n\n## Atom generation\n\nCreating a connection pool with the `pog.connect` function dynamically generates\nan Erlang atom. Atoms are not garbage collected and only a certain number of\nthem can exist in an Erlang VM instance, and hitting this limit will result in\nthe VM crashing. Due to this limitation you should not dynamically open new\nconnection pools, instead create the pools you need when your application starts\nand reuse them throughout the lifetime of your program.\n\n## SSL\n\nAs for the rest of the web, you should try to use SSL connections with any\nPostgres database. Most of the time, managed instances of Postgres will even\nrequire the library to use SSL connections.\n\n`pog` supports SSL connections out-of-the-box, and stick with current Postgres\nconventions to ensure portability of Postgres configuration across ecosystems.\n\n### Postgres SSL conventions\n\nPostgres supports 3 main modes of SSL: SSL disabled, SSL enabled, and SSL\nenabled with active security measures (i.e. checking of system-wide CA\ncertificates). Those modes can be found directly in `psql` client, but also in\nmost Postgres clients in different languages.\n\n\u003e [!NOTE]\n\u003e It could seems weird to have three different modes of SSL, while we usually\n\u003e think of SSL a switch: it's turned off, or turned on. When SSL is off, clients\n\u003e will simply ignore SSL certificates, and proceed with the connection in an\n\u003e unsecured way (as long as the server agrees with unsecure connection). When\n\u003e SSL is on, clients will read SSL certificates, and check that the connection\n\u003e uses a correct SSL certificates. It will read global Certificates Authority\n\u003e and will check that your connection is secured with one of those certificates.\n\u003e If we take the browser analogy, SSL turned off is when you're browsing an HTTP\n\u003e website, while SSL turned on is when you're browsing an HTTPS website.\n\u003e But there's a hidden mode of SSL, where SSL is enabled, but not actively\n\u003e checking that the connection is valid. In simple terms, it means the connection\n\u003e can be compromised, and the client will not check for Certificates Authority.\n\u003e You'll use the SSL connection thinking you are secured, but some potential\n\u003e attackers can target you. Continuing the browser analogy, it's when you are\n\u003e on a website secured by HTTPS, but the browser will show a warning page saying\n\u003e \"Impossible to check the validity of certificate.\", and you have to click on\n\u003e \"Continue anyway\". When you click on that button, you're using that third mode\n\u003e of SSL: it's secured, but you can not be certain that the connection is legit!\n\nIn Postgres, conventions used, including in connection URI are as follow:\n\n- Flag used to indicate SSL state is named `sslmode`.\n- `disable` disables SSL connection.\n- `require` enables SSL connection, but does not check CA certificates.\n- `verify-ca` or `verify-full` enables SSL connection, and check for CA certificates.\n\n### `pog` SSL usage\n\nIn `pog`, setting up an SSL connection simply ask you to indicate the proper flag\nin `pog.Config`. The different options are `SslDisabled`, `SslUnverified` \u0026\n`SslVerified`. Because of the nature of the 3 modes of SSL, and because talking\nto your database should be highly secured to protect you against man-in-the-middle\nattacks, you should always try to use the most secured setting.\n\n```gleam\nimport pog\n\npub fn connect() {\n  pog.default_config()\n  |\u003e pog.ssl(pog.SslVerified)\n  |\u003e pog.connect\n}\n```\n\n### Need some help?\n\nYou tried to setup a secured connection, but it does not work? Your container\nis not able to find the correct CA certificate?\n[Take a look at Solving SSL issues](https://hexdocs.pm/pog/docs/solving-ssl-issues.html)\n\n## History\n\nPreviously this library was named `gleam_pgo`. This old name is deprecated and\nall future development and support will happen here.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flpil%2Fpog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flpil%2Fpog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flpil%2Fpog/lists"}