使用 dart 和 postgresql 按查询排序

Order by query using dart and postresql

当运行使用 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.

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

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

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

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

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

  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'));
  }

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

但请确保您不使用此处用户输入的任何值 and/or 进行适当的验证和健全性检查,以免引入任何 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'));
  }