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

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 请问一下这个运行结果是怎么来的
  • ¥15 这个复选框什么作用?
  • ¥15 单通道放大电路的工作原理
  • ¥30 YOLO检测微调结果p为1
  • ¥20 求快手直播间榜单匿名采集ID用户名简单能学会的
  • ¥15 DS18B20内部ADC模数转换器
  • ¥15 做个有关计算的小程序
  • ¥15 MPI读取tif文件无法正常给各进程分配路径
  • ¥15 如何用MATLAB实现以下三个公式(有相互嵌套)
  • ¥30 关于#算法#的问题:运用EViews第九版本进行一系列计量经济学的时间数列数据回归分析预测问题 求各位帮我解答一下