Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
59 commits
Select commit Hold shift + click to select a range
81ff641
Update primary method return type to allow multiple primary keys
EmilianoBruni Aug 20, 2025
571b552
Add support for composite primary key in mysql with tests
EmilianoBruni Aug 20, 2025
1ff6c22
Add support for composite primary key in mssql with tests
EmilianoBruni Aug 20, 2025
74daa63
Fix: revert test host to localhost
EmilianoBruni Aug 20, 2025
4f5bec7
Add support for composite primary key in postgres with tests
EmilianoBruni Aug 20, 2025
7eabc68
cockroach:latest-v21.1 doesn't exist anymore on dockerhub. updated to…
EmilianoBruni Aug 20, 2025
3a87b64
fix: primary key query was wrong. Fixed.
EmilianoBruni Aug 20, 2025
c3f067e
Add support for composite primary key in cockroachdb with tests
EmilianoBruni Aug 20, 2025
51e9ff2
Add support for composite primary key in oracle
EmilianoBruni Aug 20, 2025
6abfaca
Add support for composite primary key in sqlite
EmilianoBruni Aug 20, 2025
5ec78ca
temporary disable push and pull action
EmilianoBruni Aug 20, 2025
3de5ef1
add docker in docker
EmilianoBruni Aug 20, 2025
72a22ad
removed unnecessary sudo
EmilianoBruni Aug 20, 2025
ba2eb6d
add wget
EmilianoBruni Aug 20, 2025
458fdda
add docker compose plugin
EmilianoBruni Aug 20, 2025
ca36613
default docker installation
EmilianoBruni Aug 20, 2025
673650b
force -y to apt-get
EmilianoBruni Aug 20, 2025
c3ff3f0
fix docker compose syntax
EmilianoBruni Aug 20, 2025
0cd7302
switch to pnpm
EmilianoBruni Aug 20, 2025
76ac50c
update library to latest
EmilianoBruni Aug 20, 2025
62609d4
lint:fix
EmilianoBruni Aug 20, 2025
aabaf49
update Node.js version in CI workflow and switch to pnpm for dependen…
EmilianoBruni Aug 20, 2025
c0e7d89
refactor: improve clarity in workflow steps and add service name for …
EmilianoBruni Aug 20, 2025
970f07d
fix: add Git checkout step before setting up Node.js in CI workflow
EmilianoBruni Aug 20, 2025
042b72a
fix: update docker-compose commands to use 'docker compose' syntax
EmilianoBruni Aug 20, 2025
e8c76d4
fix: remove unnecessary blank line in CI workflow and add pnpm-lock.y…
EmilianoBruni Aug 20, 2025
7aba718
fix: remove version declaration from docker-compose file
EmilianoBruni Aug 20, 2025
2c8b339
fix: move 'Starting DB services under docker' step above 'Use Node.js…
EmilianoBruni Aug 20, 2025
57345a8
add debug code
EmilianoBruni Aug 20, 2025
029542d
add sudo required for debug
EmilianoBruni Aug 20, 2025
a0278e9
move checkout to begin
EmilianoBruni Aug 20, 2025
d88c203
some test
EmilianoBruni Aug 20, 2025
56e3471
test
EmilianoBruni Aug 21, 2025
e704d66
test
EmilianoBruni Aug 21, 2025
da1c57a
test
EmilianoBruni Aug 21, 2025
0d50037
test
EmilianoBruni Aug 21, 2025
80fb01f
test
EmilianoBruni Aug 21, 2025
cbcc43c
test
EmilianoBruni Aug 21, 2025
2536244
test
EmilianoBruni Aug 21, 2025
81a8824
test
EmilianoBruni Aug 21, 2025
f450f62
test
EmilianoBruni Aug 21, 2025
1b1ef87
test
EmilianoBruni Aug 21, 2025
d30040e
test
EmilianoBruni Aug 21, 2025
44e2b53
test
EmilianoBruni Aug 21, 2025
06bacc3
test
EmilianoBruni Aug 21, 2025
cde85ec
Fix composite primary key in oracle
EmilianoBruni Aug 21, 2025
7ba4950
fix: removed column
EmilianoBruni Aug 21, 2025
285a6ce
Test sqlite works
EmilianoBruni Aug 21, 2025
2b54a72
test
EmilianoBruni Aug 21, 2025
36e5d01
fix: update README to include CockroachDB support and clarify primary…
EmilianoBruni Aug 21, 2025
2e661e0
fix: update GitHub Actions workflow to support multiple Node.js versi…
EmilianoBruni Aug 21, 2025
5961094
added
EmilianoBruni Aug 21, 2025
1bf0729
lint:fix
EmilianoBruni Aug 21, 2025
e1f6a7f
add vscode devcontainer files
EmilianoBruni Aug 21, 2025
3dfe185
moved to docker folder
EmilianoBruni Aug 21, 2025
71b0ce3
fix: clarify DB service readiness steps in GitHub Actions workflow
EmilianoBruni Aug 21, 2025
79bc22b
v++ and add contributors
EmilianoBruni Aug 21, 2025
719b84e
fix: re-enable push and pull_request triggers in GitHub Actions workflow
EmilianoBruni Aug 21, 2025
8ded76e
fix: remove "type" module to (temporary?) revert to commonjs
EmilianoBruni Aug 21, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .devcontainer.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// For format details, see https://aka.ms/devcontainer.json.
{
"name": "knex-schema-inspector",
"dockerComposeFile": "docker/docker-compose.vscode.yml",
"service": "dev",
"workspaceFolder": "/ws/${localWorkspaceFolderBasename}"
}
58 changes: 39 additions & 19 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name: Tests

on: [push, pull_request]
on: [push, pull_request, workflow_dispatch]

defaults:
run:
Expand All @@ -12,32 +12,52 @@ jobs:

strategy:
matrix:
node-version: [14.x]

env:
LD_LIBRARY_PATH: /opt/oracle/instantclient_21_1
node-version: [20, 22]

steps:
- uses: actions/checkout@v2
- name: Checkout code
uses: actions/checkout@v4

- name: Install Oracle client
run: |
sudo apt install unzip
wget -q https://download.oracle.com/otn_software/linux/instantclient/211000/instantclient-basiclite-linux.x64-21.1.0.0.0.zip
sudo mkdir -p /opt/oracle
sudo unzip -qo instantclient-basiclite-linux.x64-21.1.0.0.0.zip -d /opt/oracle
- name: init apt
run: sudo apt update

- name: Install pnpm
uses: pnpm/action-setup@v4
with:
version: 10

- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v1
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'pnpm'

- name: Starting DB services under docker
run: docker compose --file 'docker/docker-compose.yml' up -d

- name: Install dependencies
run: pnpm install

- run: docker-compose up -d
- name: Fix sqlite pnpm bug
run: |
pnpm install sqlite3 better-sqlite3
cd node_modules/sqlite3; pnpm rebuild
cd ../better-sqlite3; pnpm rebuild

- name: Wait for mysql DB services to be ready
run: |
while ! docker compose --file 'docker/docker-compose.yml' logs mysql | grep -q 'mysqld: ready for connections.'; do sleep 2; done

- run: npm ci
- name: Wait for postgres DB services to be ready
run: |
while ! docker compose --file 'docker/docker-compose.yml' logs postgres | grep -q 'database system is ready to accept connections'; do sleep 2; done

- name: Wait for mssql DB services to be ready
run: |
while ! docker compose --file 'docker/docker-compose.yml' logs mssql | grep -q 'SQL Server is now ready for client connections'; do sleep 2; done

- run: "while ! docker-compose logs mysql | grep -q 'mysqld: ready for connections.'; do sleep 2; done"
- run: "while ! docker-compose logs postgres | grep -q 'database system is ready to accept connections'; do sleep 2; done"
- run: "while ! docker-compose logs mssql | grep -q 'SQL Server is now ready for client connections'; do sleep 2; done"
- name: Run tests
run: pnpm test

- run: npm test
- name: Stop DB services
run: docker compose --file 'docker/docker-compose.yml' down
1 change: 1 addition & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
dist
pnpm-lock.yaml
35 changes: 35 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Changelog

All notable changes to this project will be documented in this file.

## [3.1.1] - 2025-08-21

### Added

- Support for combined (composite) primary keys in [`primary`](README.md#primarytable-string-promisestring--string--null).

### Changed

- Moved to pnpm

### Fixed

- Fix detection of foreign keys in CockroachDB where always returned pk of first table
- Update library to latest
- Fix Github action

## [3.1.0] - 2023-10-23

### Added

- Add support for better-sqlite3.

### Changed

- MySQL Optimization

## [3.0.1] - 2023-01-30

### Fixed

- Fix CrDB auto-increment detection ([#135](https://github.com/knex/knex-schema-inspector/issues/135))
17 changes: 13 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Utility for extracting information about existing DB schema

This library currently supports Postgres, MySQL, MS SQL, SQLite, and OracleDB. We aim to have support for the same databases as the main knex project.
This library currently supports CockroachDB, Postgres, MySQL, MS SQL, SQLite, and OracleDB. We aim to have support for the same databases as the main knex project.

## Installation

Expand Down Expand Up @@ -71,7 +71,7 @@ Note 3: MSSQL doesn't support comment for either tables or columns

- [`columns(table?: string): Promise<{ table: string, column: string }[]>`](#columnstable-string-promise-table-string-column-string-)
- [`columnInfo(table?: string, column?: string): Promise<Column[] | Column>`](#columninfotable-string-column-string-promisecolumn--column)
- [`primary(table: string): Promise<string>`](#primarytable-string-promisestring)
- [`primary(table: string): Promise<string | string[] | null>`](#primarytable-string-promisestring--string--null)

**Foreign Keys**

Expand Down Expand Up @@ -207,15 +207,24 @@ await inspector.columnInfo('articles', 'id');
// }
```

#### `primary(table: string): Promise<string>`
#### `primary(table: string): Promise<string | string[] | null>`

Retrieve the primary key column for a given table
Retrieve the primary key columns for a given table.

If there is only one primary key for a given table, it return as a string. (This is the only return in ver <= 3.1.0)

```ts
await inspector.primary('articles');
// => "id"
```

If table has a combined (multiple) primary keys, they are return as an array of string. Version previous 3.1.0 doesn't support combined pks and in this case it returned the first pk only.

```ts
await inspector.primary('article_comments');
// => ["article_id","comment_id"]
```

### Foreign Keys

Retrieve all configured foreign key constraints.
Expand Down
42 changes: 42 additions & 0 deletions docker/dev/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# config
ARG IDIR
# development|production
ARG BMODE=development

# 01a - base image
FROM ebruni/pnpm AS base
ARG IDIR
# add node_modules executables to PATH
ENV PATH="/ws/${IDIR}/node_modules/.bin:${PATH}"

# 02a - Install dependencies only when package.json changes
FROM base AS deps
ARG IDIR
ARG BMODE
ENV NODE_ENV=${BMODE}
WORKDIR /ws/${IDIR}
# Install dependencies based on the preferred package manager
COPY --chown=node:node . ./
RUN --mount=type=cache,id=ksi_pnpm-store,uid=1000,gid=1000,target=/home/node/pnpm/store [ -e pnpm-lock.yaml ] && pnpm install --frozen-lockfile || pnpm install

# 03a - Rebuild the source code only when needed
FROM base AS builder
ARG IDIR
ARG BMODE
ENV NODE_ENV=${BMODE}
WORKDIR /ws/${IDIR}
COPY --chown=node:node . ./
COPY --chown=node:node --from=deps ws/${IDIR}/pnpm-lock.yaml* .
COPY --chown=node:node --from=deps ws/${IDIR}/node_modules ./node_modules

# 04a - Production image
FROM base AS runner
ARG IDIR
ARG BMODE
ENV NODE_ENV=\${BMODE}
WORKDIR /ws/${IDIR}

COPY --from=builder ws/${IDIR}/node_modules ./node_modules
COPY --from=builder ws/${IDIR}/package.json ws/${IDIR}/pnpm-lock.yaml* ./

CMD [""]
30 changes: 30 additions & 0 deletions docker/docker-compose.vscode.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
services:
dev:
image: vs-knex-schema-inspector
build:
context: ../
dockerfile: docker/dev/Dockerfile
args:
- IDIR=knex-schema-inspector
volumes:
- ../:/ws/knex-schema-inspector:cached
- lib-modules:/ws/knex-schema-inspector/node_modules

# Overrides default command so things don't shut down after the process ends.
command: sleep infinity
env_file: ../.env
environment:
# not in .env because .env can be used in prod too
FORCE_UID: 1001
FORCE_GID: 1001
deploy:
resources:
limits:
cpus: '2'
volumes:
lib-modules:

networks:
default:
name: docker_default
external: true
21 changes: 10 additions & 11 deletions docker-compose.yml → docker/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
version: '3.1'
services:
mysql:
image: mysql:5.7
Expand All @@ -9,7 +8,7 @@ services:
ports:
- 5100:3306
volumes:
- ./test/seed/mysql.sql:/docker-entrypoint-initdb.d/seed.sql
- ../test/seed/mysql.sql:/docker-entrypoint-initdb.d/seed.sql
postgres:
image: postgres:12.3
restart: always
Expand All @@ -19,7 +18,7 @@ services:
ports:
- 5101:5432
volumes:
- ./test/seed/postgres.sql:/docker-entrypoint-initdb.d/seed.sql
- ../test/seed/postgres.sql:/docker-entrypoint-initdb.d/seed.sql

postgres10:
image: postgres:10
Expand All @@ -30,7 +29,7 @@ services:
ports:
- 5102:5432
volumes:
- ./test/seed/postgres10.sql:/docker-entrypoint-initdb.d/seed.sql
- ../test/seed/postgres10.sql:/docker-entrypoint-initdb.d/seed.sql

mssql:
image: mcr.microsoft.com/mssql/server:2017-CU24-ubuntu-16.04
Expand All @@ -44,7 +43,7 @@ services:
- 1433:1433
volumes:
- mssql-volume:/var/opt/mssql/
- ./test:/tmp/test
- ../test:/tmp/test

# Note: you need to be logged in to DockerHub, and accept the EULA for oracle/database-enterprise to work
# ... no clue how to get around that in GH Actions for tests ...
Expand All @@ -68,24 +67,24 @@ services:
working_dir: /tmp/test
command: sh -c './scripts/oracle-entrypoint.sh'
volumes:
- ./test:/tmp/test
- ../test:/tmp/test

cockroachdb:
image: cockroachdb/cockroach:latest-v21.1
image: cockroachdb/cockroach:latest-v21.2
container_name: crdb
hostname: crdb
command: start-single-node --cluster-name=example-single-node --insecure
volumes:
- ./test/seed/postgres.sql:/docker-entrypoint-initdb.d/seed.sql
- ../test/seed/postgres.sql:/docker-entrypoint-initdb.d/seed.sql
ports:
- '26257:26257'
- '8080:8080'

cockroachdb-init:
image: cockroachdb/cockroach:latest-v21.1
image: cockroachdb/cockroach:latest-v21.2
volumes:
- ./test/seed/cockroachdb.sql:/seed.sql
- ./test/scripts/cockroachdb-init.sh:/init.sh
- ../test/seed/cockroachdb.sql:/seed.sql
- ../test/scripts/cockroachdb-init.sh:/init.sh
entrypoint: '/bin/bash'
command: /init.sh

Expand Down
34 changes: 21 additions & 13 deletions lib/dialects/cockroachdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -166,10 +166,9 @@ export default class CockroachDB implements SchemaInspector {
*/
async columns(table?: string) {
const query = this.knex
.select<{ table_name: string; column_name: string }[]>(
'table_name',
'column_name'
)
.select<
{ table_name: string; column_name: string }[]
>('table_name', 'column_name')
.from('information_schema.columns')
.whereIn('table_schema', this.explodedSchema);

Expand Down Expand Up @@ -345,26 +344,35 @@ export default class CockroachDB implements SchemaInspector {
/**
* Get the primary key column for the given table
*/
async primary(table: string): Promise<string> {
async primary(table: string) {
const result = await this.knex
.select('information_schema.key_column_usage.column_name')
.from('information_schema.key_column_usage')
.leftJoin(
'information_schema.table_constraints',
'information_schema.table_constraints.constraint_name',
'information_schema.key_column_usage.constraint_name'
)
.leftJoin('information_schema.table_constraints', function () {
this.on(
'information_schema.table_constraints.constraint_name',
'=',
'information_schema.key_column_usage.constraint_name'
).andOn(
'information_schema.table_constraints.table_name',
'=',
'information_schema.key_column_usage.table_name'
);
})
.whereIn(
'information_schema.table_constraints.table_schema',
this.explodedSchema
)
.andWhere({
'information_schema.table_constraints.constraint_type': 'PRIMARY KEY',
'information_schema.table_constraints.table_name': table,
})
.first();
});

return result ? result.column_name : null;
return result.length > 0
? result.length === 1
? (result[0].column_name as string)
: (result.map((r) => r.column_name) as string[])
: null;
}

// Foreign Keys
Expand Down
Loading