Perl:如何为通过 ajax/json 传递的 DBIx::Class 查询信息包含标量引用
Perl: How to include scalar reference for DBIx::Class query information passed with ajax/json
我有一个查询要从 jquery/ajax/json 传递到将使用 DBIx::Class 和 return 结果执行的 perl 脚本。我可以让基本查询正常工作,但是当我必须包含标量引用时 运行 遇到了麻烦。我对我在这里所做的所有概念的理解有点松散,所以请原谅任何不准确的地方。
这里是我定义传递给 perl 脚本的查询参数的地方:
var jsonData = $.ajax({
url: 'cgi-bin/getdata.cgi',
data: JSON.stringify({
table: 'Processes',
search: {
query_server:'SERVER1',
query_time: {
'>=':'now() - INTERVAL 1 DAY'
}
},
attrib: {
select: [
'query_time',
{avg:'bytes_processed'}
],
order_by: 'query_time',
group_by: 'query_time'
}
}),
contentType: "application/json",
dataType: 'json',
method: 'POST',
async: false
}).responseText;
这是 perl 脚本的一部分,它读取标准输入,从 json 转换并运行查询:
while ( <STDIN> )
{
$json .= $_;
}
my $query = from_json($json);
my $table = $query->{'table'};
my $search = $query->{'search'};
my $attrib= $query->{'attrib'};
print "Table:\n" . Dumper($table) . "\n";
print "Search:\n" . Dumper($search) . "\n";
print "Attrib:\n" . Dumper($attrib) . "\n";
my $retSet = $schema->resultset($table)->search( $search, $attrib );
my $retRow = $retSet->next;
这是我得到的输出(启用 DBIC_TRACE):
Table:
$VAR1 = 'Processes';
Search:
$VAR1 = {
'query_time' => {
'>=' => 'now() - INTERVAL 1 DAY'
},
'query_server' => 'SERVER1'
};
Attrib:
$VAR1 = {
'order_by' => 'query_time',
'group_by' => 'query_time',
'select' => [
'query_time',
{
'avg' => 'bytes_processed'
}
]
};
SELECT me.query_time, AVG( bytes_processed ) FROM processes me WHERE ( ( query_server = ? AND query_time >= ? ) ) GROUP BY query_time ORDER BY query_time: 'TSMCORP6', 'now() - INTERVAL 1 DAY'
问题是 'now() - INTERVAL 1 DAY'
值需要是标量引用才能正确执行查询。如果我在 perl 脚本中构建查询(而不是从 html 文件传递),如下所示:
my $search = {
query_server => 'SERVER1',
query_time => {
'>=' => \'now() - INTERVAL 1 DAY'
}
};
然后搜索数据看起来像这样并按照我想要的方式执行:
Search:
$VAR1 = {
'query_time' => {
'>=' => \'now() - INTERVAL 1 DAY'
},
'query_server' => 'SERVER1'
};
...
SELECT me.query_time, AVG( bytes_processed ) FROM processes me WHERE ( ( query_server = ? AND query_time >= now() - INTERVAL 1 DAY ) ) GROUP BY query_time ORDER BY query_time: 'TSMCORP6'
根据我的理解,我认为将值作为引用传递没有任何意义,所以我试图了解如何在 perl 脚本中 "convert" 它。我试过在 from_json
处理之前加入反斜杠,但这没有用。非常感谢您的帮助!
更新:我能够使用以下代码将值转换为引用。但是,这行得通,因为我知道需要将什么值转换为引用。在正常情况下,该值可以在数据结构中的任何位置。我可以用 !ref!
之类的东西标记该值,然后搜索整个数据结构并转换我找到的每一个吗?那看起来怎么样?
my $cond = $query->{'search'}->{'query_time'}->{'>='};
$query->{'search'}->{'query_time'}->{'>='}=$cond;
问题是 JSON 没有任何内容可以清楚地映射到引用类型,因为它只是数据。但是,我认为您在预处理传入数据并将文字 SQL 转换为 DBIC 期望的引用方面走在了正确的轨道上。在发送方,您可以向需要特殊处理的对象添加一个 literal_sql
标志,然后您可以使用 filter_json_object
找到那些键,删除它们,并创建标量字符串引用。
use strict;
use warnings;
use Data::Dump;
use JSON;
my $json = <<'EOF';
{
"table": "Processes",
"search": {
"query_server": "SERVER1",
"query_time": {
">=": "now() - INTERVAL 1 DAY",
"literal_sql": true
}
},
"attrib": {
"select": [
"query_time", {
"avg": "bytes_processed"
}
],
"order_by": "query_time",
"group_by": "query_time"
}
}
EOF
my $query = JSON
->new
->filter_json_object (sub {
my $obj = shift;
return unless $obj->{literal_sql};
delete($obj->{literal_sql});
my ($key, $val) = each(%$obj);
$obj->{$key} = \"$val";
return $obj;
})
->decode($json);
dd($query);
输出:
{
attrib => {
group_by => "query_time",
order_by => "query_time",
select => ["query_time", { avg => "bytes_processed" }],
},
search => {
query_server => "SERVER1",
query_time => { ">=" => \"now() - INTERVAL 1 DAY" },
},
table => "Processes",
}
我有一个查询要从 jquery/ajax/json 传递到将使用 DBIx::Class 和 return 结果执行的 perl 脚本。我可以让基本查询正常工作,但是当我必须包含标量引用时 运行 遇到了麻烦。我对我在这里所做的所有概念的理解有点松散,所以请原谅任何不准确的地方。
这里是我定义传递给 perl 脚本的查询参数的地方:
var jsonData = $.ajax({
url: 'cgi-bin/getdata.cgi',
data: JSON.stringify({
table: 'Processes',
search: {
query_server:'SERVER1',
query_time: {
'>=':'now() - INTERVAL 1 DAY'
}
},
attrib: {
select: [
'query_time',
{avg:'bytes_processed'}
],
order_by: 'query_time',
group_by: 'query_time'
}
}),
contentType: "application/json",
dataType: 'json',
method: 'POST',
async: false
}).responseText;
这是 perl 脚本的一部分,它读取标准输入,从 json 转换并运行查询:
while ( <STDIN> )
{
$json .= $_;
}
my $query = from_json($json);
my $table = $query->{'table'};
my $search = $query->{'search'};
my $attrib= $query->{'attrib'};
print "Table:\n" . Dumper($table) . "\n";
print "Search:\n" . Dumper($search) . "\n";
print "Attrib:\n" . Dumper($attrib) . "\n";
my $retSet = $schema->resultset($table)->search( $search, $attrib );
my $retRow = $retSet->next;
这是我得到的输出(启用 DBIC_TRACE):
Table:
$VAR1 = 'Processes';
Search:
$VAR1 = {
'query_time' => {
'>=' => 'now() - INTERVAL 1 DAY'
},
'query_server' => 'SERVER1'
};
Attrib:
$VAR1 = {
'order_by' => 'query_time',
'group_by' => 'query_time',
'select' => [
'query_time',
{
'avg' => 'bytes_processed'
}
]
};
SELECT me.query_time, AVG( bytes_processed ) FROM processes me WHERE ( ( query_server = ? AND query_time >= ? ) ) GROUP BY query_time ORDER BY query_time: 'TSMCORP6', 'now() - INTERVAL 1 DAY'
问题是 'now() - INTERVAL 1 DAY'
值需要是标量引用才能正确执行查询。如果我在 perl 脚本中构建查询(而不是从 html 文件传递),如下所示:
my $search = {
query_server => 'SERVER1',
query_time => {
'>=' => \'now() - INTERVAL 1 DAY'
}
};
然后搜索数据看起来像这样并按照我想要的方式执行:
Search:
$VAR1 = {
'query_time' => {
'>=' => \'now() - INTERVAL 1 DAY'
},
'query_server' => 'SERVER1'
};
...
SELECT me.query_time, AVG( bytes_processed ) FROM processes me WHERE ( ( query_server = ? AND query_time >= now() - INTERVAL 1 DAY ) ) GROUP BY query_time ORDER BY query_time: 'TSMCORP6'
根据我的理解,我认为将值作为引用传递没有任何意义,所以我试图了解如何在 perl 脚本中 "convert" 它。我试过在 from_json
处理之前加入反斜杠,但这没有用。非常感谢您的帮助!
更新:我能够使用以下代码将值转换为引用。但是,这行得通,因为我知道需要将什么值转换为引用。在正常情况下,该值可以在数据结构中的任何位置。我可以用 !ref!
之类的东西标记该值,然后搜索整个数据结构并转换我找到的每一个吗?那看起来怎么样?
my $cond = $query->{'search'}->{'query_time'}->{'>='};
$query->{'search'}->{'query_time'}->{'>='}=$cond;
问题是 JSON 没有任何内容可以清楚地映射到引用类型,因为它只是数据。但是,我认为您在预处理传入数据并将文字 SQL 转换为 DBIC 期望的引用方面走在了正确的轨道上。在发送方,您可以向需要特殊处理的对象添加一个 literal_sql
标志,然后您可以使用 filter_json_object
找到那些键,删除它们,并创建标量字符串引用。
use strict;
use warnings;
use Data::Dump;
use JSON;
my $json = <<'EOF';
{
"table": "Processes",
"search": {
"query_server": "SERVER1",
"query_time": {
">=": "now() - INTERVAL 1 DAY",
"literal_sql": true
}
},
"attrib": {
"select": [
"query_time", {
"avg": "bytes_processed"
}
],
"order_by": "query_time",
"group_by": "query_time"
}
}
EOF
my $query = JSON
->new
->filter_json_object (sub {
my $obj = shift;
return unless $obj->{literal_sql};
delete($obj->{literal_sql});
my ($key, $val) = each(%$obj);
$obj->{$key} = \"$val";
return $obj;
})
->decode($json);
dd($query);
输出:
{
attrib => {
group_by => "query_time",
order_by => "query_time",
select => ["query_time", { avg => "bytes_processed" }],
},
search => {
query_server => "SERVER1",
query_time => { ">=" => \"now() - INTERVAL 1 DAY" },
},
table => "Processes",
}