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 使用C#,asp.net读取Excel文件并保存到Oracle数据库
  • ¥15 C# datagridview 单元格显示进度及值
  • ¥15 thinkphp6配合social login单点登录问题
  • ¥15 HFSS 中的 H 场图与 MATLAB 中绘制的 B1 场 部分对应不上
  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 虚心请教几个问题,小生先有礼了
  • ¥30 截图中的mathematics程序转换成matlab