
рд╢реБрдн рджрд┐рдиред рдХрд┐рд╕реА рд╕рд╛рдЗрдЯ рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рддреЗ рд╕рдордп, рдХрднреА-рдХрднреА рдПрдХ рд╕реНрдерд┐рддрд┐ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИ рдЬрдм рдЖрдкрдХреЛ рдпрд╣ рдЪреБрдирдирд╛ рд╣реЛрддрд╛ рд╣реИ рдХрд┐ рдЫрд╡рд┐рдпреЛрдВ рдХреЛ рдХреИрд╕реЗ рдФрд░ рдХрд╣рд╛рдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдирд╛ рд╣реИред рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, рд╕рдВрднрд╡ рд╡рд┐рдХрд▓реНрдкреЛрдВ рдореЗрдВ, рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╣реИрдВ:
- рдЪрд┐рддреНрд░ рдкреВрд░реА рддрд░рд╣ рд╕реЗ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╣реИрдВ
- рдЪрд┐рддреНрд░ рдлрд╝рд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рд╣реИрдВ, рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рд╣реИ
- рдЫрд╡рд┐рдпрд╛рдБ рдПрдХ рдмрд╛рд╣рд░реА рд╡рд┐рд╢реЗрд╖ рд╕реЗрд╡рд╛ рдореЗрдВ рд╣реИрдВ
рдпрджреНрдпрдкрд┐
PostgreSQL рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ (рд╕реАрдзреЗ
рдмрд╛рдЗрдЯрд╛ рдХреНрд╖реЗрддреНрд░реЛрдВ рдореЗрдВ рдпрд╛
рдмрдбрд╝реА рд╡рд╕реНрддреБрдУрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ), рдпрд╣ рдЧрддрд┐ рдФрд░ рд╕реНрдореГрддрд┐ рдЦрдкрдд рджреЛрдиреЛрдВ рдХреЗ рд╕рдВрджрд░реНрдн рдореЗрдВ рд╕рдмрд╕реЗ рдХрдо рдЗрд╖реНрдЯрддрдо рд╡рд┐рдХрд▓реНрдк рд╣реИред рдПрдХ рдЕрдиреНрдп рд╕рд╛рдорд╛рдиреНрдп рдЕрднреНрдпрд╛рд╕ рдбрд┐рд╕реНрдХ рдкрд░ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЗ рд░реВрдк рдореЗрдВ рдЫрд╡рд┐рдпреЛрдВ рдХрд╛ рднрдВрдбрд╛рд░рдг рд╣реИ, рд╕рд╛рдЗрдЯ рдХреЗ рд▓рд┐рдП рдЫрд╡рд┐ рдХрд╛ рдкрде рдмрдирддрд╛ рд╣реИред рд▓рд╛рднреЛрдВ рдореЗрдВ рд╕реЗ - рдХрд┐рд╕реА рд╡рд┐рд╢реЗрд╖ рдлрд╝рд╛рдЗрд▓ рд╕рд┐рд╕реНрдЯрдо рдХреЛ рдХреИрд╢ рдпрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ред рдФрд░ рддреАрд╕рд░рд╛ рд╡рд┐рдХрд▓реНрдк - рдЫрд╡рд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рд╕реЗрд╡рд╛ рдЖрд╡рдВрдЯрд┐рдд рдХреА рдЬрд╛рддреА рд╣реИ, рдЬреЛ рдХреИрд╢рд┐рдВрдЧ рд╣реЛ рд╕рдХрддреА рд╣реИ, рдордХреНрдЦреА рдкрд░ рд╕реНрдХреЗрд▓рд┐рдВрдЧ, рдкреНрд░рд╛рд░реВрдк рдХреЛ рдмрджрд▓ рд╕рдХрддреА рд╣реИред рдЖрдЗрдП рдРрд╕реА рд╕реЗрд╡рд╛ рдХреЗ рд╕рд╛рде
PostgreSQL рдЗрдВрдЯрд░реИрдХреНрд╢рди рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред
рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди
рд╣рдо рдЬреЛ рд╣реЛ рд░рд╣рд╛ рд╣реИ рдЙрд╕рдХреА рдПрдХ рдЫреЛрдЯреА рд╕реА рддрд╕реНрд╡реАрд░ рдХреЛ рд░реЗрдЦрд╛рдВрдХрд┐рдд рдХрд░рддреЗ рд╣реИрдВред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ http рд╕реЗрд╡рд╛ рд╣реИ, рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдХреЗ рд▓рд┐рдП, рдирд┐рдореНрди рдЖрджреЗрд╢реЛрдВ рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рдиреЗ рд╡рд╛рд▓реЗ рдЪрд┐рддреНрд░реЛрдВ рдХреЗ рд▓рд┐рдП:
- рдЗрдореЗрдЬ рд▓реЛрдбрд┐рдВрдЧ - рдПрдХ рдлреЙрд░реНрдо рдХреЗ рд╕рд╛рде POST рд░рд┐рдХреНрд╡реЗрд╕реНрдЯ рднреЗрдЬрдирд╛, рдЬрд╡рд╛рдм рдореЗрдВ JSON рдореЗрдВ рдЗрдореЗрдЬ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдХреБрдЫ рдЬрд╛рдирдХрд╛рд░реА рдЖрддреА рд╣реИ, рдЬрд┐рд╕рдХреЗ рдмреАрдЪ рдЬреЗрдирд░реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛
- рдЫрд╡рд┐ рдЕрдзрд┐рдЧреНрд░рд╣рдг - рдЫрд╡рд┐ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ my.service.local / 1001 рдХреЗ рд╕рд╛рде рдПрдХ GET рдЕрдиреБрд░реЛрдз рднреЗрдЬрдирд╛
- рдЫрд╡рд┐ рд╣рдЯрд╛рдирд╛ - рдЫрд╡рд┐ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ my.service.local / 1001 рдХреЗ рд╕рд╛рде DELETE рдЕрдиреБрд░реЛрдз рднреЗрдЬрдирд╛
рдЫрд╡рд┐ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛рдУрдВ рдХреЛ рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд┐рдпрд╛ рдЬрд╛рдПрдЧрд╛, рдЗрд╕ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЖрдк рд╕рд╛рдЗрдЯ рдХреЗ рдкреГрд╖реНрдареЛрдВ рдкрд░ рдлрд╝реЙрд░реНрдо рдХреЗ рдЯреИрдЧ рдПрдореНрдмреЗрдб рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
<img src = "http: //my.service.local/1001" />
рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкрдХреНрд╖ рдкрд░, рдПрдХ рдЫрд╡рд┐ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдирд╛ (рд╕рд╛рде рд╣реА рд╕рд╣реЗрдЬрдирд╛ рдФрд░ рд╣рдЯрд╛рдирд╛)
рдЕрдкрд▓реЛрдб_рдореЗрдЬрд╝ рдлрд╝рдВрдХреНрд╢рди (
рдлрд╝рд╛рдЗрд▓ рдирд╛рдо рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд╕рд╛рде) рдХреЗ рд▓рд┐рдП рдПрдХ рдХреЙрд▓ рдХреА рддрд░рд╣ рджрд┐рдЦрдирд╛ рдЪрд╛рд╣рд┐рдП, рдЬреЛ рд╕реЗрд╡рд╛ рдореЗрдВ рдЫрд╡рд┐ рдкрд╣рдЪрд╛рдирдХрд░реНрддрд╛ рдХреЛ рд▓реМрдЯрд╛рддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рддрдм рддрд╛рд▓рд┐рдХрд╛ рдореЗрдВ рд▓рд┐рдЦрд╛ рдЬрд╛рддрд╛ рд╣реИред рдЪреВрдВрдХрд┐
рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдПрд╕рдХреНрдпреВрдПрд▓ рд╕реЗ http рдЕрдиреБрд░реЛрдзреЛрдВ рдХреЛ рд╕реАрдзреЗ рдПрдХреНрд╕реЗрд╕ рдХрд░рдирд╛ рдЕрд╕рдВрднрд╡ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╕реА рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд╛рд░реНрдпреЛрдВ рдкрд░ рдЖрд╡рд╢реНрдпрдХ рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд▓рд╛рдЧреВ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ, рдФрд░ рдЙрдирдХреЗ рдкрд╛рд╕ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдПрдХ рдЬрдЧрд╣ рд╣реИред рд╕рд░рд▓рддрд╛ рдХреЗ рд▓рд┐рдП,
рдХрд░реНрд▓ рдФрд░
рдЬреИрдирд╕рди рд▓рд╛рдЗрдмреНрд░реЗрд░реАрдЬрд╝ (
рдЬреЗрдПрд╕рдПрди рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЙрддреНрддрд░рд╛рд░реНрджреНрдз) рдХреЗ рд╕рд╛рде рдХрд░рддреЗ рд╣реИрдВред рд╣рдо рд╢реБрд░реВ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред
рд╣реЗрдбрд░ рдлрд╝рд╛рдЗрд▓
barberry_impl.h рдореЗрдВ рд╣рдорд╛рд░реЗ рдлрд╝рдВрдХреНрд╢рди рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░реЗрдВ:
рд╕реНрд░реЛрдд рдлрд╝рд╛рдЗрд▓
barberry_impl.c рдореЗрдВ, рдирд┐рдореНрди рд╡реИрд╢реНрд╡рд┐рдХ рдЪрд░ рдбрд╛рд▓реЗрдВ:
char last_error[1024]; FILE *file = NULL; int result = 0;
Last_error рдЪрд░ рдЕрдВрддрд┐рдо рддреНрд░реБрдЯрд┐ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░реЗрдЧрд╛,
рдлрд╝рд╛рдЗрд▓ рд╕реЗрд╡рд╛ рд╕реЗ рдбреЗрдЯрд╛ рдкреНрд░рд╛рдкреНрдд рд╣реЛрдиреЗ рдкрд░ рдмрдирд╛рдИ рдЧрдИ
рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдПрдХ рд╕рдВрдХреЗрддрдХ рд╣реИ, рдФрд░ рд╕реЗрд╡рд╛ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рдХрд╛рд░реНрдпреЛрдВ рдХрд╛ рдкрд░рд┐рдгрд╛рдо рдкрд░рд┐рдгрд╛рдо рдореЗрдВ рд╕рд╣реЗрдЬрд╛ рдЬрд╛рдПрдЧрд╛ред
Barberry_error рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рддреБрдЪреНрдЫ рд╣реИ -
рдЕрдВрддрд┐рдо last_error ред рдЖрдЗрдП рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рдХрд╛рд░реНрдп рдХрд░рддреЗ рд╣реИрдВ рдлрд╝рдВрдХреНрд╢рди
barberry_upload_file ред
рдЗрд╕рд╕реЗ рдкрд╣рд▓реЗ рдХрд┐ рдЖрдк
рдХрд░реНрд▓ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдирд╛ рд╢реБрд░реВ рдХрд░реЗрдВ, рдЖрдкрдХреЛ рдЗрд╕рдХреЗ рд▓рд┐рдП рдкрд░реНрдпрд╛рд╡рд░рдг рдХреЛ рдЖрд░рдВрдн рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП (
рдХрд░реНрд▓_рдЧреЛрдмрд╛рд▓_рдЗрдирд┐рдЯ рдХрдорд╛рдВрдб рдХреЗ рд╕рд╛рде) рдФрд░ рдПрдХ рд╕рддреНрд░ рдмрдирд╛рдПрдВ (
рдХрд░реНрд▓_рдПрд╕реНрд╕реА_рдЗрдирд┐рдЯ рдХрдорд╛рдВрдб рдХреЗ рд╕рд╛рде, рдЬреЛ рд╕рддреНрд░ рд╣реИрдВрдбрд▓ рдХреЛ
рдПрдХ рдкреЙрдЗрдВрдЯрд░
рд▓реМрдЯрд╛рддрд╛ рд╣реИ )ред рдЕрдЧрд▓рд╛, рдПрдХ рд╕рдмрдорд┐рдЯ рдлрд╝реЙрд░реНрдо рдмрдирд╛рдПрдВ (
рдХрд░реНрд▓_рдлреЙрд░реНрдордб рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ) рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд╡рд┐рдХрд▓реНрдк рднрд░реЗрдВ:
- CURLOPT_URL - рд╣рдо рдЬрд┐рд╕ рд╣реЛрд╕реНрдЯ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд░рд╣реЗ рд╣реИрдВ
- CURLOPT_HTTPPOST - POST рд╡рд┐рдзрд┐ рджреНрд╡рд╛рд░рд╛ рдкреНрд░рд╕реНрддреБрдд рдкреНрд░рдкрддреНрд░
- CURLOPT_WRITEFUNCTION - рдореЗрдЬрдмрд╛рди рд╕реЗ рдЬрд╡рд╛рдм рджреЗрдиреЗ рдХреЗ рд▓рд┐рдП рдХреЙрд▓рдмреИрдХ рдлрд╝рдВрдХреНрд╢рди
рдмрд░рдмреЗрд░реА_рдЕрдкрд▓реЛрдб_рдлрд╛рдЗрд▓ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди:
int barberry_upload_file(const char *host, const char *filename) { result = -1; curl_global_init(CURL_GLOBAL_ALL); CURL *curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_URL, host); struct curl_httppost *httppost = NULL; struct curl_httppost *last_ptr = NULL; curl_formadd(&httppost, &last_ptr, CURLFORM_COPYNAME, "sendfile", CURLFORM_FILE, filename, CURLFORM_END); curl_formadd(&httppost, &last_ptr, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "send", CURLFORM_END); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, upload_response); curl_easy_setopt(curl, CURLOPT_HTTPPOST, httppost); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { sprintf(last_error, "%s", curl_easy_strerror(res)); } curl_easy_cleanup(curl); curl_formfree(httppost); } return result; }
CALLBACK upload_response рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдПрдХ рдкреНрд░реЛрдЯреЛрдЯрд╛рдЗрдк рд╣реИ:
size_t function(char *ptr, size_t size, size_t nmemb, void *userdata);
рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде:
- ptr - рдкреНрд░рд╛рдкреНрдд рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рд╕реВрдЪрдХ
- рдЖрдХрд╛рд░ * nmemb - рдЙрдирдХрд╛ рдЖрдХрд╛рд░
- userdata - FILE рдХрд╛ рдкреЙрдЗрдВрдЯрд░ *, рд╡реИрдХрд▓реНрдкрд┐рдХ рд░реВрдк рд╕реЗ CURLOPT_WRITEDATA рд╡рд┐рдХрд▓реНрдк рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛
рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдбреЗрдЯрд╛ рдХрд╛ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рдЖрдХрд╛рд░ рд╡рд╛рдкрд╕ рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдЕрд░реНрдерд╛рддред рдЖрдХрд╛рд░ * nmembред рдЗрд╕ рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдкреНрд░реЗрд╖рд┐рдд JSON рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реИ:
size_t upload_response(char *ptr, size_t size, size_t nmemb, void *userdata) { (void)userdata; parse_upload_response(ptr); return size * nmemb; }
рд╣рдо рдЗрд╕реЗ рдПрдХ рдЕрдиреНрдп рдлрд╝рдВрдХреНрд╢рди рдХреЗ рд▓рд┐рдП
рд╕реМрдВрдкреЗрдВрдЧреЗ рдЬрд┐рд╕рдореЗрдВ рд╣рдо рдЙрддреНрддрд░ рдХреЛ рдкрд╛рд░реНрд╕ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
jansson рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:
void parse_upload_response(const char *text) { if (!strcmp(text, "{}")) { sprintf(last_error, "%s", "Empty file"); return; } json_error_t error; json_t *root = json_loads(text, 0, &error); if (!root) { sprintf(last_error, "%s", text); return; } json_t *id = json_object_get(root, "id"); if(!json_is_integer(id)) { sprintf(last_error, "%s", text); json_decref(root); return; } result = json_integer_value(id); json_decref(root); }
рдЦрд╛рд▓реА рдлрд╝рд╛рдЗрд▓ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рд╣рдореЗрдВ рдЙрддреНрддрд░ {} рдкреНрд░рд╛рдкреНрдд рд╣реЛрдЧрд╛, рд╣рдо рдЗрд╕ рдорд╛рдорд▓реЗ рдХреЛ рд╕рдВрднрд╛рд▓ рд▓реЗрдВрдЧреЗред рдпрджрд┐ рд╕рдм рдХреБрдЫ рдХреНрд░рдо рдореЗрдВ рд╣реИ, рддреЛ рдлрд╝рд╛рдЗрд▓ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдЕрдкрд▓реЛрдб рдХреА рдЧрдИ рд╣реИ, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдлреЙрд░реНрдо рдореЗрдВ рдЖрдПрдЧреА: {"id": 1001, "ext": "png" ...}ред рдХреЗрд╡рд▓ рдЖрдИрдбреА рдмреНрдпрд╛рдЬ рдХреА рд╣реИ, рдФрд░ рд╣рдо рдЗрд╕реЗ рдкрд░рд┐рдгрд╛рдо рдореЗрдВ рд▓рд┐рдЦрддреЗ рд╣реИрдВред
рдлрд╝рд╛рдЗрд▓ рдХреЛ рд╕рд╣реЗрдЬрдиреЗ рдХрд╛ рдХрд╛рд░реНрдп рдереЛрдбрд╝рд╛ рд╕рд░рд▓ рд╣реИ - рдЖрдкрдХреЛ рдмрд╕ рдПрдХ GET рдЕрдиреБрд░реЛрдз рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдкреНрд░рд╛рдкреНрдд рдХрд░реЗрдВ рдФрд░ рдЗрд╕реЗ рдлрд╝рд╛рдЗрд▓ рдореЗрдВ рд▓рд┐рдЦреЗрдВ (рд╕реНрдерд┐рддрд┐ рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рдЬрдм рд╡рд╛рдВрдЫрд┐рдд рдЖрдИрдбреА рдХреЗ рд╕рд╛рде рдлрд╝рд╛рдЗрд▓ рдирд╣реАрдВ рдорд┐рд▓реА):
barberry_download_file int barberry_download_file(const char *host, int id, const char *filename) { result = 0; file = fopen(filename, "wb"); if (!file) { sprintf(last_error, "%s", "Can't create file"); return -1; } curl_global_init(CURL_GLOBAL_ALL); CURL *curl = curl_easy_init(); if (curl) { char buffer[1024]; sprintf(buffer, "%s/%d", host, id); curl_easy_setopt(curl, CURLOPT_URL, buffer); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, download_response); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { sprintf(last_error, "%s", curl_easy_strerror(res)); result = -1; } curl_easy_cleanup(curl); } fclose(file); return result; }
download_response size_t download_response(char *ptr, size_t size, size_t nmemb, void *userdata) { (void)userdata; if (!strcmp(ptr, "{}")) { sprintf(last_error, "%s", "File on server not found"); result = -1; } else { fwrite(ptr, size * nmemb, 1, file); } return size * nmemb; }
рд╕реЗрд╡рд╛ рдореЗрдВ рдлрд╝рд╛рдЗрд▓ рд╣рдЯрд╛рдирд╛ рдПрдХ DELETE рдЕрдиреБрд░реЛрдз рд╣реИ (
рдХрд░реНрд▓ рдХреЗ рд▓рд┐рдП рдЕрдиреБрд░реЛрдз рдкреНрд░рдХрд╛рд░ CURLOPT_CUSTOMREQUEST рд╡рд┐рдХрд▓реНрдк рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИ):
barberry_delete_file int barberry_delete_file(const char *host, int id) { result = 0; curl_global_init(CURL_GLOBAL_ALL); CURL *curl = curl_easy_init(); if (curl) { char buffer[1024]; sprintf(buffer, "%s/%d", host, id); curl_easy_setopt(curl, CURLOPT_URL, buffer); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, delete_response); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { sprintf(last_error, "%s", curl_easy_strerror(res)); result = -1; } curl_easy_cleanup(curl); } return result; }
delete_response size_t delete_response(char *ptr, size_t size, size_t nmemb, void *userdata) { (void)ptr; (void)userdata; return size * nmemb; }
PostgreSQL рднрд╛рдЧ рдкрд░ рдЬрд╛рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рд╣рдо рдЕрдкрдиреЗ рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдкрд░реАрдХреНрд╖рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдЫреЛрдЯреА рдХрдВрд╕реЛрд▓ рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд▓рд┐рдЦреЗрдВрдЧреЗред рдЗрд╕рдореЗрдВ, рд╣рдо рдЙрддреНрддреАрд░реНрдг рдорд╛рдкрджрдВрдбреЛрдВ рдХреА рдЬрд╛рдВрдЪ рдХрд░рддреЗ рд╣реИрдВ, рдпрджрд┐ рд╡реЗ рдЕрдкреЗрдХреНрд╖рд┐рдд рд╡рд╛рд▓реЗ (
рдкреНрд░рд┐рдВрдЯ_рд╣реЗрд▓реНрдк рдореЗрдВ рдЙрджрд╛рд╣рд░рдг) рд╕реЗ
рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВ , рддреЛ рд╣рдо рдЖрд╡рд╢реНрдпрдХ рдХрд╛рд░реНрдп рдХрд░рддреЗ рд╣реИрдВ:
barberry_test.c #include "barberry_impl.h" void print_help() { fprintf(stdout, "Usage:\n"); fprintf(stdout, " bbtest upload my.service.local /home/username/image1000.png\n"); fprintf(stdout, " bbtest download my.service.local 1000 /home/username/image1000.png\n"); fprintf(stdout, " bbtest delete my.service.local 1000\n\n"); } int main(int argc, char *argv[]) { (void)argc; (void)argv; if (argc <= 2) { print_help(); return 0; } if (!strcmp(argv[1], "upload")) { if (argc != 4) { print_help(); return 0; } int id = barberry_upload_file(argv[2], argv[3]); if (id != -1) { fprintf(stdout, "File uploaded with id %d\n", id); } else { fprintf(stderr, "%s\n", barberry_error()); } } else if (!strcmp(argv[1], "download")) { if (argc != 5) { print_help(); return 0; } int result = barberry_download_file(argv[2], atoi(argv[3]), argv[4]); if (result != -1) { fprintf(stdout, "%s\n", "File downloaded"); } else { fprintf(stderr, "%s\n", barberry_error()); } } else if (!strcmp(argv[1], "delete")) { if (argc != 4) { print_help(); return 0; } int result = barberry_delete_file(argv[2], atoi(argv[3])); if (result != -1) { fprintf(stdout, "%s\n", "File deleted"); } else { fprintf(stderr, "%s\n", barberry_error()); } } else { print_help(); } return 0; }
рдЗрд╕ рдкреВрд░реА рдЪреАрдЬрд╝ рдХреЛ рдПрдХ рд╕рд╛рде рд░рдЦрдирд╛ (рдЖрдкрдХреЗ рдУрдПрд╕ рдореЗрдВ рд╣реЗрдбрд░ рдлрд╝рд╛рдЗрд▓реЛрдВ рдФрд░ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдкрде рднрд┐рдиреНрди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ) рдФрд░ рдкрд░реАрдХреНрд╖рдг:
cc -c barberry_impl.c cc -c barberry_test.c cc -L/usr/lib -lcurl -ljansson -o bbtest barberry_test.o barberry_impl.o ./bbtest upload my.service.local ~/picture01.png File uploaded with id 1017
рдпрджрд┐ рд╕рдм рдХреБрдЫ рдХреНрд░рдо рдореЗрдВ рд╣реИ, рддреЛ рдЖрдк рд╣рдорд╛рд░реА рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдХреЗ PostgreSQL рдХреЗ рд╣рд┐рд╕реНрд╕реЗ рдореЗрдВ рдЬрд╛ рд╕рдХрддреЗ рд╣реИрдВ (PostgreSQL рдореЗрдВ рд╕рдВрдЧреНрд░рд╣реАрдд C рдлрд╝рдВрдХреНрд╢рди рдкрд░ рдЕрдзрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдХреЗ рд▓рд┐рдП,
[4] рджреЗрдЦреЗрдВ)ред
рдЖрдЗрдП рдбреЗрдЯрд╛рдмреЗрд╕ рдХреЗ рд▓рд┐рдП рдирд┐рд░реНрдпрд╛рдд рдХрд┐рдП рдЧрдП рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдШреЛрд╖рд┐рдд рдХрд░реЗрдВ (рд╕рдВрд╕реНрдХрд░рдг 1 рдХреЗ рд╕рд╛рде):
PG_FUNCTION_INFO_V1(bb_upload_file); PG_FUNCTION_INFO_V1(bb_download_file); PG_FUNCTION_INFO_V1(bb_delete_file);
рдкрд╛рда (PostgreSQL рдореЗрдВ рдЯрд╛рдЗрдк) рд╕реЗ рд╕реА-рд╕реНрдЯреНрд░рд┐рдВрдЧ рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдЫреЛрдЯрд╛ рдлрд╝рдВрдХреНрд╢рди рдорджрдж рдХрд░реЗрдЧрд╛:
char* text_to_string(text *txt) { size_t size = VARSIZE(txt) - VARHDRSZ; char *buffer = (char*)palloc(size + 1); memcpy(buffer, VARDATA(txt), size); buffer[size] = '\0'; return buffer; }
рдирд┐рд░реНрдпрд╛рдд рдХрд┐рдП рдЧрдП рдХрд╛рд░реНрдпреЛрдВ рдХреЗ рдХрд╛рд░реНрдпрд╛рдиреНрд╡рдпрди рдореЗрдВ рдкрд╣рд▓реЗ рдХреА рд▓рд┐рдЦрд┐рдд рдХрд╛рд░реНрдпрдХреНрд╖рдорддрд╛ рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рдирд╛ рд╢рд╛рдорд┐рд▓ рд╣реИ, рдЕрдЧрд░ рдХреБрдЫ рдЧрд▓рдд рд╣реЛ рдЧрдпрд╛ рд╣реИ, рддреЛ рдПрдХ рддреНрд░реБрдЯрд┐ рдЙрддреНрдкрдиреНрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП
bb_upload_file Datum bb_upload_file(PG_FUNCTION_ARGS) { char *host = text_to_string(PG_GETARG_TEXT_P(0)); char *filename = text_to_string(PG_GETARG_TEXT_P(1)); int result = barberry_upload_file(host, filename); if (result == -1) { elog(ERROR, "%s", barberry_error()); } pfree(host); pfree(filename); PG_RETURN_INT32(result); }
bb_download_file Datum bb_download_file(PG_FUNCTION_ARGS) { char *host = text_to_string(PG_GETARG_TEXT_P(0)); int id = PG_GETARG_INT32(1); char *filename = text_to_string(PG_GETARG_TEXT_P(2)); int result = barberry_download_file(host, id, filename); if (result == -1) { elog(ERROR, "%s", barberry_error()); } pfree(host); pfree(filename); PG_RETURN_VOID(); }
bb_delete_file Datum bb_delete_file(PG_FUNCTION_ARGS) { char *host = text_to_string(PG_GETARG_TEXT_P(0)); int id = PG_GETARG_INT32(1); int result = barberry_delete_file(host, id); if (result == -1) { elog(ERROR, "%s", barberry_error()); } pfree(host); PG_RETURN_VOID(); }
рд╣рдо рдПрдХ рдЧрддрд┐рд╢реАрд▓ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдХрд╛ рдирд┐рд░реНрдорд╛рдг рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ
PostgreSQL (рдЕрдкрдиреЗ рдУрдПрд╕ рдореЗрдВ рд╢реАрд░реНрд╖ рд▓реЗрдЦ рдлрд╝рд╛рдЗрд▓реЛрдВ рдФрд░ рдкреБрд╕реНрддрдХрд╛рд▓рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдкрде рднрд┐рдиреНрди рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ) рдкрд░ рдХреЙрдкреА рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:
rm -rf *.o cc -I/usr/include/postgresql/server -fpic -c barberry.c cc -I/usr/include/postgresql/server -fpic -c barberry_impl.c cc -L/usr/lib -lpq -lcurl -ljansson -shared -o barberry.so barberry.o barberry_impl.o cp *.so /usr/lib/postgresql
рдбреЗрдЯрд╛рдмреЗрд╕ рдореЗрдВ рдмрдирд╛рдП рдЧрдП SQL рдлрд╝рдВрдХреНрд╢рдВрд╕ рдЬреИрд╕реЗ рджрд┐рдЦрддреЗ рд╣реИрдВ:
CREATE OR REPLACE FUNCTION public.bb_upload_file ( p_host text, p_filename text ) RETURNS integer AS 'barberry', 'bb_upload_file' LANGUAGE c VOLATILE STRICT; CREATE OR REPLACE FUNCTION public.bb_download_file ( p_host text, p_id integer, p_filename text ) RETURNS void AS 'barberry', 'bb_download_file' LANGUAGE c VOLATILE STRICT; CREATE OR REPLACE FUNCTION public.bb_delete_file ( p_host text, p_id integer ) RETURNS void AS 'barberry', 'bb_delete_file' LANGUAGE c VOLATILE STRICT;
рд╣рдо PostgreSQL рдХреЗ рд╡рд┐рд╕реНрддрд╛рд░ рдХреЗ рд░реВрдк рдореЗрдВ рдПрдХ рдЧрддрд┐рд╢реАрд▓ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдФрд░ рдПрдХ рдПрд╕рдХреНрдпреВрдПрд▓ рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдбрд┐рдЬрд╛рдЗрди рдХрд░реЗрдВрдЧреЗ (
[5] рдореЗрдВ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд░реНрдгрд┐рдд рд╣реИ)ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ
barberry.control рдирд┐рдпрдВрддреНрд░рдг рдлрд╝рд╛рдЗрд▓ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ:
рд╣рдорд╛рд░реЗ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдХреЗ рд▓рд┐рдП SQL рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдХреЛ
рдмрд╛рд░рдмреЗрд░реА - 1.0.sql (
рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдХреНрдпреВрдПрд▓ рдкреНрд░рд▓реЗрдЦрди рдХреЗ рдЕрдиреБрд╕рд╛рд░) рдХрд╣рд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рд╣рдо рдЗрди рджреЛ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдХреЙрдкреА рдХрд░рддреЗ рд╣реИрдВ рдЬрд╣рд╛рдБ
PostgreSQL рдЕрдкрдиреЗ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рд╕реНрдЯреЛрд░ рдХрд░рддрд╛ рд╣реИред
рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдмрдирд╛рдирд╛ рдФрд░ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рдмреЗрд╣рдж рд╕рд░рд▓ рд╣реИ:
CREATE EXTENSION barberry; UPDATE avatar SET image = bb_upload_file ( 'my.service.local', 'images/avatar_admin.png' ) WHERE name = 'admin';
рд╕реНрд░реЛрдд рдлрд╝рд╛рдЗрд▓реЗрдВ
рдКрдкрд░ рджреА рдЧрдИ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдПрдХ рдЫреЛрдЯреА рдЙрдкрдпреЛрдЧрд┐рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЗрд╕реЗ рдЧреАрдереВрдм рдкрд░ рд╣реЛрд╕реНрдЯ рдирд╣реАрдВ рдХрд┐рдпрд╛ рдЧрдпрд╛ рд╣реИред рдЕрд╕реЗрдВрдмрд▓реА рдХреА рд╕реБрд╡рд┐рдзрд╛ рдХреЗ рд▓рд┐рдП, рдмреИрд░реАрдмреЗрд░реА, рдмрд░рдмреЗрд░реА_рдЯреЗрд╕реНрдЯ, рдХреНрд▓реАрди, рдкреБрдирд░реНрдирд┐рд░реНрдорд╛рдг, рдЗрдВрд╕реНрдЯреЙрд▓ рдХреЗ рдкреНрд░рдпреЛрдЬрдиреЛрдВ рдХреЗ рд▓рд┐рдП рдПрдХ рдореЗрдХрдлрд╛рдЗрд▓ рдЬреЛрдбрд╝рд╛ рдЧрдпрд╛ рд╣реИред
barberry_impl.h #ifndef BARBERRY_IMPL_H #define BARBERRY_IMPL_H #include <stdio.h> #include <string.h> #include <curl/curl.h> #include <jansson.h> // get last error char* barberry_error(); // upload file to BarBerry's service and return ID int barberry_upload_file(const char *host, const char *filename); // download file from BarBerry's service by ID int barberry_download_file(const char *host, int id, const char *filename); // delete file from BarBerry's service by ID int barberry_delete_file(const char *host, int id); #endif // BARBERRY_IMPL_H
barberry_impl.c #include "barberry_impl.h" char last_error[1024]; FILE *file = NULL; int result = 0; void parse_upload_response(const char *text) { if (!strcmp(text, "{}")) { sprintf(last_error, "%s", "Empty file"); return; } json_error_t error; json_t *root = json_loads(text, 0, &error); if (!root) { sprintf(last_error, "%s", text); return; } json_t *id = json_object_get(root, "id"); if(!json_is_integer(id)) { sprintf(last_error, "%s", text); json_decref(root); return; } result = json_integer_value(id); json_decref(root); } size_t upload_response(char *ptr, size_t size, size_t nmemb, void *userdata) { (void)userdata; parse_upload_response(ptr); return size * nmemb; } size_t download_response(char *ptr, size_t size, size_t nmemb, void *userdata) { (void)userdata; if (!strcmp(ptr, "{}")) { sprintf(last_error, "%s", "File on server not found"); result = -1; } else { fwrite(ptr, size * nmemb, 1, file); } return size * nmemb; } size_t delete_response(char *ptr, size_t size, size_t nmemb, void *userdata) { (void)ptr; (void)userdata; return size * nmemb; } char* barberry_error() { return last_error; } int barberry_upload_file(const char *host, const char *filename) { result = -1; curl_global_init(CURL_GLOBAL_ALL); CURL *curl = curl_easy_init(); if (curl) { curl_easy_setopt(curl, CURLOPT_URL, host); struct curl_httppost *httppost = NULL; struct curl_httppost *last_ptr = NULL; curl_formadd(&httppost, &last_ptr, CURLFORM_COPYNAME, "sendfile", CURLFORM_FILE, filename, CURLFORM_END); curl_formadd(&httppost, &last_ptr, CURLFORM_COPYNAME, "submit", CURLFORM_COPYCONTENTS, "send", CURLFORM_END); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, upload_response); curl_easy_setopt(curl, CURLOPT_HTTPPOST, httppost); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { sprintf(last_error, "%s", curl_easy_strerror(res)); } curl_easy_cleanup(curl); curl_formfree(httppost); } return result; } int barberry_download_file(const char *host, int id, const char *filename) { result = 0; file = fopen(filename, "wb"); if (!file) { sprintf(last_error, "%s", "Can't create file"); return -1; } curl_global_init(CURL_GLOBAL_ALL); CURL *curl = curl_easy_init(); if (curl) { char buffer[1024]; sprintf(buffer, "%s/%d", host, id); curl_easy_setopt(curl, CURLOPT_URL, buffer); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, download_response); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { sprintf(last_error, "%s", curl_easy_strerror(res)); result = -1; } curl_easy_cleanup(curl); } fclose(file); return result; } int barberry_delete_file(const char *host, int id) { result = 0; curl_global_init(CURL_GLOBAL_ALL); CURL *curl = curl_easy_init(); if (curl) { char buffer[1024]; sprintf(buffer, "%s/%d", host, id); curl_easy_setopt(curl, CURLOPT_URL, buffer); curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, delete_response); CURLcode res = curl_easy_perform(curl); if (res != CURLE_OK) { sprintf(last_error, "%s", curl_easy_strerror(res)); result = -1; } curl_easy_cleanup(curl); } return result; }
barberry.c #include <postgres.h> #include <fmgr.h> #include "barberry_impl.h" #ifdef PG_MODULE_MAGIC PG_MODULE_MAGIC; #endif PG_FUNCTION_INFO_V1(bb_upload_file); PG_FUNCTION_INFO_V1(bb_download_file); PG_FUNCTION_INFO_V1(bb_delete_file); char* text_to_string(text *txt) { size_t size = VARSIZE(txt) - VARHDRSZ; char *buffer = (char*)palloc(size + 1); memcpy(buffer, VARDATA(txt), size); buffer[size] = '\0'; return buffer; } Datum bb_upload_file(PG_FUNCTION_ARGS) { char *host = text_to_string(PG_GETARG_TEXT_P(0)); char *filename = text_to_string(PG_GETARG_TEXT_P(1)); int result = barberry_upload_file(host, filename); if (result == -1) { elog(ERROR, "%s", barberry_error()); } pfree(host); pfree(filename); PG_RETURN_INT32(result); } Datum bb_download_file(PG_FUNCTION_ARGS) { char *host = text_to_string(PG_GETARG_TEXT_P(0)); int id = PG_GETARG_INT32(1); char *filename = text_to_string(PG_GETARG_TEXT_P(2)); int result = barberry_download_file(host, id, filename); if (result == -1) { elog(ERROR, "%s", barberry_error()); } pfree(host); pfree(filename); PG_RETURN_VOID(); } Datum bb_delete_file(PG_FUNCTION_ARGS) { char *host = text_to_string(PG_GETARG_TEXT_P(0)); int id = PG_GETARG_INT32(1); int result = barberry_delete_file(host, id); if (result == -1) { elog(ERROR, "%s", barberry_error()); } pfree(host); PG_RETURN_VOID(); }
barberry_test.c #include "barberry_impl.h" void print_help() { fprintf(stdout, "Usage:\n"); fprintf(stdout, " bbtest upload my.service.local /home/username/image1000.png\n"); fprintf(stdout, " bbtest download my.service.local 1000 /home/username/image1000.png\n"); fprintf(stdout, " bbtest delete my.service.local 1000\n\n"); } int main(int argc, char *argv[]) { (void)argc; (void)argv; if (argc <= 2) { print_help(); return 0; } if (!strcmp(argv[1], "upload")) { if (argc != 4) { print_help(); return 0; } int id = barberry_upload_file(argv[2], argv[3]); if (id != -1) { fprintf(stdout, "File uploaded with id %d\n", id); } else { fprintf(stderr, "%s\n", barberry_error()); } } else if (!strcmp(argv[1], "download")) { if (argc != 5) { print_help(); return 0; } int result = barberry_download_file(argv[2], atoi(argv[3]), argv[4]); if (result != -1) { fprintf(stdout, "%s\n", "File downloaded"); } else { fprintf(stderr, "%s\n", barberry_error()); } } else if (!strcmp(argv[1], "delete")) { if (argc != 4) { print_help(); return 0; } int result = barberry_delete_file(argv[2], atoi(argv[3])); if (result != -1) { fprintf(stdout, "%s\n", "File deleted"); } else { fprintf(stderr, "%s\n", barberry_error()); } } else { print_help(); } return 0; }
рдмрд╛рд░рдмреЗрд░реА - 1.0.sql CREATE OR REPLACE FUNCTION public.bb_upload_file ( p_host text, p_filename text ) RETURNS integer AS 'barberry', 'bb_upload_file' LANGUAGE c VOLATILE STRICT; CREATE OR REPLACE FUNCTION public.bb_download_file ( p_host text, p_id integer, p_filename text ) RETURNS void AS 'barberry', 'bb_download_file' LANGUAGE c VOLATILE STRICT; CREATE OR REPLACE FUNCTION public.bb_delete_file ( p_host text, p_id integer ) RETURNS void AS 'barberry', 'bb_delete_file' LANGUAGE c VOLATILE STRICT
рдиреЛрдЯ
- рдЪреВрдВрдХрд┐ рдбрд╛рдпрдиреЗрдорд┐рдХ рд▓рд╛рдЗрдмреНрд░реЗрд░реА рдкреЛрд╕реНрдЯрдЧреНрд░реЗрдЬ (DBMS рдХреЗ рд▓рд┐рдП рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛) рдХреА рдУрд░ рд╕реЗ рднрд░реА рд╣реБрдИ рд╣реИ, рдЗрд╕рдореЗрдВ рдбрд╛рдЙрдирд▓реЛрдб рдХреА рдЧрдИ рдлрд╝рд╛рдЗрд▓реЛрдВ рддрдХ рдкрд╣реБрдВрдЪ рдФрд░ рд╕рд╣реЗрдЬреА рдЧрдИ рдлрд╝рд╛рдЗрд▓реЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХрд╛ рдЕрдзрд┐рдХрд╛рд░ рднреА рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред
- рдЖрдк PostgreSQL рд╕реЗ рдХрд░реНрд▓ рддрдХ рдкрд╣реБрдВрдЪрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рдмрдирд╛рдХрд░ рд╡рд┐рдЪрд╛рд░ рдХрд╛ рд╡рд┐рд╕реНрддрд╛рд░ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, XML рдлреЙрд░реНрдореЗрдЯ рдореЗрдВ рдлреЙрд░реНрдо, рд╣реЗрдбрд░ рдФрд░ рдмрд╛рдХреА рд╕рднреА рдЪреАрдЬреЛрдВ рдХрд╛ рд╡рд┐рд╡рд░рдг рдЦрд░рд╛рдм рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдлрд┐рд░ C рдХреЛрдб рдореЗрдВ рдкрд╛рд░реНрд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░ рдХрд░реНрд▓ рдореЗрдВ рд╕рдВрдмрдВрдзрд┐рдд рдХрдорд╛рдВрдбреНрд╕ рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░реЗрдВрдЧреЗред
рд╕рдВрджрд░реНрдн
- PostgreSQL рдкреНрд░рд▓реЗрдЦрди
- рдХрд░реНрд▓ рдкреНрд░рд▓реЗрдЦрди
- рдЬрд╛рдирд╕рди рдкреНрд░рд▓реЗрдЦрди
- PostgreSQL рдореЗрдВ C рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд╛рд░реНрдп ред
- PostgreSQL рдореЗрдВ рдПрдХреНрд╕рдЯреЗрдВрд╢рди рдмрдирд╛рдирд╛ ред