重整cgi-bin文件目录,库文件添加进项目相对位置,避免环境变量不同引起编译失败; 增加mqtt_sub_ctos,用于从MQTT服务器订阅并接收传感器数据

This commit is contained in:
flykhan 2023-10-25 17:34:40 +08:00
parent fc2fdc3b6b
commit 519318dd1a
16 changed files with 2480 additions and 5 deletions

View File

@ -1,7 +1,23 @@
cc = gcc
# CFLAGS = -Wall -g
MQTT_CFLAGS = -lmosquitto -lpthread -ldl
MQTT_CFLAGS += -I./includes
MQTT_CFLAGS += -L./mqtt_libs
SQLITE3_CFLAGS = -lpthread -ldl -lcjson
SQLITE3_CFLAGS += -I./includes
all: all:
sqlite_cgi_base: sqlite_cgi_base:
gcc sqlite3.c sqlite_cgi_base.c -o sqlite_cgi_base.cgi -lpthread -ldl -lcjson $(cc) sqlite3.c sqlite_cgi_base.c -o sqlite_cgi_base.cgi $(SQLITE3_CFLAGS)
sqlite_cgi_insert_base:
$(cc) sqlite3.c sqlite_cgi_insert_base.c -o sqlite_cgi_insert_base.cgi $(SQLITE3_CFLAGS)
mqtt_sub_ctos:
$(cc) mqtt_sub_ctos.c -o mqtt_sub_ctos.cgi $(MQTT_CFLAGS)
clean: clean:
rm -rf *.cgi rm -rf *.cgi

1772
cgi-bin/includes/mosquitto.h Executable file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,144 @@
/*
Copyright (c) 2009-2018 Roger Light <roger@atchoo.org>
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Roger Light - initial implementation and documentation.
*/
#ifndef MOSQUITTO_BROKER_H
#define MOSQUITTO_BROKER_H
#include <stdbool.h>
struct mosquitto;
enum mosquitto_protocol {
mp_mqtt,
mp_mqttsn,
mp_websockets
};
/* =========================================================================
*
* Utility Functions
*
* Use these functions from within your plugin.
*
* There are also very useful functions in libmosquitto.
*
* ========================================================================= */
/*
* Function: mosquitto_log_printf
*
* Write a log message using the broker configured logging.
*
* Parameters:
* level - Log message priority. Can currently be one of:
*
* MOSQ_LOG_INFO
* MOSQ_LOG_NOTICE
* MOSQ_LOG_WARNING
* MOSQ_LOG_ERR
* MOSQ_LOG_DEBUG
* MOSQ_LOG_SUBSCRIBE (not recommended for use by plugins)
* MOSQ_LOG_UNSUBSCRIBE (not recommended for use by plugins)
*
* These values are defined in mosquitto.h.
*
* fmt, ... - printf style format and arguments.
*/
void mosquitto_log_printf(int level, const char *fmt, ...);
/* =========================================================================
*
* Client Functions
*
* Use these functions to access client information.
*
* ========================================================================= */
/*
* Function: mosquitto_client_address
*
* Retrieve the IP address of the client as a string.
*/
const char *mosquitto_client_address(const struct mosquitto *client);
/*
* Function: mosquitto_client_clean_session
*
* Retrieve the clean session flag value for a client.
*/
bool mosquitto_client_clean_session(const struct mosquitto *client);
/*
* Function: mosquitto_client_id
*
* Retrieve the client id associated with a client.
*/
const char *mosquitto_client_id(const struct mosquitto *client);
/*
* Function: mosquitto_client_keepalive
*
* Retrieve the keepalive value for a client.
*/
int mosquitto_client_keepalive(const struct mosquitto *client);
/*
* Function: mosquitto_client_certificate
*
* If TLS support is enabled, return the certificate provided by a client as an
* X509 pointer from openssl. If the client did not provide a certificate, then
* NULL will be returned. This function will only ever return a non-NULL value
* if the `require_certificate` option is set to true.
*
* If TLS is not supported, this function will always return NULL.
*/
void *mosquitto_client_certificate(const struct mosquitto *client);
/*
* Function: mosquitto_client_protocol
*
* Retrieve the protocol with which the client has connected. Can be one of:
*
* mp_mqtt (MQTT over TCP)
* mp_mqttsn (MQTT-SN)
* mp_websockets (MQTT over Websockets)
*/
int mosquitto_client_protocol(const struct mosquitto *client);
/*
* Function: mosquitto_client_sub_count
*
* Retrieve the number of subscriptions that have been made by a client.
*/
int mosquitto_client_sub_count(const struct mosquitto *client);
/*
* Function: mosquitto_client_username
*
* Retrieve the username associated with a client.
*/
const char *mosquitto_client_username(const struct mosquitto *client);
#endif

View File

@ -0,0 +1,264 @@
/*
Copyright (c) 2012-2018 Roger Light <roger@atchoo.org>
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Roger Light - initial implementation and documentation.
*/
#ifndef MOSQUITTO_PLUGIN_H
#define MOSQUITTO_PLUGIN_H
#define MOSQ_AUTH_PLUGIN_VERSION 3
#define MOSQ_ACL_NONE 0x00
#define MOSQ_ACL_READ 0x01
#define MOSQ_ACL_WRITE 0x02
#define MOSQ_ACL_SUBSCRIBE 0x04
#include <stdbool.h>
struct mosquitto;
struct mosquitto_opt {
char *key;
char *value;
};
struct mosquitto_auth_opt {
char *key;
char *value;
};
struct mosquitto_acl_msg {
const char *topic;
const void *payload;
long payloadlen;
int qos;
bool retain;
};
/*
* To create an authentication plugin you must include this file then implement
* the functions listed in the "Plugin Functions" section below. The resulting
* code should then be compiled as a shared library. Using gcc this can be
* achieved as follows:
*
* gcc -I<path to mosquitto_plugin.h> -fPIC -shared plugin.c -o plugin.so
*
* On Mac OS X:
*
* gcc -I<path to mosquitto_plugin.h> -fPIC -shared plugin.c -undefined dynamic_lookup -o plugin.so
*
* Authentication plugins can implement one or both of authentication and
* access control. If your plugin does not wish to handle either of
* authentication or access control it should return MOSQ_ERR_PLUGIN_DEFER. In
* this case, the next plugin will handle it. If all plugins return
* MOSQ_ERR_PLUGIN_DEFER, the request will be denied.
*
* For each check, the following flow happens:
*
* * The default password file and/or acl file checks are made. If either one
* of these is not defined, then they are considered to be deferred. If either
* one accepts the check, no further checks are made. If an error occurs, the
* check is denied
* * The first plugin does the check, if it returns anything other than
* MOSQ_ERR_PLUGIN_DEFER, then the check returns immediately. If the plugin
* returns MOSQ_ERR_PLUGIN_DEFER then the next plugin runs its check.
* * If the final plugin returns MOSQ_ERR_PLUGIN_DEFER, then access will be
* denied.
*/
/* =========================================================================
*
* Plugin Functions
*
* You must implement these functions in your plugin.
*
* ========================================================================= */
/*
* Function: mosquitto_auth_plugin_version
*
* The broker will call this function immediately after loading the plugin to
* check it is a supported plugin version. Your code must simply return
* MOSQ_AUTH_PLUGIN_VERSION.
*/
int mosquitto_auth_plugin_version(void);
/*
* Function: mosquitto_auth_plugin_init
*
* Called after the plugin has been loaded and <mosquitto_auth_plugin_version>
* has been called. This will only ever be called once and can be used to
* initialise the plugin.
*
* Parameters:
*
* user_data : The pointer set here will be passed to the other plugin
* functions. Use to hold connection information for example.
* opts : Pointer to an array of struct mosquitto_opt, which
* provides the plugin options defined in the configuration file.
* opt_count : The number of elements in the opts array.
*
* Return value:
* Return 0 on success
* Return >0 on failure.
*/
int mosquitto_auth_plugin_init(void **user_data, struct mosquitto_opt *opts, int opt_count);
/*
* Function: mosquitto_auth_plugin_cleanup
*
* Called when the broker is shutting down. This will only ever be called once
* per plugin.
* Note that <mosquitto_auth_security_cleanup> will be called directly before
* this function.
*
* Parameters:
*
* user_data : The pointer provided in <mosquitto_auth_plugin_init>.
* opts : Pointer to an array of struct mosquitto_opt, which
* provides the plugin options defined in the configuration file.
* opt_count : The number of elements in the opts array.
*
* Return value:
* Return 0 on success
* Return >0 on failure.
*/
int mosquitto_auth_plugin_cleanup(void *user_data, struct mosquitto_opt *opts, int opt_count);
/*
* Function: mosquitto_auth_security_init
*
* This function is called in two scenarios:
*
* 1. When the broker starts up.
* 2. If the broker is requested to reload its configuration whilst running. In
* this case, <mosquitto_auth_security_cleanup> will be called first, then
* this function will be called. In this situation, the reload parameter
* will be true.
*
* Parameters:
*
* user_data : The pointer provided in <mosquitto_auth_plugin_init>.
* opts : Pointer to an array of struct mosquitto_opt, which
* provides the plugin options defined in the configuration file.
* opt_count : The number of elements in the opts array.
* reload : If set to false, this is the first time the function has
* been called. If true, the broker has received a signal
* asking to reload its configuration.
*
* Return value:
* Return 0 on success
* Return >0 on failure.
*/
int mosquitto_auth_security_init(void *user_data, struct mosquitto_opt *opts, int opt_count, bool reload);
/*
* Function: mosquitto_auth_security_cleanup
*
* This function is called in two scenarios:
*
* 1. When the broker is shutting down.
* 2. If the broker is requested to reload its configuration whilst running. In
* this case, this function will be called, followed by
* <mosquitto_auth_security_init>. In this situation, the reload parameter
* will be true.
*
* Parameters:
*
* user_data : The pointer provided in <mosquitto_auth_plugin_init>.
* opts : Pointer to an array of struct mosquitto_opt, which
* provides the plugin options defined in the configuration file.
* opt_count : The number of elements in the opts array.
* reload : If set to false, this is the first time the function has
* been called. If true, the broker has received a signal
* asking to reload its configuration.
*
* Return value:
* Return 0 on success
* Return >0 on failure.
*/
int mosquitto_auth_security_cleanup(void *user_data, struct mosquitto_opt *opts, int opt_count, bool reload);
/*
* Function: mosquitto_auth_acl_check
*
* Called by the broker when topic access must be checked. access will be one
* of:
* MOSQ_ACL_SUBSCRIBE when a client is asking to subscribe to a topic string.
* This differs from MOSQ_ACL_READ in that it allows you to
* deny access to topic strings rather than by pattern. For
* example, you may use MOSQ_ACL_SUBSCRIBE to deny
* subscriptions to '#', but allow all topics in
* MOSQ_ACL_READ. This allows clients to subscribe to any
* topic they want, but not discover what topics are in use
* on the server.
* MOSQ_ACL_READ when a message is about to be sent to a client (i.e. whether
* it can read that topic or not).
* MOSQ_ACL_WRITE when a message has been received from a client (i.e. whether
* it can write to that topic or not).
*
* Return:
* MOSQ_ERR_SUCCESS if access was granted.
* MOSQ_ERR_ACL_DENIED if access was not granted.
* MOSQ_ERR_UNKNOWN for an application specific error.
* MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check.
*/
int mosquitto_auth_acl_check(void *user_data, int access, const struct mosquitto *client, const struct mosquitto_acl_msg *msg);
/*
* Function: mosquitto_auth_unpwd_check
*
* Called by the broker when a username/password must be checked.
*
* Return:
* MOSQ_ERR_SUCCESS if the user is authenticated.
* MOSQ_ERR_AUTH if authentication failed.
* MOSQ_ERR_UNKNOWN for an application specific error.
* MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check.
*/
int mosquitto_auth_unpwd_check(void *user_data, const struct mosquitto *client, const char *username, const char *password);
/*
* Function: mosquitto_psk_key_get
*
* Called by the broker when a client connects to a listener using TLS/PSK.
* This is used to retrieve the pre-shared-key associated with a client
* identity.
*
* Examine hint and identity to determine the required PSK (which must be a
* hexadecimal string with no leading "0x") and copy this string into key.
*
* Parameters:
* user_data : the pointer provided in <mosquitto_auth_plugin_init>.
* hint : the psk_hint for the listener the client is connecting to.
* identity : the identity string provided by the client
* key : a string where the hex PSK should be copied
* max_key_len : the size of key
*
* Return value:
* Return 0 on success.
* Return >0 on failure.
* Return MOSQ_ERR_PLUGIN_DEFER if your plugin does not wish to handle this check.
*/
int mosquitto_auth_psk_key_get(void *user_data, const struct mosquitto *client, const char *hint, const char *identity, char *key, int max_key_len);
#endif

139
cgi-bin/includes/mosquittopp.h Executable file
View File

@ -0,0 +1,139 @@
/*
Copyright (c) 2010-2018 Roger Light <roger@atchoo.org>
All rights reserved. This program and the accompanying materials
are made available under the terms of the Eclipse Public License v1.0
and Eclipse Distribution License v1.0 which accompany this distribution.
The Eclipse Public License is available at
http://www.eclipse.org/legal/epl-v10.html
and the Eclipse Distribution License is available at
http://www.eclipse.org/org/documents/edl-v10.php.
Contributors:
Roger Light - initial implementation and documentation.
*/
#ifndef MOSQUITTOPP_H
#define MOSQUITTOPP_H
#ifdef _WIN32
# ifdef mosquittopp_EXPORTS
# define mosqpp_EXPORT __declspec(dllexport)
# else
# define mosqpp_EXPORT __declspec(dllimport)
# endif
#else
# define mosqpp_EXPORT
#endif
#include <cstdlib>
#include <mosquitto.h>
#include <time.h>
namespace mosqpp {
mosqpp_EXPORT const char *strerror(int mosq_errno);
mosqpp_EXPORT const char *connack_string(int connack_code);
mosqpp_EXPORT int sub_topic_tokenise(const char *subtopic, char ***topics, int *count);
mosqpp_EXPORT int sub_topic_tokens_free(char ***topics, int count);
mosqpp_EXPORT int lib_version(int *major, int *minor, int *revision);
mosqpp_EXPORT int lib_init();
mosqpp_EXPORT int lib_cleanup();
mosqpp_EXPORT int topic_matches_sub(const char *sub, const char *topic, bool *result);
mosqpp_EXPORT int validate_utf8(const char *str, int len);
mosqpp_EXPORT int subscribe_simple(
struct mosquitto_message **messages,
int msg_count,
bool retained,
const char *topic,
int qos=0,
const char *host="localhost",
int port=1883,
const char *client_id=NULL,
int keepalive=60,
bool clean_session=true,
const char *username=NULL,
const char *password=NULL,
const struct libmosquitto_will *will=NULL,
const struct libmosquitto_tls *tls=NULL);
mosqpp_EXPORT int subscribe_callback(
int (*callback)(struct mosquitto *, void *, const struct mosquitto_message *),
void *userdata,
const char *topic,
int qos=0,
bool retained=true,
const char *host="localhost",
int port=1883,
const char *client_id=NULL,
int keepalive=60,
bool clean_session=true,
const char *username=NULL,
const char *password=NULL,
const struct libmosquitto_will *will=NULL,
const struct libmosquitto_tls *tls=NULL);
/*
* Class: mosquittopp
*
* A mosquitto client class. This is a C++ wrapper class for the mosquitto C
* library. Please see mosquitto.h for details of the functions.
*/
class mosqpp_EXPORT mosquittopp {
private:
struct mosquitto *m_mosq;
public:
mosquittopp(const char *id=NULL, bool clean_session=true);
virtual ~mosquittopp();
int reinitialise(const char *id, bool clean_session);
int socket();
int will_set(const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false);
int will_clear();
int username_pw_set(const char *username, const char *password=NULL);
int connect(const char *host, int port=1883, int keepalive=60);
int connect_async(const char *host, int port=1883, int keepalive=60);
int connect(const char *host, int port, int keepalive, const char *bind_address);
int connect_async(const char *host, int port, int keepalive, const char *bind_address);
int reconnect();
int reconnect_async();
int disconnect();
int publish(int *mid, const char *topic, int payloadlen=0, const void *payload=NULL, int qos=0, bool retain=false);
int subscribe(int *mid, const char *sub, int qos=0);
int unsubscribe(int *mid, const char *sub);
void reconnect_delay_set(unsigned int reconnect_delay, unsigned int reconnect_delay_max, bool reconnect_exponential_backoff);
int max_inflight_messages_set(unsigned int max_inflight_messages);
void message_retry_set(unsigned int message_retry);
void user_data_set(void *userdata);
int tls_set(const char *cafile, const char *capath=NULL, const char *certfile=NULL, const char *keyfile=NULL, int (*pw_callback)(char *buf, int size, int rwflag, void *userdata)=NULL);
int tls_opts_set(int cert_reqs, const char *tls_version=NULL, const char *ciphers=NULL);
int tls_insecure_set(bool value);
int tls_psk_set(const char *psk, const char *identity, const char *ciphers=NULL);
int opts_set(enum mosq_opt_t option, void *value);
int loop(int timeout=-1, int max_packets=1);
int loop_misc();
int loop_read(int max_packets=1);
int loop_write(int max_packets=1);
int loop_forever(int timeout=-1, int max_packets=1);
int loop_start();
int loop_stop(bool force=false);
bool want_write();
int threaded_set(bool threaded=true);
int socks5_set(const char *host, int port=1080, const char *username=NULL, const char *password=NULL);
// names in the functions commented to prevent unused parameter warning
virtual void on_connect(int /*rc*/) {return;}
virtual void on_connect_with_flags(int /*rc*/, int /*flags*/) {return;}
virtual void on_disconnect(int /*rc*/) {return;}
virtual void on_publish(int /*mid*/) {return;}
virtual void on_message(const struct mosquitto_message * /*message*/) {return;}
virtual void on_subscribe(int /*mid*/, int /*qos_count*/, const int * /*granted_qos*/) {return;}
virtual void on_unsubscribe(int /*mid*/) {return;}
virtual void on_log(int /*level*/, const char * /*str*/) {return;}
virtual void on_error() {return;}
};
}
#endif

View File

@ -0,0 +1 @@
libmosquitto.so.1

Binary file not shown.

View File

@ -0,0 +1 @@
libmosquittopp.so.1

Binary file not shown.

View File

@ -0,0 +1,10 @@
prefix=/opt/mqtt/mosquitto
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib
Name: mosquitto
Description: mosquitto MQTT library (C bindings)
Version: 1.5.4
Cflags: -I${includedir}
Libs: -L${libdir} -lmosquitto

View File

@ -0,0 +1,10 @@
prefix=/opt/mqtt/mosquitto
exec_prefix=${prefix}
includedir=${prefix}/include
libdir=${exec_prefix}/lib
Name: mosquittopp
Description: mosquitto MQTT library (C++ bindings)
Version: 1.5.4
Cflags: -I${includedir}
Libs: -L${libdir} -lmosquittopp

119
cgi-bin/mqtt_sub_ctos.c Normal file
View File

@ -0,0 +1,119 @@
/*
MQTT
CG
sqlite3
ctos MQTT
*/
#include "includes/mosquitto.h" // MQTT 的头文件
#include <pthread.h>
#include <signal.h>
#include <stdbool.h> // bool 类型
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <cjson/cJSON.h> // cJSON 的头文件
#include "includes/sqlite3.h" // sqlite3 的头文件
struct mosquitto *client; // mosquitto 客户端
int isRunning = 1; // 线程运行标志
pthread_t main_th_id; // 主线程 ID
// sqlite3 连接的回调函数
void connect_callback(struct mosquitto *mosq, void *args, int rc)
{
if (rc == 0)
{
printf("连接MQTT服务成功!\n");
}
else
{
printf("连接MQTT服务失败!\n");
}
}
// sqlite3 订阅的回调函数
void on_subscribe(struct mosquitto *mosq,
void *obj,
int mid,
int qos_count,
const int *granted_qos)
{
printf("-订阅的消息ID为--%d 成功, Qos的granted: %d--\n", mid,
*granted_qos);
}
// sqlite3 接收消息的回调函数(处理接收到的消息,并将消息存入 sqlite3 数据库)
void on_message(struct mosquitto *mosq,
void *obj,
const struct mosquitto_message *message)
{
printf("收到%s(%d)的消息: %s\n", message->topic, message->mid,
(char *)message->payload);
if (strncmp((char *)message->payload, "exit", 4) == 0)
{
isRunning = 0;
mosquitto_loop_stop(client, true);
}
}
int main(int argc, char const *argv[])
{
main_th_id = pthread_self();
// 1. 初始化mosquitto的库环境
// 使用mosquitto库函数前要先初始化使用之后要清除。
mosquitto_lib_init(); // 初始化(固定格式)
// 2. 创建mosquitto的客户端
unsigned char userdata[128] = "1";
client = mosquitto_new("166", true, userdata); // 创建客户端句柄
// struct mosquitto* mosquitto_new(
// const char *id,//用户自定义标识ID
// bool clean_session, //断开后是否保留订阅信息true/false
// void *userdata //回调参数
// );
// d可以为NULLclean_session的标识必须是true, userdata也可以是NULL
if (client == NULL) // 创建失败
{
printf("创建mqtt客户端失败!\n");
perror("mosquitto_new\n");
return -1;
}
// 设置回调函数
mosquitto_connect_callback_set(client, connect_callback); // 设置连接回调函数,用于连接后的处理
mosquitto_subscribe_callback_set(client, on_subscribe); // 设置订阅回调函数,用于订阅后的处理
mosquitto_message_callback_set(client, on_message); // 设置接收消息回调函数,用于接收到消息后的处理
// 3. 连接mqtt broker
int flag = mosquitto_connect(client, "flykhan.com", 1883, 60);
if (flag == MOSQ_ERR_SUCCESS)
{
printf("-----连接MQTT 服务器成功!-----\n");
}
else
{
printf("-----连接MQTT 服务器失败!-----\n");
return -1;
}
int msgId = 1; // 消息ID
// 开始订阅信息
flag = mosquitto_subscribe(client, &msgId, "ctos", 0);
if (flag == MOSQ_ERR_SUCCESS)
{
printf("订阅消息ID: %d 成功, 等待消息!\n", msgId);
}
while (isRunning)
{
// 处理网络事件
mosquitto_loop_start(client); // 接收网络数据
// usleep(500);
}
// 关闭mosquitto的客户端
mosquitto_destroy(client);
// 最后清理库环境
mosquitto_lib_cleanup();
return 0;
}

View File

@ -43,6 +43,7 @@
#ifndef _SQLITEINT_H_ #ifndef _SQLITEINT_H_
#define _SQLITEINT_H_ #define _SQLITEINT_H_
/* /*
** These #defines should enable >2GB file support on POSIX if the ** These #defines should enable >2GB file support on POSIX if the
** underlying operating system supports it. If the OS lacks ** underlying operating system supports it. If the OS lacks

View File

@ -1,7 +1,6 @@
#include <cjson/cJSON.h> #include <cjson/cJSON.h>
#include <stdio.h> #include <stdio.h>
// #include "cJSON.h" #include "includes/sqlite3.h" // sqlite3 的头文件
#include "sqlite3.h"
#include <stdlib.h> #include <stdlib.h>
// cJSON *result_json; // 用于存储查询结果 // cJSON *result_json; // 用于存储查询结果

View File

@ -1,8 +1,7 @@
#include <cjson/cJSON.h> #include <cjson/cJSON.h>
#include <stdio.h> #include <stdio.h>
// #include "cJSON.h"
#include <stdlib.h> #include <stdlib.h>
#include "sqlite3.h" #include "includes/sqlite3.h"
// cJSON *result_json; // 用于存储查询结果 // cJSON *result_json; // 用于存储查询结果