dongshaidu2456 2017-09-19 23:34
浏览 228
已采纳

COALESCE在Postgres中返回文本类型而不是time_stamp类型

I'm trying to use COALESCE to deal with sql injections in Go.

query := `SELECT mc.company_name_full, msc.company_id, msc.cdate, %s
          FROM %s AS mc INNER JOIN %s AS msc
          ON (mc.id = msc.company_id)
          WHERE %s AND
          msc.company_id = COALESCE($1, msc.company_id) AND
          mc.company_name_full ~* COALESCE($2, mc.company_name_full) AND
          msc.cdate >= '2017-07-01' AND
          msc.cdate <= '%s'`
query = fmt.Sprintf(query, selectParam, companyTable, statsTable, whereParam, time.Now().Local().Format("2006-01-02"))

This query works, but when I try to use COALESCE with Time_stamp

query := `SELECT mc.company_name_full, msc.company_id, msc.cdate, %s
          FROM %s AS mc INNER JOIN %s AS msc
          ON (mc.id = msc.company_id)
          WHERE %s AND
          msc.company_id = COALESCE($1, msc.company_id) AND
          mc.company_name_full ~* COALESCE($2, mc.company_name_full) AND
          msc.cdate >= COALESCE($3, '2017-07-01') AND
          msc.cdate <= COALESCE($4, '%s')`

but I get this error

pq:operator does not exist: timestamp without time zone >= text

What can I do to ensure that COALESCE returns a timestamp type?

  • 写回答

2条回答 默认 最新

  • dongwei2983 2017-09-20 00:00
    关注

    You can cast the text string to a timestamp, like so:

    `SELECT mc.company_name_full, msc.company_id, msc.cdate, %s
          FROM %s AS mc INNER JOIN %s AS msc
          ON (mc.id = msc.company_id)
          WHERE %s AND
          msc.company_id = COALESCE($1, msc.company_id) AND
          mc.company_name_full ~* COALESCE($2, mc.company_name_full) AND
          msc.cdate >= COALESCE($3, '2017-07-01'::timestamp) AND
          msc.cdate <= COALESCE($4, '%s'::timestamp)`
    

    General Caveat:

    I'm not too familiar with the syntax of Go, but from what I can tell, %s here is used by Sprintf for direct formatting (interpolation), so having these in your where clause still technically allows SQL Injection.

    Anywhere possible (and for some things, like table names, it really isn't, but even in that case you need to be as careful as possible from where the variables that are interpolated come), bindings should be used.

    e.g. why can't time.Now().Local().Format("2006-01-02") be passed as a binding and not interpolated?

    Update in response to comment from OP:

    From the Go lib/pq package doc, in the example code:

    rows, err := db.Query(`SELECT name FROM users WHERE favorite_fruit = $1
        OR age BETWEEN $2 AND $2 + 3`, "orange", 64)
    

    the $1 and $2 are bindings. That is to say, the library handles escaping them (Go's pq package is a Go wrapper around the pure Postgres libpq library), and should prevent SQL Injection. They bind (that is, connect to) the arguments that are subsequently passed.

    e.g. $1 maps to "orange" and $2 maps to 64.

    The references to %s in your original queries, in contrast, are directly formatted -- meaning there is no Postgres-based (libpq) escaping, and as such, no protection from SQL Injection. The values are simply passed right on through.

    More detail on Go formatting.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 运筹学中在线排序的时间在线排序的在线LPT算法
  • ¥30 求一段fortran代码用IVF编译运行的结果
  • ¥15 深度学习根据CNN网络模型,搭建BP模型并训练MNIST数据集
  • ¥15 lammps拉伸应力应变曲线分析
  • ¥15 C++ 头文件/宏冲突问题解决
  • ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
  • ¥50 安卓adb backup备份子用户应用数据失败
  • ¥20 有人能用聚类分析帮我分析一下文本内容嘛
  • ¥15 请问Lammps做复合材料拉伸模拟,应力应变曲线问题
  • ¥30 python代码,帮调试,帮帮忙吧