【问题标题】:Order by query using dart and postresql使用 dart 和 postgresql 按查询排序
【发布时间】:2015-05-13 22:50:02
【问题描述】:

使用 dart 和 postresql 驱动程序运行此查询时

  getPost(int limit, int offset, String order_by){
    connect(uri).then((conn){
      conn.query('''select * from posts
                    order by @order_by
                    limit @limit offset @offset''', {'limit': limit, 'offset': offset, 'order_by': order_by})
                    .toList()
                    .then((rows){
        print(rows);
      })
      .whenComplete(() => conn.close());
    })
    .catchError((err) => print('Error in getPost: $err'));
  }

我收到了Error: 42601 non-integer constant in ORDER BY

上面的代码是一个辅助类的方法。我使用以下代码运行它。

dbUtil.getPost(10, 10, "posted_at");

我读到here postgresql 需要一个字符串文字。这就是为什么我也尝试了这个代码dbUtil.getPost(10, 10, r"posted_at");,但没有成功。 如果我将@order_by 替换为posted_at,则查询会正确返回值。

有人知道如何解决这个问题吗?

受以下答案启发的工作代码。

  getPost(int limit, int offset, String order_by){
    connect(uri).then((conn){
      var sb = new StringBuffer();
      sb.write("select * from posts ");
      sb.write(order_by);
      sb.write(" limit @limit offset @offset"); 
      String query = sb.toString();
      conn.query(query, {'limit': limit, 'offset': offset})
                    .toList()
                    .then((rows){
        print(rows);
      })
      .whenComplete(() => conn.close());
    })
    .catchError((err) => print('Error in getPost: $err'));
  }

【问题讨论】:

  • 我在我的回答中添加了一个更大胆的例子。您也没有连接期货(缺少回报)。我没有在我的示例中更改这一点,因为我不知道意图。
  • 我认为您不需要使用 StringBuffer 来构建查询。我相信第一个示例中的错误是您在传递给 query() 的映射中缺少 order_by 参数。这可能会导致将 null 替换到您的查询中,从而导致奇怪的错误消息。尝试在您的数据库上打开查询日志记录,然后您将能够看到查询的确切文本。
  • 不幸的是,您确实需要以某种方式构建字符串。我的代码没有丢失'order_by': order_by 部分。我只是错误地将其插入问题中。
  • @GregLowe 我修复了代码,使其看起来像以前那样。顺便问一下,您对bounty 感兴趣吗?
  • 感谢您的提议。 ;) 但没必要。

标签: postgresql dart


【解决方案1】:

我认为 SQL 标准不支持将绑定变量用于列名(表名、索引名等)。这些名称需要在 SQL 语句中使用例如字符串连接或插值进行硬编码。

但请确保您不要在此处使用来自用户输入的任何值和/或进行适当的验证和健全性检查,以免引入任何 SQL 注入后门。

PostgreSql 包不处理您传递执行的 SQL,它仅将其以所需格式转发到数据库并解析结果(目前不正确,但它应该以这种方式工作,请参阅下面的评论)。

一个例子:

bool isValidSqlColumnName(String columnName) {
  return new RegExp(r'^[a-zA-Z_][a-zA-Z0-9_]*$').hasMatch(columnName);
}

getPost(int limit, int offset, String order_by){
    if(!isValidSqlColumnName(order_by)) {
      throw 'Only valid column names are accepted.';
    }
    connect(uri).then((conn){
      conn.query('''select * from posts
                    order by $order_by
                    limit @limit offset @offset''', {'limit': limit, 'offset': offset, 'order_by': order_by})
                    .toList()
                    .then((rows){
        print(rows);
      })
      .whenComplete(() => conn.close());
    })
    .catchError((err) => print('Error in getPost: $err'));
  }

【讨论】:

  • 目前 postgresql 包只使用简单查询协议,这意味着所有的参数替换都由客户端在驱动程序中完成,并将原始 sql 字符串发送到服务器。因此,您实际上可以使用@order_by 替换 order_by(我认为错误是 Lukasz 忘记将其添加到传递给 query() 的映射中)。当我开始实施更多的 postgresql 协议时,这种情况会有所改变。
  • 我想最好不要提及它,因为那将是一个重大变化;-)
  • 好点。但是,语法也会有所不同,postgresql 使用 $ 美元符号,而我的驱动程序使用 @ 符号。虽然我想我可以写一个向后兼容的翻译模式。
猜你喜欢
  • 1970-01-01
  • 2019-01-08
  • 1970-01-01
  • 2021-03-30
  • 2018-11-11
  • 1970-01-01
  • 1970-01-01
  • 2016-09-26
  • 1970-01-01
相关资源
最近更新 更多