IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> windows下mysql 自定义函数 之http 实操 -> 正文阅读

[网络协议]windows下mysql 自定义函数 之http 实操

有没有遇到这种场景呢,当使用mysql做复杂字符串处理的时候总感觉mysql内置的函数不够用呢。比如做字符串切割,解析xml等。而这个时候你恰恰对编写mysql函数或者存储过程缺乏一定的经验积累、而你擅长的可能是c/c++,java、c#或者其它编程语言。当然,你也可以把数据库中的数据加载到应用程序中去处理,然后利用应用程序灵活复杂的字符串处理函数实现功能。当然这也是可以的的,只不过注意力需要做切换,因为有的时候可能你想的是只对数据库操作就实现你的目标。再比如我想把现有mysql数据库中的数据同步到其它数据源如oracle。当然这种需求通过应用程序都是可以实现的 只不过始终要把数据库中的数据复制一份到应用程序,这时候应用程序其实扮演的也是临时数据库的角色,只不过这个临时数据库的存储介质是内存。数据库和应用程序其实没有本质上的区别。只不过数据库是相对固化的、当然如果你有兴趣去修改数据库的源码那也是可以的。数据库设计者也考虑到了拓展性的问题,所以有了用户定义函数(UDF)用来补充内置函数的不足。编写MYSQL UDF需要一定的c/c++基础。其它数据库也是充满了UDF的影子,比如oracle 因为它内置了java虚拟机所以可以直接利用java的语法去创建函数 这样的话明显在极大的程度上提高了数据库的数据处理能力。还有h2嵌入式数据库,因为它本身就是使用java来写的 所以它的UDF函数当然可以直接利用java了。如果我们脑洞够大实力够强的话,我们在Mysql里面其实可以集成一个java虚拟机然后用java语法去编写自定义函数。当然这里我们只简单对c/c++实现的http接口做个分析。http协议早已经成为一种标准,因为它可以跨语言跨平台。这样理论上我们使用任何语言编写的http接口都可以被mysql所利用了,当然执行效率又是另一方面的事情。

以下示例程序中使用mysql8作为测试对象,示例程序包含1个头文件和1个源代码文件,项目中需要引用curl的头文件和mysql8的头文件

mysql-udf-http.h

#include <curl/curl.h>
/* Common definitions for all functions */
#define CURL_UDF_MAX_SIZE 1024*1024

#define VERSION_STRING "1.0\n"
#define VERSION_STRING_LENGTH 4

typedef struct st_curl_results st_curl_results;
struct st_curl_results {
?? ?char *result;
?? ?size_t size;
};
#pragma once
?

main.c

#define _CRT_SECURE_NO_WARNINGS
#include <mysql.h>
#include <string.h>

#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
#include "mysql-udf-http.h"
#pragma comment(lib,"legacy_stdio_definitions.lib")

/*
?* 当libjpeg-turbo为vs2010编译时,vs2015下静态链接libjpeg-turbo会链接出错:找不到__iob_func,
?* 增加__iob_func到__acrt_iob_func的转换函数解决此问题,
?* 当libjpeg-turbo用vs2015编译时,不需要此补丁文件
?*/
#if _MSC_VER>=1900
#include "stdio.h"?
_ACRTIMP_ALT FILE* __cdecl __acrt_iob_func(unsigned);
#ifdef __cplusplus?
extern "C"
#endif?
FILE* __cdecl __iob_func(unsigned i) {
?? ?return __acrt_iob_func(i);
}
#endif /* _MSC_VER>=1900 */


_declspec(dllexport) BOOL http_get_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
_declspec(dllexport) char *http_get(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error);
_declspec(dllexport) void http_get_deinit(UDF_INIT *initid);

_declspec(dllexport) BOOL http_post_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
_declspec(dllexport) char *http_post(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error);
_declspec(dllexport) void http_post_deinit(UDF_INIT *initid);

_declspec(dllexport) BOOL http_put_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
_declspec(dllexport) char *http_put(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error);
_declspec(dllexport) void http_put_deinit(UDF_INIT *initid);

_declspec(dllexport) BOOL http_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message);
_declspec(dllexport) char *http_delete(UDF_INIT *initid, UDF_ARGS *args, char *result, unsigned long *length, char *is_null, char *error);
_declspec(dllexport) void http_delete_deinit(UDF_INIT *initid);

static void *myrealloc(void *ptr, size_t size)
{
?? ?/* There might be a realloc() out there that doesn't like reallocing
?? ? ? NULL pointers, so we take care of it here */
?? ?if (ptr)
?? ??? ?return realloc(ptr, size);
?? ?else
?? ??? ?return malloc(size);
}

static size_t
result_cb(void *ptr, size_t size, size_t nmemb, void *data)
{
?? ?size_t realsize = size * nmemb;
?? ?struct st_curl_results *res = (struct st_curl_results *)data;

?? ?res->result = (char *)myrealloc(res->result, res->size + realsize + 1);
?? ?if (res->result)
?? ?{
?? ??? ?memcpy(&(res->result[res->size]), ptr, realsize);
?? ??? ?res->size += realsize;
?? ??? ?res->result[res->size] = 0;
?? ?}
?? ?return realsize;
}

/* ------------------------HTTP GET----------------------------- */

BOOL http_get_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
?? ?st_curl_results *container;

?? ?if (args->arg_count != 1)
?? ?{
?? ??? ?strncpy(message,
?? ??? ??? ?"one argument must be supplied: http_get('<url>').",
?? ??? ??? ?MYSQL_ERRMSG_SIZE);
?? ??? ?return 1;
?? ?}

?? ?args->arg_type[0] = STRING_RESULT;

?? ?initid->max_length = CURL_UDF_MAX_SIZE;
?? ?container = (st_curl_results *)malloc(sizeof(st_curl_results));

?? ?initid->ptr = (char *)container;

?? ?return 0;
}

char *http_get(UDF_INIT *initid, UDF_ARGS *args,
?? ?char *result,
?? ?unsigned long *length,
?? ?char *is_null,
?? ?char *error)
{
?? ?CURLcode retref;
?? ?CURL *curl;
?? ?st_curl_results *res = (st_curl_results *)initid->ptr;

?? ?curl_global_init(CURL_GLOBAL_ALL);
?? ?curl = curl_easy_init();

?? ?res->result = NULL;
?? ?res->size = 0;

?? ?if (curl)
?? ?{
?? ??? ?curl_easy_setopt(curl, CURLOPT_URL, args->args[0]);
?? ??? ?curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, result_cb);
?? ??? ?curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)res);
?? ??? ?curl_easy_setopt(curl, CURLOPT_USERAGENT, "mysql-udf-http/1.0");
?? ??? ?retref = curl_easy_perform(curl);
?? ??? ?if (retref) {
?? ??? ??? ?fprintf(stderr, "error\n");
?? ??? ??? ?if (res->result)
?? ??? ??? ??? ?strcpy(res->result, "");
?? ??? ??? ?res->size = 0;
?? ??? ?}
?? ?}
?? ?curl_easy_cleanup(curl);
?? ?*length = res->size;
?? ?return ((char *)res->result);
}

void http_get_deinit(UDF_INIT *initid)
{
?? ?/* if we allocated initid->ptr, free it here */
?? ?st_curl_results *res = (st_curl_results *)initid->ptr;

?? ?if (res->result)
?? ??? ?free(res->result);
?? ?free(res);
?? ?return;
}

/* ------------------------HTTP POST----------------------------- */

BOOL http_post_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
?? ?st_curl_results *container;

?? ?if (args->arg_count != 2)
?? ?{
?? ??? ?strncpy(message,
?? ??? ??? ?"two arguments must be supplied: http_post('<url>','<data>').",
?? ??? ??? ?MYSQL_ERRMSG_SIZE);
?? ??? ?return 1;
?? ?}

?? ?args->arg_type[0] = STRING_RESULT;

?? ?initid->max_length = CURL_UDF_MAX_SIZE;
?? ?container = (st_curl_results *)malloc(sizeof(st_curl_results));

?? ?initid->ptr = (char *)container;

?? ?return 0;
}

char *http_post(UDF_INIT *initid, UDF_ARGS *args,
?? ?char *result,
?? ?unsigned long *length,
?? ? char *is_null,
?? ?char *error)
{
?? ?CURLcode retref;
?? ?CURL *curl;
?? ?st_curl_results *res = (st_curl_results *)initid->ptr;

?? ?curl_global_init(CURL_GLOBAL_ALL);
?? ?curl = curl_easy_init();

?? ?res->result = NULL;
?? ?res->size = 0;

?? ?if (curl)
?? ?{
?? ??? ?struct curl_slist *chunk = NULL;
?? ??? ?chunk = curl_slist_append(chunk, "Expect:");

?? ??? ?curl_easy_setopt(curl, CURLOPT_URL, args->args[0]);
?? ??? ?curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, result_cb);
?? ??? ?curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)res);
?? ??? ?curl_easy_setopt(curl, CURLOPT_USERAGENT, "mysql-udf-http/1.0");
?? ??? ?curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
?? ??? ?curl_easy_setopt(curl, CURLOPT_POSTFIELDS, args->args[1]);
?? ??? ?retref = curl_easy_perform(curl);
?? ??? ?if (retref) {
?? ??? ??? ?fprintf(stderr, "error\n");
?? ??? ??? ?if (res->result)
?? ??? ??? ??? ?strcpy(res->result, "");
?? ??? ??? ?res->size = 0;
?? ??? ?}
?? ?}
?? ?curl_easy_cleanup(curl);
?? ?*length = res->size;
?? ?return ((char *)res->result);
}

void http_post_deinit(UDF_INIT *initid)
{
?? ?/* if we allocated initid->ptr, free it here */
?? ?st_curl_results *res = (st_curl_results *)initid->ptr;

?? ?if (res->result)
?? ??? ?free(res->result);
?? ?free(res);
?? ?return;
}

/* ------------------------HTTP PUT----------------------------- */

BOOL http_put_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
?? ?st_curl_results *container;

?? ?if (args->arg_count != 2)
?? ?{
?? ??? ?strncpy(message,
?? ??? ??? ?"two arguments must be supplied: http_put('<url>','<data>').",
?? ??? ??? ?MYSQL_ERRMSG_SIZE);
?? ??? ?return 1;
?? ?}

?? ?args->arg_type[0] = STRING_RESULT;

?? ?initid->max_length = CURL_UDF_MAX_SIZE;
?? ?container = (st_curl_results *)malloc(sizeof(st_curl_results));

?? ?initid->ptr = (char *)container;

?? ?return 0;
}

char *http_put(UDF_INIT *initid, UDF_ARGS *args,
?? ?char *result,
?? ?unsigned long *length,
?? ?char *is_null,
?? ?char *error)
{
?? ?CURLcode retref;
?? ?CURL *curl;
?? ?st_curl_results *res = (st_curl_results *)initid->ptr;

?? ?curl_global_init(CURL_GLOBAL_ALL);
?? ?curl = curl_easy_init();

?? ?res->result = NULL;
?? ?res->size = 0;

?? ?if (curl)
?? ?{
?? ??? ?struct curl_slist *chunk = NULL;
?? ??? ?chunk = curl_slist_append(chunk, "Expect:");

?? ??? ?curl_easy_setopt(curl, CURLOPT_URL, args->args[0]);
?? ??? ?curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, result_cb);
?? ??? ?curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)res);
?? ??? ?curl_easy_setopt(curl, CURLOPT_USERAGENT, "mysql-udf-http/1.0");
?? ??? ?curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
?? ??? ?curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
?? ??? ?curl_easy_setopt(curl, CURLOPT_POSTFIELDS, args->args[1]);
?? ??? ?retref = curl_easy_perform(curl);
?? ??? ?if (retref) {
?? ??? ??? ?fprintf(stderr, "error\n");
?? ??? ??? ?if (res->result)
?? ??? ??? ??? ?strcpy(res->result, "");
?? ??? ??? ?res->size = 0;
?? ??? ?}
?? ?}
?? ?curl_easy_cleanup(curl);
?? ?*length = res->size;
?? ?return ((char *)res->result);
}

void http_put_deinit(UDF_INIT *initid)
{
?? ?/* if we allocated initid->ptr, free it here */
?? ?st_curl_results *res = (st_curl_results *)initid->ptr;

?? ?if (res->result)
?? ??? ?free(res->result);
?? ?free(res);
?? ?return;
}

/* ------------------------HTTP DELETE----------------------------- */

BOOL http_delete_init(UDF_INIT *initid, UDF_ARGS *args, char *message)
{
?? ?st_curl_results *container;

?? ?if (args->arg_count != 1)
?? ?{
?? ??? ?strncpy(message,
?? ??? ??? ?"one arguments must be supplied: http_delete('<url>').",
?? ??? ??? ?MYSQL_ERRMSG_SIZE);
?? ??? ?return 1;
?? ?}

?? ?args->arg_type[0] = STRING_RESULT;

?? ?initid->max_length = CURL_UDF_MAX_SIZE;
?? ?container = (st_curl_results *)malloc(sizeof(st_curl_results));

?? ?initid->ptr = (char *)container;

?? ?return 0;
}

char *http_delete(UDF_INIT *initid, UDF_ARGS *args,
?? ?char *result,
?? ?unsigned long *length,
?? ?char *is_null,
?? ?char *error)
{
?? ?CURLcode retref;
?? ?CURL *curl;
?? ?st_curl_results *res = (st_curl_results *)initid->ptr;

?? ?curl_global_init(CURL_GLOBAL_ALL);
?? ?curl = curl_easy_init();

?? ?res->result = NULL;
?? ?res->size = 0;

?? ?if (curl)
?? ?{
?? ??? ?curl_easy_setopt(curl, CURLOPT_URL, args->args[0]);
?? ??? ?curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, result_cb);
?? ??? ?curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)res);
?? ??? ?curl_easy_setopt(curl, CURLOPT_USERAGENT, "mysql-udf-http/1.0");
?? ??? ?curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
?? ??? ?retref = curl_easy_perform(curl);
?? ??? ?if (retref) {
?? ??? ??? ?fprintf(stderr, "error\n");
?? ??? ??? ?if (res->result)
?? ??? ??? ??? ?strcpy(res->result, "");
?? ??? ??? ?res->size = 0;
?? ??? ?}
?? ?}
?? ?curl_easy_cleanup(curl);
?? ?*length = res->size;
?? ?return ((char *)res->result);
}

void http_delete_deinit(UDF_INIT *initid)
{
?? ?/* if we allocated initid->ptr, free it here */
?? ?st_curl_results *res = (st_curl_results *)initid->ptr;

?? ?if (res->result)
?? ??? ?free(res->result);
?? ?free(res);
?? ?return;
}

使用vs编译过程中可能出现以下错误

需要引用的库文件有

??编译成功之后将?MySQLUdfHttpWin.dll 拷到mysql8 插件目录?

然后在navicat中进行注册 自定义函数

注册之后运行结果如下

?HTTP_GET

?HTTP_POST

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-04-27 11:39:57  更:2022-04-27 11:40:52 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 2:23:04-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码