微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用 Elixir/Ecto/Postgrex 在插入的二进制字符串中避免转义字符? 更新

如何解决如何使用 Elixir/Ecto/Postgrex 在插入的二进制字符串中避免转义字符? 更新

我是 elixir/ecto 的新手,我不明白为什么我的 'androidx.constraintlayout:constraintlayout:2.0.4' 字段(在架构中定义为 error_data)在我的 postgresql 列中插入斜线转义:

:binary

根据@smathy 的见解,我在 params = %{error_data: "eyJtZXNzYWdlIjoiSW52YWxpZCB0b2tlbiIsImNhdXNlIjpbXSwiZXJyb3IiOiJub3RfZm91bmQiLCJzdGF0dXMiOjQwMX0="} cast(%{},params,[:error_data]) |> change(%{error_data: Base.decode64!(params.error_data)}) |> Ecto.Repo.insert() IO.puts(get_change(changeset,:error_data) 调用之间放置了一个 change。它显示数据已被解码并且在插入前没有转义斜线。但是显示 Ecto 查询的下一行被转义了...检查我的应用程序的输出

insert

然后检查这些数据库查询:第一个代码插入错误。最后一个来自手动插入的未转义错误

[info] Creating error for 1 on channel 1
{"message":"Invalid token","cause":[],"error":"not_found","status":401}
[debug] QUERY OK db=0.5ms
INSERT INTO "errors" ("code","error","error_message","http_status","id","channel_id","inserted_at","updated_at") VALUES ($1,$2,$3,$4,$5,$6,$7,$8) RETURNING "id" ["error-03","{\"message\":\"Invalid token\",\"cause\":[],\"error\":\"not_found\",\"status\":401}","Invalid token",401,1,~N[2021-02-16 12:24:58],~N[2021-02-16 12:24:58]]

如何避免这种转义并插入纯解码 (dev=# SELECT error FROM errors ORDER BY updated_at DESC limit 1; error --------------------------------------------------------------------------------------- "{\"message\":\"Invalid token\",\"status\":401}" (1 row) dev=# SELECT error FROM errors ORDER BY updated_at ASC limit 1; error --------------------- {"eita": "deu pau"} (1 row) ) 内容? 如果我可以在插入中使用 ecto 片段,我会告诉数据库解码 base64 字符串......我也没有找到如何做到这一点......有什么帮助吗?

我想知道是否有任何环境配置会影响 ECTO 以记录它的查询并以字符串转换/转义 {"message":"Invalid token","status":401} 二进制文件结束...

解决方法

它们实际上并不存在,它们只是由您用来打印该值的任何工具显示出来,因为该工具使用 #define PIO_APC_ROUTINE_DEFINED #include <winternl.h> #include <iphlpapi.h> #include <IcmpAPI.h> //-------------- // types //-------------- typedef DWORD (WINAPI *LPFN_IcmpSendEcho2)(HANDLE,HANDLE,PIO_APC_ROUTINE,PVOID,IPAddr,LPVOID,WORD,PIP_OPTION_INFORMATION,DWORD,DWORD); typedef DWORD (WINAPI *LPFN_IcmpSendEcho2Ex)(HANDLE,DWORD); typedef HANDLE (WINAPI *LPFN_IcmpCreateFile)(); typedef BOOL (WINAPI *LPFN_IcmpCloseHandle)(HANDLE); typedef DWORD (WINAPI *LPFN_IcmpParseReplies)(LPVOID,DWORD); BYTE PingSignature[]={ 'X','Y','Z','1','2','3','4','5','6','7','8' }; typedef struct _sPingContext { ULONG *OutstandingCount; // shared number of pings outstanding CMutex *Mutex; // mutex for ipsfound CNumericBuffer<uint32_t> *IPsFound; // list of ips found (MSBF format) LPFN_IcmpParseReplies fnIcmpParseReplies; // function pointer BYTE ReplyBuffer[sizeof(ICMP_ECHO_REPLY) + sizeof(PingSignature) + sizeof(IO_STATUS_BLOCK) + 8]; // reply buffer (see API docs) _sPingContext(ULONG *outstandingcount,CMutex *mutex,CNumericBuffer<uint32_t> *ipsfound,LPFN_IcmpParseReplies fnicmpparsereplies) { OutstandingCount=outstandingcount; Mutex=mutex; IPsFound=ipsfound; fnIcmpParseReplies=fnicmpparsereplies; memset(ReplyBuffer,sizeof(ReplyBuffer)); }; } sPingContext,*psPingContext; //------------------------------------------------------------------------- // Purpose: Callback for async ping // // Input: ioresult - [i] io result of async operation // pingccontext - [i] context passed on ping // replysize - [i] reply size of ReplyBuffer // // Output: na // // Notes: // VOID PingCallbackCommon(DWORD ioresult,sPingContext* pingcontext,DWORD replysize) { // parse response buffer if (pingcontext) { if (ioresult==IP_SUCCESS) { if (pingcontext->fnIcmpParseReplies(pingcontext->ReplyBuffer,replysize)) { // point to reply buffer PICMP_ECHO_REPLY pechoreply=reinterpret_cast<PICMP_ECHO_REPLY>(pingcontext->ReplyBuffer); if (pechoreply->Status==IP_SUCCESS) { // check response if (pechoreply->DataSize==sizeof(PingSignature)) { if (memcmp(pechoreply->Data,PingSignature,pechoreply->DataSize)==0) { // successful ping pingcontext->Mutex->Lock(); pingcontext->IPsFound->AddItem(pechoreply->Address); pingcontext->Mutex->Unlock(); } } } } } // reduce count InterlockedDecrement(pingcontext->OutstandingCount); // clean up delete pingcontext; } } //------------------------------------------------------------------------- // Purpose: Callback for async ping // // Input: apccontext - [i] context passed on ping // // Output: na // // Notes: // VOID PingCallbackOld(PVOID apcontext) { sPingContext *pingcontext=reinterpret_cast<sPingContext*>(apcontext); PingCallbackCommon(IP_SUCCESS,pingcontext,sizeof(pingcontext->ReplyBuffer)); } //------------------------------------------------------------------------- // Purpose: Callback for async ping // // Input: apccontext - [i] context passed on ping // iostatusblock - [i] status of request // // Output: na // // Notes: // VOID PingCallback(PVOID apcontext,PIO_STATUS_BLOCK iostatusblock,ULONG reserved) { PingCallbackCommon(iostatusblock->Status,reinterpret_cast<sPingContext*>(apcontext),iostatusblock->Information); } //------------------------------------------------------------------------- // Purpose: build list of network hosts using IPv4 Ping // // Input: subnet - [i] subnet being scanned (LSB format) // hoststart - [i] host starting number for scan // hostend - [i] host ending number for scan // ips - [io] numeric buffer to update with found addresses // // Output: na // // Notes: // void IPV4Ping(IPAddr sourceip,uint32_t subnet,uint32_t hoststart,uint32_t hostend,CNumericBuffer<uint32_t> &ips) { // skip 127. network if ((sourceip & 0xFF)==127) return; bool oldlib=false; LPFN_IcmpSendEcho2Ex fnIcmpSendEcho2Ex=NULL; LPFN_IcmpCreateFile fnIcmpCreateFile=NULL; LPFN_IcmpCloseHandle fnIcmpCloseHandle=NULL; LPFN_IcmpParseReplies fnIcmpParseReplies=NULL; // first thing is first - check which set of functions to use HMODULE hlib=LoadLibrary(_T("iphlpapi.dll")); if (hlib) { // load functions fnIcmpCreateFile=(LPFN_IcmpCreateFile) GetProcAddress(hlib,"IcmpCreateFile"); fnIcmpSendEcho2Ex=(LPFN_IcmpSendEcho2Ex) GetProcAddress(hlib,"IcmpSendEcho2Ex"); fnIcmpCloseHandle=(LPFN_IcmpCloseHandle) GetProcAddress(hlib,"IcmpCloseHandle"); fnIcmpParseReplies=(LPFN_IcmpParseReplies) GetProcAddress(hlib,"IcmpParseReplies"); } // check if have everything if (!hlib || fnIcmpCreateFile==NULL || fnIcmpSendEcho2Ex==NULL || fnIcmpCloseHandle==NULL || fnIcmpParseReplies==NULL) { // no,try old version oldlib=true; // clean up if (hlib) { FreeLibrary(hlib); } // load old lib hlib=LoadLibrary(_T("icmp.dll")); // check if loaded if (hlib) { // load functions fnIcmpCreateFile=(LPFN_IcmpCreateFile) GetProcAddress(hlib,"IcmpCreateFile"); fnIcmpSendEcho2Ex=(LPFN_IcmpSendEcho2Ex) GetProcAddress(hlib,"IcmpSendEcho2Ex"); fnIcmpCloseHandle=(LPFN_IcmpCloseHandle) GetProcAddress(hlib,"IcmpCloseHandle"); fnIcmpParseReplies=(LPFN_IcmpParseReplies) GetProcAddress(hlib,"IcmpParseReplies"); } } // check if have everything if (hlib) { if (fnIcmpCreateFile!=NULL && fnIcmpSendEcho2Ex!=NULL && fnIcmpCloseHandle!=NULL && fnIcmpParseReplies!=NULL) { // open icmp HANDLE hicmp=fnIcmpCreateFile(); if (hicmp!=INVALID_HANDLE_VALUE) { // variables for callback handling ULONG outstandingcount=0; CMutex mutex; // process pings for (uint32_t host=hoststart; host<=hostend; host++) { // build full ip IPAddr ip=subnet | host; ip=GETMSBFDWORD(&ip); // create context sPingContext *pcontext; if ((pcontext=new sPingContext(&outstandingcount,&mutex,&ips,fnIcmpParseReplies))!=NULL) { // count request InterlockedIncrement(&outstandingcount); // now issue ping DWORD result=fnIcmpSendEcho2Ex(hicmp,NULL,oldlib ? (PIO_APC_ROUTINE) PingCallbackOld : PingCallback,pcontext,sourceip,ip,sizeof(PingSignature),pcontext->ReplyBuffer,sizeof(pcontext->ReplyBuffer),50); // check if failed if (result==0) { // check if because pending if (GetLastError()!=ERROR_IO_PENDING) { // no - use callback to clean up CDebugPrint::DebugPrint(_T("IcmpSendEcho Error %u\n"),GetLastError()); PingCallbackOld(pcontext); } else { // fire off pending APC callbacks ready SleepEx(0,TRUE); } } else { // completed sync - use callback to clean up PingCallbackOld(pcontext); } } } // wait for completion while (outstandingcount) { // handle callbacks SleepEx(10,TRUE); } // clean up fnIcmpCloseHandle(hicmp); } } // clean up FreeLibrary(hlib); } } //------------------------------------------------------------------------- // Purpose: build list of network hosts by way of IP scan for V4 // // Input: ipadapteraddress - [i] adapter ip address to build for // // Output: na // // Notes: ip addresses are MSBF // void IPV4Scan(IP_ADAPTER_UNICAST_ADDRESS *ipadapteraddress) { // build the subnet mask to use if (ipadapteraddress->OnLinkPrefixLength<=32 && ipadapteraddress->OnLinkPrefixLength!=0) { in_addr ia=reinterpret_cast<sockaddr_in*>(ipadapteraddress->Address.lpSockaddr)->sin_addr; // valid mask length - build mask uint32_t rangemask=((1U<<(32-ipadapteraddress->OnLinkPrefixLength))-1); uint32_t mask=~rangemask; uint32_t subnet=GETMSBFDWORD(&ia.s_addr) & mask; CDebugPrint::DebugPrint(_T("Subnet %u.%u.%u.%u/%u\n"),(subnet>>24) & 0xFF,(subnet>>16) & 0xFF,(subnet>>8) & 0xFF,(subnet>>0) & 0xFF,ipadapteraddress->OnLinkPrefixLength); CDebugPrint::DebugPrint(_T("Scanning %u hosts\n"),(UINT32_MAX & rangemask)-1); CNumericBuffer<uint32_t> ipsfound; IPV4Ping(ia.s_addr,subnet,1,(UINT32_MAX & rangemask)-1,ipsfound); for (UINT i=0; i<(UINT)ipsfound.GetCount(); i++) { uint32_t ip=ipsfound[i]; CDebugPrint::DebugPrint(_T("Ping found %u.%u.%u.%u\n"),ip & 0xFF,(ip>>8) & 0xFF,(ip>>16) & 0xFF,(ip>>24) & 0xFF); } } else CDebugPrint::DebugPrint(_T("Invalid subnet length %u\n"),ipadapteraddress->OnLinkPrefixLength); } 作为字符串分隔符,因此将它们转义以避免歧义.

同样的事情发生在 " 会话中,如果您实际打印出该值,那么它会如您所愿,因为当您输出一个字符串时,它不会包含分隔符:

iex

更新

这是我在字符串 (varchar) 字段中精确运行您在上面显示的代码后运行的 iex(6)> Base.decode64! "eyJtZXNzYWdlIjoiSW52YWxpZCB0b2tlbiIsImNhdXNlIjpbXSwiZXJyb3IiOiJub3RfZm91bmQiLCJzdGF0dXMiOjQwMX0=" "{\"message\":\"Invalid token\",\"cause\":[],\"error\":\"not_found\",\"status\":401}" iex(7)> IO.puts v {"message":"Invalid token","cause":[],"error":"not_found","status":401} :ok 查询:

psql

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。