
Security News
Deno 2.2 Improves Dependency Management and Expands Node.js Compatibility
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
npm i mql2
const { PostgreSQL } = require('mql2');
const { CONNECT } = PostgreSQL;
const POOL = await CONNECT({
host: 'localhost',
user: 'username',
password: '1234',
database: 'dbname'
});
MQL은 내부적으로 node-postgres를 사용합니다. CONNECT
함수에 사용되는 옵션은 node-postgres와 동일합니다. 디비 연결이나 커넥션 풀과 관련된 자세한 옵션은 node-postgres 사이트에서 확인할 수 있습니다.
const { MySQL } = require('mql2');
const { CONNECT } = MySQL;
const POOL = await CONNECT({
host: 'localhost',
user: 'username',
password: '1234',
database: 'dbname'
});
MQL은 내부적으로 mysql를 사용합니다. CONNECT
함수에 사용되는 옵션은 mysql과 동일합니다. 디비 연결이나 커넥션 풀과 관련된 자세한 옵션은 mysql 사이트에서 확인할 수 있습니다.
const { QUERY } = POOL;
const id = 10;
const posts = await QUERY `SELECT * FROM posts WHERE id = ${id}`;
// [{ id: 10, ... }]
const type = 'TYPE1';
const limit = 10;
QUERY `
SELECT * FROM table1 WHERE table2_id IN (
SELECT id FROM table2 WHERE type = ${type} ORDER BY id DESC LIMIT ${limit}
)
`;
const status = 'STATUS1';
QUERY `
SELECT *
FROM table1 AS t1, table2 AS t2
WHERE t1.id = t2.table1_id AND t1.status = ${status}
ORDER BY id DESC
LIMIT 10
`;
CONNECT
를 통해 얻은 QUERY
는 connection pool을 이용합니다.
const POOL = await CONNECT();
const = {
VALUES, IN, NOT_IN, EQ, SET, COLUMN, CL, TABLE, TB, SQL, MQL_DEBUG,
QUERY,
ASSOCIATE,
LJOIN,
TRANSACTION
} = POOL;
const users = await QUERY `SELECT * FROM users WHERE ${EQ({
email: 'dev@marpple.com',
password: '1234'
})}`;
// [{ id: 15, email: 'dev@marpple.com', ... }]
const users = await QUERY `SELECT * FROM users WHERE ${IN('id', [15, 19, 20, 40])}`;
// [{ id: 15, ...}, { id: 19, ...} ...]
const users = await QUERY `SELECT * FROM users WHERE ${NOT_IN('id', [2, 4])} LIMIT 3 ORDER BY ID`;
// [{ id: 1, ...}, { id: 3, ...}, { id: 5, ...}]
const post = { user_id: 10, body: 'hoho' };
await QUERY `
INSERT INTO posts ${VALUES(post)}
`;
// INSERT INTO posts ("user_id", "body") VALUES (10, 'hohoho')
await QUERY `
INSERT INTO coords ${VALUES([
{x: 20},
{y: 30},
{x: 10, y: 20}
])}`;
// INSERT INTO coords ("x", "y") VALUES (20, DEFAULT), (DEFAULT, 30), (10, 20)
await QUERY `
UPDATE posts ${SET({ body: 'yo!', updated_at: new Date() })} WHERE id = ${post.id}
`;
// UPDATE posts SET "body" = 'yo!', "updated_at" = '2018-08-28T23:18:13.263Z' WHERE id = 10
COLUMN == CL; // true
await QUERY `
SELECT
COLUMN('id', 'bb as cc', 't2.name', 't2.name as name2', { a: 'c' }, { 't3.a': 'd' })
...
`;
// SELECT
// "id", "bb" AS "cc", "t2"."name", "t2"."name" AS "name2", "a" AS "c", "t3"."a" AS "d"
// ...
TABLE == TB; // true
await QUERY `
SELECT
...
FROM TABLE('t1'), TABLE('tt as t2')
`;
// SELECT
// ...
// FROM "t1", "tt" AS "t2"
ASSOCIATE
는 connection pool을 이용합니다.
/*
* users
* - id
* - name
*
* posts
* - id
* - user_id
* - body
* comments
* - id
* - user_id
* - post_id
* - body
* */
const { ASSOCIATE } = POOL;
const posts = await ASSOCIATE `
posts
- user
< comments
- user
`;
posts[0].body; // 내용
posts[0]._.user.name // 글쓴이 이름
posts[0]._.comments[0].body // 코멘트 내용
posts[0]._.comments[0]._.user.name // 댓글 작성자 이름
/*
* photos
* - attached_type
* - attached_id
* */
await ASSOCIATE `
posts
- user
p - photo
p < photos
< comments
p < photos
`;
// SELECT * FROM photos WHERE attached_id IN (${map($ => $.id, posts)}) AND attached_type = 'photos';
// SELECT * FROM photos WHERE attached_id IN (${map($ => $.id, users)}) AND attached_type = 'users';
// SELECT * FROM photos WHERE attached_id IN (${map($ => $.id, comments)}) AND attached_type = 'comments';
/*
* books
* - id
*
* authors
* - id
* - name
*
* books_authors
* - author_id
* - book_id
* */
const books = await ASSOCIATE `
books
x authors
`;
books[0]._.authors[0].name; // 이름
const authors = await ASSOCIATE `
authors
x books ${{ xtable: 'books_authors' }}
`;
authors[0]._.books[0].name; // 책 이름
/*
* 테이블명과 컬럼명이 이미 MQL 포맷과 동일하거나 ViEW 등을 이용해 잘 맞춰놨을 때에는
* ASSOCIATE에게 넘긴 문자열들을 기반으로 자동으로 테이블명과 컬럼명들을 적절히 생성합니다.
* users
* - id
* posts
* - id
* - user_id
* comments
* - id
* - post_id
* - user_id
* likes
* - attached_type
* - attached_id
* - user_id
* posts_tags
* - post_id
* - tag_id
* tags
* - id
* */
ASSOCIATE `
posts
- user
< comments
- user
p < likes
- user
p < likes
- user
x tags
`;
/*
* 위 상황에서 컬럼들을 최소화해서 가져오고 싶거나 쿼리를 추가하고 싶다면 아래와 같이할 수 있습니다.
* column에 기본키나 외래키 등을 포함시키지 않아도 적절히 ASSOCIATE 내부에서 추가하여 적절히 가져옵니다.
* */
ASSOCIATE `
posts ${SQL `WHERE is_hidden = false ORDER BY id DESC LIMIT ${10}`}
- user
< comments ${{
column: COLUMN('body', 'updated_at')
}}
- user
p < likes
- user
p < likes
- user
x tags
`;
/*
* 만일 테이블이 아래와 같다면 옵션을 통해 매칭을 시켜주면 됩니다.
* members
* - member_id
* articles
* - id
* - writer_id
* comments
* - id
* - article_id
* - writer_id
* likes
* - parent_name
* - parent_id
* - member_id
* tags_articles
* - article_id
* - tag_name
* tags
* - name
* */
const posts = await ASSOCIATE `
posts ${{
table: 'articles' // 데이터베이스 테이블 명이 다를 때
}}
- user ${{ // - 를 했으므로 하나를 객체로 가져옴
left_key: 'writer_id', // articles가 가진 members.member_id를 가리키는 컬럼
key: 'member_id', // members 테이블이 가진 키
table: 'members' // user의 테이블 명
}}
< comments ${{ // < 를 했으므로 배열로 여러개를 가져옴
key: 'article_id' // articles의 id를 가리키는 comments가 가진 컬럼
}}
- user ${{
left_key: 'writer_id', // articles가 가진 members.member_id를 가리키는 컬럼
key: 'member_id', // members 테이블이 가진 키
table: 'members' // user의 테이블 명
}}
p < likes ${{ // p < 를 이용해 하나의 likes 테이블을 통해 comments와 posts의 likes를 구현
poly_type: { parent_name: 'comments' },
key: 'parent_id'
}}
p < likes ${{ // p < 를 이용해 하나의 likes 테이블을 통해 comments와 posts의 likes를 구현
poly_type: { parent_name: 'articles' },
key: 'parent_id'
}}
x tags ${{ // x 를 통해 중간 테이블을 join 하여 다대다 관계 구현
left_key: 'id', // articles.id (articles.id = tags_articles.article_id)
left_xkey: 'article_id', // left_key와 매칭되는 tags_articles의 키 article_id
xtable: 'tags_articles', // 중간 테이블 이름
xkey: 'tag_name', // key와 매칭되는 tags_articles의 키 tag_name
key: 'name' // tags가 가진 키 (tags_articles.tag_name = tags.name)
}}
`;
위와 같이 데이터베이스의 테이블명과 사용하고자하는 이름이 다르거나, ASSOCIATE
가 자동생성하는 컬럼명 등과 실제 데이터베이스의 상태가 다를 경우 옵션을 이용하여 맞춰줄 수 있습니다. 그러나 대부분의 경우는 데이터베이스의 VIEW를 사용하는 것이 코드 관리에 좋습니다.
hook
을 이용하여 가상 컬럼이나, 정렬, 필터 등의 추가 작업을 할 수 있습니다. 자신의 안쪽 데이터들이 모두 불려진 후 실행되어 활용하기 좋습니다.
const users = await ASSOCIATE `
users ${{hook: users => users.map(u =>
Object.assign({}, u, { _popular: !!u._.posts.find(p => p._is_best) })
)}}
< posts ${{hook: posts => posts.map(
p => Object.assign({}, p, { _is_best: p._.comments.length > 1 }))}}
- user
< comments
- user
`;
users[0]._popular; // true
users[0]._.posts[0]._is_best; // true
users[0]._.posts[1]._is_best; // false
const { PostgreSQL } = require('mql2');
const { CONNECT } = PostgreSQL;
const POOL = await CONNECT({
host: 'localhost',
user: 'username',
password: '1234',
database: 'dbname',
charset: 'utf8'
});
const { TRANSACTION } = POOL;
const { QUERY, COMMIT, ROLLBACK } = await TRANSACTION();
await QUERY `
INSERT INTO posts ${VALUES(post)}
`;
await QUERY `
UPDATE posts ${SET({ body: 'yo!', updated_at: new Date() })} WHERE id = ${post.id}
`;
await ROLLBACK();
TRANSACTION
을 통해 얻은 QUERY
는 하나의 connection을 이용합니다. ROLLBACK
이나 COMMIT
을 하고나면 앞서 함께 얻었던 QUERY
함수의 커넥션은 해제되고 더이상 사용할 수 없습니다.
MQL_DEBUG.LOG
를 true
로 설정한 후 QUERY
를 실행하면 콘솔에 DB로 보낸 쿼리들을 출력합니다.
MQL_DEBUG.LOG = true;
QUERY `SELECT ${"hi~"} as ho`;
// { text: 'SELECT $1 as ho', values: ['hi'] }
FAQs
query builder
The npm package mql2 receives a total of 37 weekly downloads. As such, mql2 popularity was classified as not popular.
We found that mql2 demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Deno 2.2 enhances Node.js compatibility, improves dependency management, adds OpenTelemetry support, and expands linting and task automation for developers.
Security News
React's CRA deprecation announcement sparked community criticism over framework recommendations, leading to quick updates acknowledging build tools like Vite as valid alternatives.
Security News
Ransomware payment rates hit an all-time low in 2024 as law enforcement crackdowns, stronger defenses, and shifting policies make attacks riskier and less profitable.