不喜欢使用 orm 框架,分享一个自己写 postgresql 的 sql 构造库 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
KouShuiYu
V2EX    Node.js

不喜欢使用 orm 框架,分享一个自己写 postgresql 的 sql 构造库

  •  
  •   KouShuiYu 2021-02-23 11:49:40 +08:00 3616 次点击
    这是一个创建于 1690 天前的主题,其中的信息可能已经有所发展或是发生改变。

    GitHub 地址

    API 文档暂时还没有,下面是使用的 demo

    pg-helper

    use node-postgres easier

    Examples

    const {PgHelper} = require('@c_kai/pg-helper'); // detail https://node-postgres.com/api/pool const pgHelper = new PgHelper({ host, user, password, database, port: 5432, max: 20, idleTimeoutMillis: 30000, connectionTimeoutMillis: 2000, }); 

    insert

    const result = await pgHelper.insert([{ percentage: 0, type: 'public', params: {}, created_by: 1, status: 'created', job_uuid: '103', },{ percentage: 0, type: 'public', params: {}, created_by: 1, status: 'created', job_uuid: '104', }], { tableName: 'jobs', returning: true, }); 

    delete

    const result = await pgHelper.delete({}, { tableName: 'jobs', transaction, }); 

    update

    const result = await pgHelper.update({ type: 'pravate', status: 'gg', }, { update: ['type', 'status'], tableName: 'jobs', returning: ['id'], transaction, }); 

    select

    const result = await pgHelper.select({ percentage: 0, }, { where: { percentage: '= {percentage}' or: { id: '=1', } }, schemaName: 'public', tableName: 'jobs', autoHump: false, count: true, }); 

    Run sql

    await pgHelper.runSql('select now()'); // with params await pgHelper.runSql('select power({a}, {b})', { a: 2, b: 4 }); 

    Run sql use transaction

    await pgHelper.runTSql([ { sql: 'select now()', }, { sql: 'select power({a}, {b})', params: { a: 2, b: 4} } ]) 

    OR

    let transaction; try { transaction = await pgHelper.getTransaction(); let result4 = await pgHelper.runSql('select {str1} || {str2}', { str1: 'xiao', str2: 'hong', }, { transaction, }); transaction.commit(); console.log(result4) } catch (error) { transaction.rollback(); } 
    第 1 条附言    2021-02-23 15:08:43 +08:00
    API 文档完成了 字段限制,分割了

    # pg-helper

    A small helper for node-postgres to help you with building your queries.


    [node-postgres]( https://node-postgres.com/) 使用序数参数查询`($1, $2, etc)`, 因此变量需要有明确的顺序,一旦参数过多使用起来就异常麻烦,该模块使你更容易、更快速、更安全的构建 SQL 。

    ## Featrues

    + 你可以使用`pgHelper.runSql` 函数

    ```js
    pgHelper.runSql('SELECT * FROM table WHERE field1 = {field1} AND field2 = {field2}', {field1, field2});

    //当然你仍然可以使用
    pgHelper.runSql('SELECT * FROM table WHERE field1 = $1 AND field2 = $2', [field1, field2]);
    ```

    + 该模块还提供了`select`、`update`、`delete`、`insert` 等函数方便对单表进行 CURD ;

    + 该模块封装了对事务的操作

    ```js
    await pgHelper.runTSql([
    {
    sql: 'select now()',
    },
    {
    sql: 'select power({a}, {b})',
    params: { a: 2, b: 4}
    }
    ]);

    //OR

    let transaction;
    try {
    transaction = await pgHelper.getTransaction();
    await pgHelper.runSql('select now()', {
    transaction,
    });
    await pgHelper.runSql('select power({a}, {b})', { a: 2, b: 4}, {
    transaction,
    });
    transaction.commit();

    } catch (error) {
    transaction.rollback();
    }
    ```
    第 2 条附言    2021-02-23 15:17:44 +08:00

    API

    PgHelper Class

    new PgHelper(config, options)

    • config same as pg.Pool
    • options
      • options.autoHump Boolean - 如果autoHump为true返回字段的名称会格式化为驼峰
      • options.returning Boolean - 如果returning为true返回结果会包含更新、插入、修改的数据
      • options.logger Object - 替换默认的日志需要包含infoerror两个函数

    pgHelper.insert(params, options)

    Function

    params

    • params Array<Object> - 插入表的数据,其中Object的key需要和字段一一对应
    • options
      • options.tableNameString- 表名称
      • options.schemaNameString- 表名称;default: public
      • options.returning Boolean|Array - 如果returning为true,返回结果会包含插入的数据,为数组时返回数组包含的字段

    return

    same as pg.queries

    pgHelper.delete(params, options)

    Function

    params

    • params Object - 模版参数,其中Object的key需要和SQL模版中{key}值一一对应

    • options

      • options.tableNameString- 表名称

      • options.schemaNameString- 表名称;default: public

      • options.returning Boolean|Array - 如果returning为true,返回结果会包含删除的数据,为数组时返回数组包含的字段

      • options.whereObject 构建where sql

        { id: '>10', type: '={type}', or:{ id:'= any({ids})' } } // sql //where (id > 0 and type={type} or (id = any({ids} ) ) 
    第 3 条附言    2021-02-23 15:19:37 +08:00

    pgHelper.update(params, options)

    Function

    params

    • params Object - 模版参数,其中Object的key需要和SQL模版中{key}值一一对应

    • options

      • options.tableNameString- 表名称

      • options.schemaNameString- 表名称;default: public

      • options.returning Boolean|Array - 如果returning为true,返回结果会包含更新的数据,为数组时返回数组包含的字段

      • options.whereObject 构建where sql

        { id: '>10', type: '={type}', or:{ id:'= any({ids})' } } // sql //where (id > 0 and type={type} or (id = any({ids} ) ) 
      • options. updateArray|Object - 需要更新的字段

        ['name', 'type'] // name = {name},type={type} OR { name: 'name', type: 'myType', } name = {name},type={myType} 

    return

    same as pg.queries

    pgHelper.select(params, options)

    Function

    params

    • params Object - 模版参数,其中Object的key需要和SQL模版中{key}值一一对应

    • options

      • options.tableNameString- 表名称

      • options.schemaNameString- 表名称;default: public

      • options.whereObject 构建where sql

        { id: '>10', type: '={type}', or:{ id:'= any({ids})' } } // sql //where (id > 0 and type={type} or (id = any({ids} ) ) 
      • options.limit int - limit number

      • options.offset int -offset number

      • options.count Boolean -是否返回查询的行数

      • options.include array - 返回的字段数组default*

      • options.order array 构建ordersql

        ['id', ['type', 'desc'], [''name'', 'asc']] // order by id, type desc, name asc 

    return

    same as pg.queries

    18 条回复    2021-02-24 11:40:54 +08:00
    bleepbloop
        1
    bleepbloop  
       2021-02-23 11:53:25 +08:00
    看了一下,好像不能防注入?
    KouShuiYu
        2
    KouShuiYu  
    OP
       2021-02-23 11:55:02 +08:00
    @bleepbloop 可以防止注入 sql 中的{params}会被替换为$n 的形式
    KouShuiYu
        3
    KouShuiYu  
    OP
       2021-02-23 11:56:07 +08:00
    KouShuiYu
        4
    KouShuiYu  
    OP
       2021-02-23 11:58:44 +08:00
    官方提供的这种方式感觉太不好用了
    ```js
    const query = {
    text: 'INSERT INTO users(name email) VALUES($1, $2)',
    values: ['brianc', '[email protected]'],
    }

    ```

    我改成了这种形式
    ```
    const query = {
    text: 'INSERT INTO users(name, email) VALUES({name}, {email})',
    values: { name: 'brianc', email: '[email protected]']
    }
    ``
    KouShuiYu
        5
    KouShuiYu  
    OP
       2021-02-23 11:59:33 +08:00
    官方提供的这种方式感觉太不好用了
    ```js
    const query = {
    text: 'INSERT INTO users(name, email) VALUES($1, $2)',
    values: ['brianc', '[email protected]'],
    }

    ```

    我改成了这种形式
    ```js
    const query = {
    text: 'INSERT INTO users(name, email) VALUES({name}, {email})',
    values: { name: 'brianc', email: '[email protected]']
    }
    ```
    KouShuiYu
        6
    KouShuiYu  
    OP
       2021-02-23 12:00:06 +08:00
    额,好像不支持代码块
    fucUup
        7
    fucUup  
       2021-02-23 12:39:42 +08:00
    js 读写数据库?????

    小心清库跑路
    KiseXu
        8
    KiseXu  
       2021-02-23 12:45:26 +08:00
    @fucUup 这个节点是 Node.js
    fucUup
        9
    fucUup  
       2021-02-23 12:48:21 +08:00
    @KiseXu 跟语言无关, 我是吐槽你的交付物, 用起来很容易犯错的, 这样就不好, 一定要用核电站的思维写代码, 把容易犯错的设计砍掉
    fucUup
        10
    fucUup  
       2021-02-23 12:49:53 +08:00
    这种交付物, 接近裸写 sql, 不仅分库分表 一旦表动难维护, 还有容易清库跑路嫌疑
    RockShake
        11
    RockShake  
       2021-02-23 13:04:00 +08:00
    做小项目没问题的,楼主说了这是 ORM 的替代方案
    0clickjacking0
        12
    0clickjacking0  
       2021-02-23 15:23:28 +08:00
    orm 是真的可以杜绝 sql 注入的
    xieren58
        13
    xieren58  
       2021-02-23 15:24:54 +08:00
    knexjs 不好用吗?
    KouShuiYu
        14
    KouShuiYu  
    OP
       2021-02-23 16:05:25 +08:00
    @xieren58 这个用起来比较简单,对照的是 https://github.com/felixfbecker/node-sql-template-strings,我又加上了方便单表 CURD 的四个方法
    ERRASYNCTYPE
        15
    ERRASYNCTYPE  
       2021-02-24 11:11:05 +08:00
    哈哈哈哈跟我自己做的一个好像,不过我用 gt gte lt lte 这些 mongodb 的保留词来做 where 构造
    KouShuiYu
        16
    KouShuiYu  
    OP
       2021-02-24 11:33:35 +08:00
    @ERRASYNCTYPE 考虑到 where 表达式情况太复杂了,还要额外加好多接口,所以就放开了
    ERRASYNCTYPE
        17
    ERRASYNCTYPE  
       2021-02-24 11:40:07 +08:00
    @KouShuiYu 确实,还有 or between 什么的要处理,所以我都是自己根据自己业务去个别调整来着,不完备
    felixin
        18
    felixin  
       2021-02-24 11:40:54 +08:00 via Android
    看一下 slonik
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     4493 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 01:02 PVG 09:02 LAX 18:02 JFK 21:02
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86