V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
KouShuiYu
V2EX  ›  Node.js

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

  •  
  •   KouShuiYu · 13 天前 · 1782 次点击

    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 条附言  ·  13 天前
    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 条附言  ·  13 天前

    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 条附言  ·  13 天前

    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   13 天前
    看了一下,好像不能防注入?
    KouShuiYu
        2
    KouShuiYu   13 天前
    @bleepbloop 可以防止注入 sql 中的{params}会被替换为$n 的形式
    KouShuiYu
        4
    KouShuiYu   13 天前
    官方提供的这种方式感觉太不好用了
    ```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   13 天前
    官方提供的这种方式感觉太不好用了
    ```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   13 天前
    额,好像不支持代码块
    fucUup
        7
    fucUup   13 天前
    js 读写数据库?????

    小心清库跑路
    KiseXu
        8
    KiseXu   13 天前
    @fucUup 这个节点是 Node.js
    fucUup
        9
    fucUup   13 天前
    @KiseXu 跟语言无关, 我是吐槽你的交付物, 用起来很容易犯错的, 这样就不好, 一定要用核电站的思维写代码, 把容易犯错的设计砍掉
    fucUup
        10
    fucUup   13 天前
    这种交付物, 接近裸写 sql, 不仅分库分表 一旦表动难维护, 还有容易清库跑路嫌疑
    RockShake
        11
    RockShake   13 天前
    做小项目没问题的,楼主说了这是 ORM 的替代方案
    0clickjacking0
        12
    0clickjacking0   13 天前
    orm 是真的可以杜绝 sql 注入的
    xieren58
        13
    xieren58   13 天前
    knexjs 不好用吗?
    KouShuiYu
        14
    KouShuiYu   13 天前
    @xieren58 这个用起来比较简单,对照的是 https://github.com/felixfbecker/node-sql-template-strings,我又加上了方便单表 CURD 的四个方法
    ERRASYNCTYPE
        15
    ERRASYNCTYPE   12 天前
    哈哈哈哈跟我自己做的一个好像,不过我用 gt gte lt lte 这些 mongodb 的保留词来做 where 构造
    KouShuiYu
        16
    KouShuiYu   12 天前
    @ERRASYNCTYPE 考虑到 where 表达式情况太复杂了,还要额外加好多接口,所以就放开了
    ERRASYNCTYPE
        17
    ERRASYNCTYPE   12 天前
    @KouShuiYu 确实,还有 or between 什么的要处理,所以我都是自己根据自己业务去个别调整来着,不完备
    felixin
        18
    felixin   12 天前 via Android
    看一下 slonik
    关于   ·   帮助文档   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2835 人在线   最高记录 5497   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 00:38 · PVG 08:38 · LAX 16:38 · JFK 19:38
    ♥ Do have faith in what you're doing.