{"id":40990983,"url":"https://github.com/rom8726/pgfixtures","last_synced_at":"2026-01-22T07:40:02.880Z","repository":{"id":293606293,"uuid":"983069540","full_name":"rom8726/pgfixtures","owner":"rom8726","description":"A GoLang library for applying test fixtures to a PostgreSQL and MySQL databases.","archived":false,"fork":false,"pushed_at":"2025-06-22T16:14:31.000Z","size":51,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-22T17:25:55.106Z","etag":null,"topics":["fixtures","golang","postgresql","testing"],"latest_commit_sha":null,"homepage":"https://rom8726.github.io/pgfixtures.html","language":"Go","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/rom8726.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,"zenodo":null}},"created_at":"2025-05-13T20:39:17.000Z","updated_at":"2025-06-22T16:14:34.000Z","dependencies_parsed_at":null,"dependency_job_id":"b1010d99-0aac-4a29-ac41-45f8fcda0cea","html_url":"https://github.com/rom8726/pgfixtures","commit_stats":null,"previous_names":["rom8726/pgfixtures"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/rom8726/pgfixtures","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rom8726%2Fpgfixtures","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rom8726%2Fpgfixtures/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rom8726%2Fpgfixtures/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rom8726%2Fpgfixtures/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rom8726","download_url":"https://codeload.github.com/rom8726/pgfixtures/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rom8726%2Fpgfixtures/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28658109,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-22T01:17:37.254Z","status":"online","status_checked_at":"2026-01-22T02:00:07.137Z","response_time":144,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["fixtures","golang","postgresql","testing"],"created_at":"2026-01-22T07:40:01.938Z","updated_at":"2026-01-22T07:40:02.874Z","avatar_url":"https://github.com/rom8726.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# pgfixtures\n\n[![Go Reference](https://pkg.go.dev/badge/github.com/rom8726/pgfixtures.svg)](https://pkg.go.dev/github.com/rom8726/pgfixtures)\n[![Go Report Card](https://goreportcard.com/badge/github.com/rom8726/pgfixtures)](https://goreportcard.com/report/github.com/rom8726/pgfixtures)\n[![Coverage Status](https://coveralls.io/repos/github/rom8726/pgfixtures/badge.svg?branch=main)](https://coveralls.io/github/rom8726/pgfixtures?branch=main)\n[![libs.tech recommends](https://libs.tech/project/983069540/badge.svg)](https://libs.tech/project/983069540/pgfixtures)\n\n[![boosty-cozy](https://gideonwhite1029.github.io/badges/cozy-boosty_vector.svg)](https://boosty.to/dev-tools-hacker)\n\nA Go library and CLI tool for loading fixtures into PostgreSQL and MySQL databases with dynamic value support.\n\n`pgfixtures` is a library and CLI tool for loading test data (fixtures) into databases.\nIt's useful for setting up test environments in integration tests.\n\n## Features\n\n- Load data from YAML files\n- Support for both PostgreSQL and MySQL databases\n- Support dynamic values through `$eval()` for executing SQL queries\n- Automatic table cleanup before loading (optional)\n- Reset sequences after loading (optional)\n- Dry-run mode to preview planned changes\n- Support for foreign keys and proper loading order\n- **Fixture templates and inheritance via `include` with merge by `id`**\n\n⚠️ **NOTE: Please, point table schema for each table in YAML fixture for correct toposort (for example, public.test)**\n\n## Installation\n\n```bash\ngo get github.com/rom8726/pgfixtures\n```\n\n## Usage\n\n### As a CLI Tool\n```bash\npgfixtures load \\\n  --file fixtures.yml \\\n  --db \"postgres://user:password@localhost:5432/dbname?sslmode=disable\" \\\n  --db-type postgres \\\n  --truncate \\\n  --reset-seq\n```\n\nFor MySQL:\n```bash\npgfixtures load \\\n  --file fixtures.yml \\\n  --db \"user:password@tcp(localhost:3306)/dbname\" \\\n  --db-type mysql \\\n  --truncate \\\n  --reset-seq\n```\n\nFlags:\n- `--file, -f`: path to YAML fixtures file (default: fixtures.yml)\n- `--db`: database connection string (required)\n- `--db-type`: database type (postgres or mysql, default: postgres)\n- `--truncate`: clean tables before loading (default: true)\n- `--reset-seq`: reset sequences after loading (default: true)\n- `--dry-run`: show planned changes without executing them\n\n### As a Library\n```go\nimport (\n    \"github.com/rom8726/pgfixtures\"\n)\n\n// For PostgreSQL\npgCfg := \u0026pgfixtures.Config{\n    FilePath:     \"fixtures.yml\",\n    ConnStr:      \"postgres://user:password@localhost:5432/dbname?sslmode=disable\",\n    DatabaseType: db.PostgreSQL, // Default if not specified\n    Truncate:     true,\n    ResetSeq:     true,\n    DryRun:       false,\n}\n\nerr := pgfixtures.Load(context.Background(), pgCfg)\n\n// For MySQL\nmyCfg := \u0026pgfixtures.Config{\n    FilePath:     \"fixtures.yml\",\n    ConnStr:      \"user:password@tcp(localhost:3306)/dbname\",\n    DatabaseType: db.MySQL,\n    Truncate:     true,\n    ResetSeq:     true,\n    DryRun:       false,\n}\n\nerr = pgfixtures.Load(context.Background(), myCfg)\n```\n\n## Fixture Format\n\nFixtures are described in YAML format where top-level keys are table names:\n```yaml\npublic.users:\n  - id: 1\n    name: \"John Doe\"\n    created_at: $eval(SELECT NOW())\n  - id: 2\n    name: \"Jane Doe\"\n    created_at: $eval(SELECT NOW() - INTERVAL '1 day')\n\npublic.orders:\n  - id: 1\n    user_id: 1\n    total: 100.50\n```\n\n### Dynamic Values\n\nUse `$eval()` construction for generating dynamic values. You can write SQL queries inside:\n```yaml\npublic.users:\n  - id: 1\n    created_at: $eval(SELECT NOW())\n    updated_at: $eval(SELECT NOW() + INTERVAL '1 hour')\n    random_num: $eval(SELECT floor(random() * 100))\n```\n\n### Fixture Templates, Inheritance and Merge by id\n\nYou can split your fixtures into reusable templates and include them in your main fixture file using the `include` key. You can include one or multiple files:\n\n```yaml\n# base.yml\npublic.users:\n  - id: 1\n    name: \"Base User\"\n  - id: 2\n    name: \"Template User\"\n\n# addon.yml\npublic.users:\n  - id: 2\n    name: \"Addon User\"\n  - id: 3\n    name: \"Addon User 2\"\n\n# main.yml\ninclude:\n  - base.yml\n  - addon.yml\npublic.users:\n  - id: 2\n    name: \"Overridden User\"\n  - id: 4\n    name: \"Main User\"\n```\n\n**How it works:**\n- All included files are merged in order.\n- For each table, rows are merged by `id` (if present): if the same `id` appears in several files, the last one wins (the main file overrides included templates).\n- As a result, in the example above, the final `public.users` will contain:\n  - id: 1, name: \"Base User\"\n  - id: 2, name: \"Overridden User\"   # from main.yml, overrides all previous\n  - id: 3, name: \"Addon User 2\"\n  - id: 4, name: \"Main User\"\n\nIf a row does not have an `id` field, it is simply appended.\n\n### Row Templates and Inheritance (`templates` / `extends`)\n\nYou can define reusable row templates and inherit from them using the `templates` section and the `extends` key. This allows you to describe common fields once and inherit them in other rows, overriding only the necessary values.\n\n**Example:**\n```yaml\npublic.users:\n  templates:\n    - table: public.users\n      name: base\n      fields:\n        is_admin: false\n        super: false\n    - table: public.users\n      name: admin\n      extends: base\n      fields:\n        is_admin: true\n    - table: public.users\n      name: superadmin\n      extends: admin\n      fields:\n        super: true\n  # regular rows\n  - id: 1\n    name: \"Base User\"\n    email: \"user1@example.com\"\n    extends: base\n  - id: 2\n    name: \"Admin User\"\n    email: \"admin@example.com\"\n    extends: admin\n  - id: 3\n    name: \"Super Admin\"\n    email: \"superadmin@example.com\"\n    extends: superadmin\n  - id: 4\n    name: \"NoTemplate\"\n    email: \"notemplate@example.com\"\n```\n\n**How it works:**\n- The `templates` section defines templates with a unique `name` and (optionally) an `extends` key for inheritance.\n- In regular rows, you can specify `extends: \u003ctemplate_name\u003e` to inherit all fields from the template (and its parents), overriding only the necessary fields.\n- Inheritance can be multi-level (extends a chain).\n- If a field is present in both the template and the row, the row value takes precedence.\n- Cyclic inheritance is detected and prevented.\n\n**Resulting rows:**\n- id: 1 — will get all fields from the `base` template\n- id: 2 — from `admin` (i.e., both `base` and `admin`)\n- id: 3 — from `superadmin` (i.e., all three templates)\n- id: 4 — only explicitly specified fields\n\n### Table Loading Order\n\nThe loading order is automatically determined based on foreign key dependencies. This ensures that referenced records exist before dependent records are inserted.\n\nExample of proper table ordering:\n1. Independent tables (no foreign keys)\n2. Tables with foreign keys pointing to loaded tables\n3. Junction tables (many-to-many relationships)\n\n## Limitations\n\n- SQL queries in `$eval()` must return exactly one value\n- Loading order is determined automatically based on foreign keys\n- MySQL support is new and may have some edge cases not fully covered\n- Only the `id` field is used for merging rows when using `include` (if present)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2From8726%2Fpgfixtures","html_url":"https://awesome.ecosyste.ms/projects/github.com%2From8726%2Fpgfixtures","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2From8726%2Fpgfixtures/lists"}