{"id":206576,"date":"2013-12-23T03:09:02","date_gmt":"2013-12-22T23:09:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=206576"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=206576","title":{"rendered":"<span class=\"post_title\">\u0412\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 PostgreSQL \u0441 \u0432\u043d\u0435\u0448\u043d\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439<\/span>"},"content":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" align=\"right\" src=\"http:\/\/habr.habrastorage.org\/post_images\/31d\/418\/41f\/31d41841f8783931a3bab223e42d272b.png\"\/><br \/>  \u0414\u043e\u0431\u0440\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0443\u0442\u043e\u043a. \u041f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u0430 \u0438\u043d\u043e\u0433\u0434\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c, \u043a\u0430\u043a \u0438 \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u0421\u0440\u0435\u0434\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435:  <\/p>\n<ul>\n<li>\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u0432 \u0411\u0414<\/li>\n<li>\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435, \u0432 \u0411\u0414 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430<\/li>\n<li>\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0435<\/li>\n<\/ul>\n<p>  \u0425\u043e\u0442\u044c <b>PostgreSQL<\/b> \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432 \u0411\u0414 \u0444\u0430\u0439\u043b\u043e\u0432 (\u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 <i>bytea<\/i> \u043f\u043e\u043b\u044f\u0445 \u0438\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 <a href=\"http:\/\/www.postgresql.org\/docs\/9.3\/static\/largeobjects.html\">large objects<\/a>), \u044d\u0442\u043e \u043d\u0430\u0438\u043c\u0435\u043d\u0435\u0435 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u043a\u0430\u043a \u0432 \u043f\u043b\u0430\u043d\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438, \u0442\u0430\u043a \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u0435\u043c\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438. \u0414\u0440\u0443\u0433\u043e\u0439, \u043e\u0431\u0449\u0435\u043f\u0440\u0438\u043d\u044f\u0442\u043e\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0439, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0432 \u0432\u0438\u0434\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435, \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0443\u0442\u044c \u043a \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044e. \u0418\u0437 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432 \u2014 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u0418 \u0442\u0440\u0435\u0442\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u2014 \u0434\u043b\u044f \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043c\u0430\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u043b\u0435\u0442\u0443, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0430. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 <b>PostgreSQL<\/b> \u0441 \u0442\u0430\u043a\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c.<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h4>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f<\/h4>\n<p>  \u041e\u0431\u0440\u0438\u0441\u0443\u0435\u043c \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043a\u0430\u0440\u0442\u0438\u043d\u0443 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u044f\u0449\u0435\u0433\u043e. \u0423 \u043d\u0430\u0441 \u0438\u043c\u0435\u0435\u0442\u0441\u044f http-\u0441\u0435\u0440\u0432\u0438\u0441, \u043f\u043e \u0442\u0438\u043f\u0443 <a href=\"https:\/\/github.com\/Magomogo\/barberry-service\">\u044d\u0442\u043e\u0433\u043e<\/a>, \u0434\u043b\u044f \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u044e\u0449\u0438\u0439 \u0442\u0430\u043a\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b:  <\/p>\n<ul>\n<li>\u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u2014 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 POST-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0441 \u0444\u043e\u0440\u043c\u043e\u0439, \u0432 \u043e\u0442\u0432\u0435\u0442 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442 JSON \u0441 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0435\u0439 \u043e\u0431 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0438, \u0441\u0440\u0435\u0434\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u0433\u0435\u043d\u0435\u0440\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440<\/li>\n<li>\u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u2014 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 GET-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f <i><a href=\"http:\/\/my.service.local\/1001\">my.service.local\/1001<\/a><\/i><\/li>\n<li>\u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u2014 \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0430 DELETE-\u0437\u0430\u043f\u0440\u043e\u0441\u0430 c \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u043e\u043c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f <i><a href=\"http:\/\/my.service.local\/1001\">my.service.local\/1001<\/a><\/i><\/li>\n<\/ul>\n<p>  \u0412 \u0411\u0414 \u0431\u0443\u0434\u0443\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440\u044b \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439, \u0432 \u0442\u0430\u043a\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043d\u0430 \u0441\u0442\u0440\u0430\u043d\u0438\u0446\u0430\u0445 \u0441\u0430\u0439\u0442\u0430 \u043c\u043e\u0436\u043d\u043e \u0431\u0443\u0434\u0435\u0442 \u0432\u0442\u0440\u0430\u0438\u0432\u0430\u0442\u044c \u0442\u0435\u0433\u0438 \u0432\u0438\u0434\u0430:  <\/p>\n<pre>&lt;img src=&quot;http:\/\/my.service.local\/1001&quot;\/&gt;<\/pre>\n<p>  \u0421\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f \u0437\u0430\u0433\u0440\u0443\u0437\u043a\u0430 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f (\u0440\u0430\u0432\u043d\u043e \u043a\u0430\u043a \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435) \u0434\u043e\u043b\u0436\u043d\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0435\u0442\u044c \u043a\u0430\u043a \u0432\u044b\u0437\u043e\u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <i>upload_image<\/i> (\u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u043c <i>filename<\/i>), \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u0442 \u0438\u0434\u0435\u043d\u0442\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0435, \u0437\u0430\u043f\u0438\u0441\u0443\u0435\u043c\u044b\u0439 \u0437\u0430\u0442\u0435\u043c \u0432 \u0442\u0430\u0431\u043b\u0438\u0446\u0443. \u0422\u0430\u043a \u043a\u0430\u043a \u043d\u0430\u043f\u0440\u044f\u043c\u0443\u044e \u0438\u0437 <b>PostgreSQL<\/b> \u043d\u0435\u043b\u044c\u0437\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0438\u0442\u0441\u044f \u043a http \u0437\u0430\u043f\u0440\u043e\u0441\u0430\u043c, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u043d\u0430 \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445 \u043d\u0430 \u0421, \u0430 \u0432 \u043d\u0438\u0445 \u0443\u0436\u0435 \u0435\u0441\u0442\u044c \u0433\u0434\u0435 \u0440\u0430\u0437\u0433\u0443\u043b\u044f\u0442\u0441\u044f. \u0414\u043b\u044f \u043f\u0440\u043e\u0441\u0442\u043e\u0442\u044b, \u043e\u0431\u043e\u0439\u0434\u0451\u043c\u0441\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c\u0438 <b>curl<\/b> \u0438 <b>jansson<\/b> (\u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044f\u044f \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 JSON). \u041c\u043e\u0436\u0435\u043c \u043d\u0430\u0447\u0438\u043d\u0430\u0442\u044c.<\/p>\n<p>  \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0432 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 <i>barberry_impl.h<\/i> \u043d\u0430\u0448\u0438 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439:  <\/p>\n<pre><code class=\"cpp\">\/\/ 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); <\/code><\/pre>\n<p>  \u0412 \u0444\u0430\u0439\u043b\u0435 \u0441 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c \u043a\u043e\u0434\u043e\u043c <i>barberry_impl.c<\/i> \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u0433\u043b\u043e\u0431\u0430\u043b\u044c\u043d\u044b\u0435 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435:  <\/p>\n<pre><code class=\"cpp\">char last_error[1024]; FILE *file = NULL; int result = 0; <\/code><\/pre>\n<p>  \u041f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0430\u044f <i>last_error<\/i> \u0431\u0443\u0434\u0435\u0442 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u043e\u0448\u0438\u0431\u043a\u0443, <i>file<\/i> \u2014 \u044d\u0442\u043e \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0444\u0430\u0439\u043b, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0439 \u043f\u0440\u0438 \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u0438 \u0434\u0430\u043d\u043d\u044b\u0445 \u043e\u0442 \u0441\u0435\u0440\u0432\u0438\u0441\u0430, \u0430 \u0432 <i>result<\/i> \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0442\u0441\u044f \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0440\u0430\u0431\u043e\u0442\u044b \u0441 \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c.<\/p>\n<p>  \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <i>barberry_error<\/i> \u0442\u0440\u0438\u0432\u0438\u0430\u043b\u044c\u043d\u0430 \u2014 \u0432\u043e\u0437\u0432\u0440\u0430\u0442 <i>last_error<\/i>. \u0420\u0430\u0437\u0431\u0435\u0440\u0435\u043c \u043f\u043e\u0434\u0440\u043e\u0431\u043d\u043e \u0444\u0443\u043d\u043a\u0446\u0438\u044e <i>barberry_upload_file<\/i>.<\/p>\n<p>  \u041f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c, \u043a\u0430\u043a \u043d\u0430\u0447\u0430\u0442\u044c \u0440\u0430\u0431\u043e\u0442\u0443 \u0441 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u043e\u0439 <b>curl<\/b>, \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043f\u0440\u043e\u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u043e\u043a\u0440\u0443\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043d\u0435\u0451 (\u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 <i>curl_gobal_init<\/i>) \u0438 \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0441\u0435\u0441\u0441\u0438\u044e (\u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 <i>curl_easy_init<\/i>, \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u044e\u0449\u0435\u0439 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u0445\u044d\u043d\u0434\u043b \u0441\u0435\u0441\u0441\u0438\u0438). \u0414\u0430\u043b\u0435\u0435, \u0441\u043e\u0437\u0434\u0430\u0435\u043c submit-\u0444\u043e\u0440\u043c\u0443 (\u0447\u0435\u0440\u0435\u0437 <i>curl_formadd<\/i>) \u0438 \u0437\u0430\u043f\u043e\u043b\u043d\u044f\u0435\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435 \u043e\u043f\u0446\u0438\u0438:  <\/p>\n<ul>\n<li>CURLOPT_URL \u2014 \u0445\u043e\u0441\u0442, \u0441 \u043a\u043e\u0442\u043e\u0440\u044b\u043c \u043c\u044b \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c<\/li>\n<li>CURLOPT_HTTPPOST \u2014 \u0444\u043e\u0440\u043c\u0430, \u043e\u0442\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u0430\u044f \u043c\u0435\u0442\u043e\u0434\u043e\u043c POST<\/li>\n<li>CURLOPT_WRITEFUNCTION \u2014 CALLBACK-\u0444\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u043e\u0442\u0432\u0435\u0442\u0430 \u043e\u0442 \u0445\u043e\u0441\u0442\u0430<\/li>\n<\/ul>\n<p>  \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f <i>barberry_upload_file<\/i>:  <\/p>\n<pre><code class=\"cpp\">int barberry_upload_file(const char *host, const char *filename) { \tresult = -1;  \tcurl_global_init(CURL_GLOBAL_ALL);  \tCURL *curl = curl_easy_init();  \tif (curl) \t{ \t\tcurl_easy_setopt(curl, CURLOPT_URL, host);  \t\tstruct curl_httppost *httppost = NULL; \t\tstruct curl_httppost *last_ptr = NULL;  \t\tcurl_formadd(&httppost, &last_ptr, CURLFORM_COPYNAME, &quot;sendfile&quot;, CURLFORM_FILE, filename, CURLFORM_END); \t\tcurl_formadd(&httppost, &last_ptr, CURLFORM_COPYNAME, &quot;submit&quot;, CURLFORM_COPYCONTENTS, &quot;send&quot;, CURLFORM_END);  \t\tcurl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, upload_response); \t\tcurl_easy_setopt(curl, CURLOPT_HTTPPOST, httppost);  \t\tCURLcode res = curl_easy_perform(curl);  \t\tif (res != CURLE_OK) \t\t{ \t\t\tsprintf(last_error, &quot;%s&quot;, curl_easy_strerror(res)); \t\t}  \t\tcurl_easy_cleanup(curl); \t\tcurl_formfree(httppost); \t}  \treturn result; } <\/code><\/pre>\n<p>  CALLBACK-\u0444\u0443\u043d\u043a\u0446\u0438\u044f <i>upload_response<\/i> \u0438\u043c\u0435\u0435\u0442 \u043f\u0440\u043e\u0442\u043e\u0442\u0438\u043f:  <\/p>\n<pre><code class=\"cpp\">size_t function(char *ptr, size_t size, size_t nmemb, void *userdata); <\/code><\/pre>\n<p>  \u0441 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u043c\u0438:  <\/p>\n<ul>\n<li>ptr \u2014 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u043c\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435<\/li>\n<li>size * nmemb \u2014 \u0438\u0445 \u0440\u0430\u0437\u043c\u0435\u0440<\/li>\n<li>userdata \u2014 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 FILE*, \u043f\u0440\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u043c\u044b\u0439 \u0447\u0435\u0440\u0435\u0437 \u043e\u043f\u0446\u0438\u044e CURLOPT_WRITEDATA<\/li>\n<\/ul>\n<p>  \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043e\u043b\u0436\u043d\u0430 \u0432\u043e\u0437\u0440\u0430\u0442\u0438\u0442\u044c \u0444\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u043e\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u043d\u043d\u044b\u0445 \u0434\u0430\u043d\u043d\u044b\u0445, \u0442.\u0435. size * nmemb. \u0412 \u0434\u0430\u043d\u043d\u043e\u043c, \u0432 \u044d\u0442\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u0442\u044c JSON \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0439 \u0432 \u043e\u0442\u0432\u0435\u0442\u0435:  <\/p>\n<pre><code class=\"cpp\">size_t upload_response(char *ptr, size_t size, size_t nmemb, void *userdata) { \t(void)userdata;  \tparse_upload_response(ptr);  \treturn size * nmemb; } <\/code><\/pre>\n<p>  \u041f\u043e\u0440\u0443\u0447\u0438\u043c \u044d\u0442\u043e \u0434\u0440\u0443\u0433\u043e\u0439 \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u043c <b>jansson<\/b> \u0434\u043b\u044f \u0440\u0430\u0437\u0431\u043e\u0440\u0430 \u043e\u0442\u0432\u0435\u0442\u0430:  <\/p>\n<pre><code class=\"cpp\">void parse_upload_response(const char *text) { \tif (!strcmp(text, &quot;{}&quot;)) \t{ \t\tsprintf(last_error, &quot;%s&quot;, &quot;Empty file&quot;);  \t\treturn; \t}  \tjson_error_t error;  \tjson_t *root = json_loads(text, 0, &error);  \tif (!root) \t{ \t\tsprintf(last_error, &quot;%s&quot;, text);  \t\treturn; \t}  \tjson_t *id = json_object_get(root, &quot;id&quot;);  \tif(!json_is_integer(id)) \t{ \t\tsprintf(last_error, &quot;%s&quot;, text);  \t\tjson_decref(root);  \t\treturn; \t}  \tresult = json_integer_value(id);  \tjson_decref(root); } <\/code><\/pre>\n<p>  \u0412 \u0441\u043b\u0443\u0447\u0430\u0435 \u043f\u0443\u0441\u0442\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430, \u043d\u0430\u043c \u043f\u0440\u0438\u0439\u0434\u0451\u0442 \u043e\u0442\u0432\u0435\u0442 {}, \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0435\u043c \u044d\u0442\u043e\u0442 \u0441\u043b\u0443\u0447\u0430\u0439. \u0415\u0441\u043b\u0438 \u0432\u0441\u0451 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u0444\u0430\u0439\u043b \u0431\u044b\u043b \u0443\u0441\u043f\u0435\u0448\u043d\u043e \u0437\u0430\u0433\u0440\u0443\u0436\u0435\u043d \u043e\u0442\u0432\u0435\u0442 \u043f\u0440\u0438\u0439\u0434\u0435\u0442 \u0432 \u0432\u0438\u0434\u0435: { \u00abid\u00bb:1001, \u00abext\u00bb:\u00abpng\u00bb\u2026 }. \u0418\u043d\u0442\u0435\u0440\u0435\u0441\u0443\u0435\u0442 \u0442\u043e\u043b\u044c\u043a\u043e id, \u0435\u0433\u043e \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u043c \u0432 result.<\/p>\n<p>  \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0434\u043b\u044f \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0444\u0430\u0439\u043b\u0430 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043f\u0440\u043e\u0449\u0435 \u2014 \u043d\u0443\u0436\u043d\u043e \u043b\u0438\u0448\u044c \u0441\u0444\u043e\u0440\u043c\u0438\u0440\u043e\u0432\u0430\u0442\u044c GET-\u0437\u0430\u043f\u0440\u043e\u0441, \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u043e\u0442\u0432\u0435\u0442 \u0438 \u0437\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u0435\u0433\u043e \u0432 \u0444\u0430\u0439\u043b (\u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0432 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044e, \u043a\u043e\u0433\u0434\u0430 \u0444\u0430\u0439\u043b \u0441 \u043d\u0443\u0436\u043d\u044b\u043c id \u043d\u0435 \u043d\u0430\u0439\u0434\u0435\u043d):  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">barberry_download_file<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">int barberry_download_file(const char *host, int id, const char *filename) { \tresult = 0;  \tfile = fopen(filename, &quot;wb&quot;);  \tif (!file) \t{ \t\tsprintf(last_error, &quot;%s&quot;, &quot;Can't create file&quot;);  \t\treturn -1; \t}  \tcurl_global_init(CURL_GLOBAL_ALL);  \tCURL *curl = curl_easy_init();  \tif (curl) \t{ \t\tchar buffer[1024];  \t\tsprintf(buffer, &quot;%s\/%d&quot;, host, id);  \t\tcurl_easy_setopt(curl, CURLOPT_URL, buffer); \t\tcurl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, download_response);  \t\tCURLcode res = curl_easy_perform(curl);  \t\tif (res != CURLE_OK) \t\t{ \t\t\tsprintf(last_error, &quot;%s&quot;, curl_easy_strerror(res));  \t\t\tresult = -1; \t\t}  \t\tcurl_easy_cleanup(curl); \t}  \tfclose(file);  \treturn result; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">download_response<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">size_t download_response(char *ptr, size_t size, size_t nmemb, void *userdata) { \t(void)userdata;  \tif (!strcmp(ptr, &quot;{}&quot;)) \t{ \t\tsprintf(last_error, &quot;%s&quot;, &quot;File on server not found&quot;);  \t\tresult = -1; \t} \telse \t{ \t\tfwrite(ptr, size * nmemb, 1, file); \t}  \treturn size * nmemb; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0444\u0430\u0439\u043b\u0430 \u0432 \u0441\u0435\u0440\u0432\u0438\u0441\u0435 \u2014 \u044d\u0442\u043e DELETE-\u0437\u0430\u043f\u0440\u043e\u0441 (\u0442\u0438\u043f \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u0434\u043b\u044f <b>curl<\/b> \u0443\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0447\u0435\u0440\u0435\u0437 \u043e\u043f\u0446\u0438\u044e CURLOPT_CUSTOMREQUEST):  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">barberry_delete_file<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">int barberry_delete_file(const char *host, int id) { \tresult = 0;  \tcurl_global_init(CURL_GLOBAL_ALL);  \tCURL *curl = curl_easy_init();  \tif (curl) \t{ \t\tchar buffer[1024];  \t\tsprintf(buffer, &quot;%s\/%d&quot;, host, id);  \t\tcurl_easy_setopt(curl, CURLOPT_URL, buffer); \t\tcurl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, &quot;DELETE&quot;); \t\tcurl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, delete_response);  \t\tCURLcode res = curl_easy_perform(curl);  \t\tif (res != CURLE_OK) \t\t{ \t\t\tsprintf(last_error, &quot;%s&quot;, curl_easy_strerror(res));  \t\t\tresult = -1; \t\t}  \t\tcurl_easy_cleanup(curl); \t}  \treturn result; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">delete_response<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">size_t delete_response(char *ptr, size_t size, size_t nmemb, void *userdata) { \t(void)ptr; \t(void)userdata;  \treturn size * nmemb; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041f\u0440\u0435\u0436\u0434\u0435 \u0447\u0435\u043c \u043f\u0435\u0440\u0435\u0439\u0442\u0438 \u043a PostgreSQL-\u0447\u0430\u0441\u0442\u0438, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u043a\u043e\u043d\u0441\u043e\u043b\u044c\u043d\u0443\u044e \u0443\u0442\u0438\u043b\u0438\u0442\u0443 \u0434\u043b\u044f \u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u043d\u0430\u0448\u0438\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439. \u0412 \u043d\u0435\u0439 \u043f\u0440\u043e\u0432\u0435\u0440\u044f\u0435\u043c \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b, \u0435\u0441\u043b\u0438 \u043e\u043d\u0438 \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0442 \u043e\u0436\u0438\u0434\u0430\u0435\u043c\u044b\u043c (\u043f\u0440\u0438\u043c\u0435\u0440 \u0432 <i>print_help<\/i>), \u0442\u043e \u0434\u0435\u043b\u0430\u0435\u043c \u043d\u0443\u0436\u043d\u044b\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u044f:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">barberry_test.c<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">#include &quot;barberry_impl.h&quot;  void print_help() { \tfprintf(stdout, &quot;Usage:\\n&quot;); \tfprintf(stdout, &quot;  bbtest upload my.service.local \/home\/username\/image1000.png\\n&quot;); \tfprintf(stdout, &quot;  bbtest download my.service.local 1000 \/home\/username\/image1000.png\\n&quot;); \tfprintf(stdout, &quot;  bbtest delete my.service.local 1000\\n\\n&quot;); }  int main(int argc, char *argv[]) { \t(void)argc; \t(void)argv;  \tif (argc &lt;= 2) \t{ \t\tprint_help();  \t\treturn 0; \t}  \tif (!strcmp(argv[1], &quot;upload&quot;)) \t{ \t\tif (argc != 4) \t\t{ \t\t\tprint_help();  \t\t\treturn 0; \t\t}  \t\tint id = barberry_upload_file(argv[2], argv[3]);  \t\tif (id != -1) \t\t{ \t\t\tfprintf(stdout, &quot;File uploaded with id %d\\n&quot;, id); \t\t} \t\telse \t\t{ \t\t\tfprintf(stderr, &quot;%s\\n&quot;, barberry_error()); \t\t} \t} \telse if (!strcmp(argv[1], &quot;download&quot;)) \t{ \t\tif (argc != 5) \t\t{ \t\t\tprint_help();  \t\t\treturn 0; \t\t}  \t\tint result = barberry_download_file(argv[2], atoi(argv[3]), argv[4]);  \t\tif (result != -1) \t\t{ \t\t\tfprintf(stdout, &quot;%s\\n&quot;, &quot;File downloaded&quot;); \t\t} \t\telse \t\t{ \t\t\tfprintf(stderr, &quot;%s\\n&quot;, barberry_error()); \t\t} \t} \telse if (!strcmp(argv[1], &quot;delete&quot;)) \t{ \t\tif (argc != 4) \t\t{ \t\t\tprint_help();  \t\t\treturn 0; \t\t}  \t\tint result = barberry_delete_file(argv[2], atoi(argv[3]));  \t\tif (result != -1) \t\t{ \t\t\tfprintf(stdout, &quot;%s\\n&quot;, &quot;File deleted&quot;); \t\t} \t\telse \t\t{ \t\t\tfprintf(stderr, &quot;%s\\n&quot;, barberry_error()); \t\t} \t} \telse \t{ \t\tprint_help(); \t}  \treturn 0; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0432\u0441\u0451 \u044d\u0442\u043e \u0434\u0435\u043b\u043e (\u043f\u0443\u0442\u0438 \u0432 \u0412\u0430\u0448\u0435\u0439 \u041e\u0421 \u043a \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u043c \u0444\u0430\u0439\u043b\u0430\u043c \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c \u043c\u043e\u0433\u0443\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u0441\u044f) \u0438 \u0442\u0435\u0441\u0442\u0438\u0440\u0443\u0435\u043c:  <\/p>\n<pre><code class=\"bash\">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 <\/code><\/pre>\n<p>  \u0415\u0441\u043b\u0438 \u0432\u0441\u0451 \u0432 \u043f\u043e\u0440\u044f\u0434\u043a\u0435, \u043c\u043e\u0436\u043d\u043e \u043f\u0435\u0440\u0435\u0445\u043e\u0434\u0438\u0442 \u043a PostgreSQL-\u0447\u0430\u0441\u0442\u0438 \u043d\u0430\u0448\u0435\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 (\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0439 \u043e \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445 \u043d\u0430 C \u0432 PostgreSQL \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 <b>[4]<\/b>).<\/p>\n<p>  \u041e\u0431\u044c\u044f\u0432\u0438\u043c \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0435 \u0434\u043b\u044f \u0411\u0414 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 (\u0441 \u0432\u0435\u0440\u0441\u0438\u0435\u0439 1):  <\/p>\n<pre><code class=\"cpp\">PG_FUNCTION_INFO_V1(bb_upload_file); PG_FUNCTION_INFO_V1(bb_download_file); PG_FUNCTION_INFO_V1(bb_delete_file); <\/code><\/pre>\n<p>  \u0414\u043b\u044f \u043a\u043e\u043d\u0432\u0435\u0440\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0437 text (\u0442\u0438\u043f \u0432 PostgreSQL) \u0432 c-string \u043f\u043e\u043c\u043e\u0436\u0435\u0442 \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u044f:  <\/p>\n<pre><code class=\"cpp\">char* text_to_string(text *txt) { \tsize_t size = VARSIZE(txt) - VARHDRSZ;  \tchar *buffer = (char*)palloc(size + 1);  \tmemcpy(buffer, VARDATA(txt), size);  \tbuffer[size] = '\\0';  \treturn buffer; } <\/code><\/pre>\n<p>  \u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u043c\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0437\u0430\u043a\u043b\u044e\u0447\u0430\u0435\u0442\u0441\u044f \u0432 \u0434\u0435\u043b\u0435\u0433\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0438 \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u043e\u043c\u0443 \u0440\u0430\u043d\u0435\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u0443, \u0441 \u0433\u0435\u043d\u0435\u0440\u0430\u0446\u0438\u0435\u0439 \u043e\u0448\u0438\u0431\u043a\u0438, \u0435\u0441\u043b\u0438 \u0447\u0442\u043e-\u0442\u043e \u043f\u043e\u0448\u043b\u043e \u043d\u0435 \u0442\u0430\u043a:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">bb_upload_file<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">Datum bb_upload_file(PG_FUNCTION_ARGS) { \tchar *host = text_to_string(PG_GETARG_TEXT_P(0)); \tchar *filename = text_to_string(PG_GETARG_TEXT_P(1));  \tint result = barberry_upload_file(host, filename);  \tif (result == -1) \t{ \t\telog(ERROR, &quot;%s&quot;, barberry_error()); \t}  \tpfree(host); \tpfree(filename);  \tPG_RETURN_INT32(result); } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">bb_download_file<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">Datum bb_download_file(PG_FUNCTION_ARGS) { \tchar *host = text_to_string(PG_GETARG_TEXT_P(0)); \tint id = PG_GETARG_INT32(1); \tchar *filename = text_to_string(PG_GETARG_TEXT_P(2));  \tint result = barberry_download_file(host, id, filename);  \tif (result == -1) \t{ \t\telog(ERROR, &quot;%s&quot;, barberry_error()); \t}  \tpfree(host); \tpfree(filename);  \tPG_RETURN_VOID(); } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">bb_delete_file<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">Datum bb_delete_file(PG_FUNCTION_ARGS) { \tchar *host = text_to_string(PG_GETARG_TEXT_P(0)); \tint id = PG_GETARG_INT32(1);  \tint result = barberry_delete_file(host, id);  \tif (result == -1) \t{ \t\telog(ERROR, &quot;%s&quot;, barberry_error()); \t}  \tpfree(host);  \tPG_RETURN_VOID(); } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0421\u043e\u0431\u0438\u0440\u0430\u0435\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0438 \u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u0435\u0435 \u043a <b>PostgreSQL<\/b> (\u043f\u0443\u0442\u0438 \u0432 \u0412\u0430\u0448\u0435\u0439 \u041e\u0421 \u043a \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043e\u0447\u043d\u044b\u043c \u0444\u0430\u0439\u043b\u0430\u043c \u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430\u043c \u043c\u043e\u0433\u0443\u0442 \u043e\u0442\u043b\u0438\u0447\u0430\u0442\u0441\u044f):  <\/p>\n<pre><code class=\"bash\">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 <\/code><\/pre>\n<p>  SQL-\u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0432 \u0411\u0414, \u0438\u043c\u0435\u044e\u0442 \u0432\u0438\u0434:  <\/p>\n<pre><code class=\"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; <\/code><\/pre>\n<p>  \u041e\u0444\u043e\u0440\u043c\u0438\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0438 SQL-\u0441\u043a\u0440\u0438\u043f\u0442 \u0432 \u0432\u0438\u0434\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043a PostgreSQL (\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0435 \u043e\u043f\u0438\u0441\u0430\u043d\u043e \u0432 <b>[5]<\/b>). \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0444\u0430\u0439\u043b <i>barberry.control<\/i>:  <\/p>\n<pre><code class=\"bash\"># BarBerry image service comment = 'BarBerry image service' default_version = '1.0' module_pathname = '$libdir\/barberry' relocatable = true <\/code><\/pre>\n<p>  SQL-\u0441\u043a\u0440\u0438\u043f\u0442 \u0434\u043b\u044f \u043d\u0430\u0448\u0435\u0433\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043d\u0430\u0437\u0432\u0430\u0442\u044c \u043a\u0430\u043a <i>barberry&#8212;1.0.sql<\/i> (\u0441\u043e\u0433\u043b\u0430\u0441\u043d\u043e \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438 <b>PostgreSQL<\/b>). \u0421\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u043c \u044d\u0442\u0438 \u0434\u0432\u0430 \u0444\u0430\u0439\u043b\u0430 \u0442\u0443\u0434\u0430, \u0433\u0434\u0435 <b>PostgreSQL<\/b> \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0441\u0432\u043e\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f.<\/p>\n<p>  \u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043f\u0440\u0435\u0434\u0435\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0435:  <\/p>\n<pre><code class=\"sql\">CREATE EXTENSION barberry; UPDATE avatar SET image = bb_upload_file ( 'my.service.local', 'images\/avatar_admin.png' ) WHERE name = 'admin'; <\/code><\/pre>\n<p>  <\/p>\n<h4>\u0418\u0441\u0445\u043e\u0434\u043d\u044b\u0435 \u0444\u0430\u0439\u043b\u044b<\/h4>\n<p>  \u0411\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0432\u044b\u0448\u0430 \u043a\u0430\u043a \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0430\u044f \u0443\u0442\u0438\u043b\u0438\u0442\u0430, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0435 \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u0430 \u043d\u0430 github. \u0414\u043b\u044f \u043e\u0431\u043b\u0435\u0433\u0447\u0435\u043d\u0438\u044f \u0441\u0431\u043e\u0440\u043a\u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d Makefile \u0441 \u0446\u0435\u043b\u044f\u043c\u0438 barberry, barberry_test, clean, rebuild, install.  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">barberry_impl.h<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">#ifndef BARBERRY_IMPL_H #define BARBERRY_IMPL_H  #include &lt;stdio.h&gt; #include &lt;string.h&gt; #include &lt;curl\/curl.h&gt; #include &lt;jansson.h&gt;  \/\/ 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 <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">barberry_impl.c<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">#include &quot;barberry_impl.h&quot;  char last_error[1024]; FILE *file = NULL; int result = 0;  void parse_upload_response(const char *text) { \tif (!strcmp(text, &quot;{}&quot;)) \t{ \t\tsprintf(last_error, &quot;%s&quot;, &quot;Empty file&quot;);  \t\treturn; \t}  \tjson_error_t error;  \tjson_t *root = json_loads(text, 0, &error);  \tif (!root) \t{ \t\tsprintf(last_error, &quot;%s&quot;, text);  \t\treturn; \t}  \tjson_t *id = json_object_get(root, &quot;id&quot;);  \tif(!json_is_integer(id)) \t{ \t\tsprintf(last_error, &quot;%s&quot;, text);  \t\tjson_decref(root);  \t\treturn; \t}  \tresult = json_integer_value(id);  \tjson_decref(root); }  size_t upload_response(char *ptr, size_t size, size_t nmemb, void *userdata) { \t(void)userdata;  \tparse_upload_response(ptr);  \treturn size * nmemb; }  size_t download_response(char *ptr, size_t size, size_t nmemb, void *userdata) { \t(void)userdata;  \tif (!strcmp(ptr, &quot;{}&quot;)) \t{ \t\tsprintf(last_error, &quot;%s&quot;, &quot;File on server not found&quot;);  \t\tresult = -1; \t} \telse \t{ \t\tfwrite(ptr, size * nmemb, 1, file); \t}  \treturn size * nmemb; }  size_t delete_response(char *ptr, size_t size, size_t nmemb, void *userdata) { \t(void)ptr; \t(void)userdata;  \treturn size * nmemb; }   char* barberry_error() { \treturn last_error; }  int barberry_upload_file(const char *host, const char *filename) { \tresult = -1;  \tcurl_global_init(CURL_GLOBAL_ALL);  \tCURL *curl = curl_easy_init();  \tif (curl) \t{ \t\tcurl_easy_setopt(curl, CURLOPT_URL, host);  \t\tstruct curl_httppost *httppost = NULL; \t\tstruct curl_httppost *last_ptr = NULL;  \t\tcurl_formadd(&httppost, &last_ptr, CURLFORM_COPYNAME, &quot;sendfile&quot;, CURLFORM_FILE, filename, CURLFORM_END); \t\tcurl_formadd(&httppost, &last_ptr, CURLFORM_COPYNAME, &quot;submit&quot;, CURLFORM_COPYCONTENTS, &quot;send&quot;, CURLFORM_END);  \t\tcurl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, upload_response); \t\tcurl_easy_setopt(curl, CURLOPT_HTTPPOST, httppost);  \t\tCURLcode res = curl_easy_perform(curl);  \t\tif (res != CURLE_OK) \t\t{ \t\t\tsprintf(last_error, &quot;%s&quot;, curl_easy_strerror(res)); \t\t}  \t\tcurl_easy_cleanup(curl); \t\tcurl_formfree(httppost); \t}  \treturn result; }  int barberry_download_file(const char *host, int id, const char *filename) { \tresult = 0;  \tfile = fopen(filename, &quot;wb&quot;);  \tif (!file) \t{ \t\tsprintf(last_error, &quot;%s&quot;, &quot;Can't create file&quot;);  \t\treturn -1; \t}  \tcurl_global_init(CURL_GLOBAL_ALL);  \tCURL *curl = curl_easy_init();  \tif (curl) \t{ \t\tchar buffer[1024];  \t\tsprintf(buffer, &quot;%s\/%d&quot;, host, id);  \t\tcurl_easy_setopt(curl, CURLOPT_URL, buffer); \t\tcurl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, download_response);  \t\tCURLcode res = curl_easy_perform(curl);  \t\tif (res != CURLE_OK) \t\t{ \t\t\tsprintf(last_error, &quot;%s&quot;, curl_easy_strerror(res));  \t\t\tresult = -1; \t\t}  \t\tcurl_easy_cleanup(curl); \t}  \tfclose(file);  \treturn result; }  int barberry_delete_file(const char *host, int id) { \tresult = 0;  \tcurl_global_init(CURL_GLOBAL_ALL);  \tCURL *curl = curl_easy_init();  \tif (curl) \t{ \t\tchar buffer[1024];  \t\tsprintf(buffer, &quot;%s\/%d&quot;, host, id);  \t\tcurl_easy_setopt(curl, CURLOPT_URL, buffer); \t\tcurl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, &quot;DELETE&quot;); \t\tcurl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, delete_response);  \t\tCURLcode res = curl_easy_perform(curl);  \t\tif (res != CURLE_OK) \t\t{ \t\t\tsprintf(last_error, &quot;%s&quot;, curl_easy_strerror(res));  \t\t\tresult = -1; \t\t}  \t\tcurl_easy_cleanup(curl); \t}  \treturn result; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">barberry.c<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">#include &lt;postgres.h&gt; #include &lt;fmgr.h&gt;  #include &quot;barberry_impl.h&quot;  #ifdef PG_MODULE_MAGIC \tPG_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) { \tsize_t size = VARSIZE(txt) - VARHDRSZ;  \tchar *buffer = (char*)palloc(size + 1);  \tmemcpy(buffer, VARDATA(txt), size);  \tbuffer[size] = '\\0';  \treturn buffer; }  Datum bb_upload_file(PG_FUNCTION_ARGS) { \tchar *host = text_to_string(PG_GETARG_TEXT_P(0)); \tchar *filename = text_to_string(PG_GETARG_TEXT_P(1));  \tint result = barberry_upload_file(host, filename);  \tif (result == -1) \t{ \t\telog(ERROR, &quot;%s&quot;, barberry_error()); \t}  \tpfree(host); \tpfree(filename);  \tPG_RETURN_INT32(result); }  Datum bb_download_file(PG_FUNCTION_ARGS) { \tchar *host = text_to_string(PG_GETARG_TEXT_P(0)); \tint id = PG_GETARG_INT32(1); \tchar *filename = text_to_string(PG_GETARG_TEXT_P(2));  \tint result = barberry_download_file(host, id, filename);  \tif (result == -1) \t{ \t\telog(ERROR, &quot;%s&quot;, barberry_error()); \t}  \tpfree(host); \tpfree(filename);  \tPG_RETURN_VOID(); }  Datum bb_delete_file(PG_FUNCTION_ARGS) { \tchar *host = text_to_string(PG_GETARG_TEXT_P(0)); \tint id = PG_GETARG_INT32(1);  \tint result = barberry_delete_file(host, id);  \tif (result == -1) \t{ \t\telog(ERROR, &quot;%s&quot;, barberry_error()); \t}  \tpfree(host);  \tPG_RETURN_VOID(); } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">barberry_test.c<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">#include &quot;barberry_impl.h&quot;  void print_help() { \tfprintf(stdout, &quot;Usage:\\n&quot;); \tfprintf(stdout, &quot;  bbtest upload my.service.local \/home\/username\/image1000.png\\n&quot;); \tfprintf(stdout, &quot;  bbtest download my.service.local 1000 \/home\/username\/image1000.png\\n&quot;); \tfprintf(stdout, &quot;  bbtest delete my.service.local 1000\\n\\n&quot;); }  int main(int argc, char *argv[]) { \t(void)argc; \t(void)argv;  \tif (argc &lt;= 2) \t{ \t\tprint_help();  \t\treturn 0; \t}  \tif (!strcmp(argv[1], &quot;upload&quot;)) \t{ \t\tif (argc != 4) \t\t{ \t\t\tprint_help();  \t\t\treturn 0; \t\t}  \t\tint id = barberry_upload_file(argv[2], argv[3]);  \t\tif (id != -1) \t\t{ \t\t\tfprintf(stdout, &quot;File uploaded with id %d\\n&quot;, id); \t\t} \t\telse \t\t{ \t\t\tfprintf(stderr, &quot;%s\\n&quot;, barberry_error()); \t\t} \t} \telse if (!strcmp(argv[1], &quot;download&quot;)) \t{ \t\tif (argc != 5) \t\t{ \t\t\tprint_help();  \t\t\treturn 0; \t\t}  \t\tint result = barberry_download_file(argv[2], atoi(argv[3]), argv[4]);  \t\tif (result != -1) \t\t{ \t\t\tfprintf(stdout, &quot;%s\\n&quot;, &quot;File downloaded&quot;); \t\t} \t\telse \t\t{ \t\t\tfprintf(stderr, &quot;%s\\n&quot;, barberry_error()); \t\t} \t} \telse if (!strcmp(argv[1], &quot;delete&quot;)) \t{ \t\tif (argc != 4) \t\t{ \t\t\tprint_help();  \t\t\treturn 0; \t\t}  \t\tint result = barberry_delete_file(argv[2], atoi(argv[3]));  \t\tif (result != -1) \t\t{ \t\t\tfprintf(stdout, &quot;%s\\n&quot;, &quot;File deleted&quot;); \t\t} \t\telse \t\t{ \t\t\tfprintf(stderr, &quot;%s\\n&quot;, barberry_error()); \t\t} \t} \telse \t{ \t\tprint_help(); \t}  \treturn 0; } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">barberry&#8212;1.0.sql<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">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 <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">barberry.control<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"bash\"># BarBerry image service comment = 'BarBerry image service' default_version = '1.0' module_pathname = '$libdir\/barberry' relocatable = true <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">Makefile<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"bash\">################################# # Makefile for barberry library # #################################  # options  CC=cc CFLAGS=-fpic -c INCLUDEPATH=-I\/usr\/include\/postgresql\/server LIBS=-L\/usr\/lib -lpq -lcurl -ljansson  # targets  all: barberry barberry_test  barberry: barberry.o barberry_impl.o \t$(CC) $(LIBS) -shared -o barberry.so barberry.o barberry_impl.o  barberry_test: barberry_test.o barberry_impl.o \t$(CC) $(LIBS) -o bbtest barberry_test.o barberry_impl.o  barberry.o: \t$(CC) $(INCLUDEPATH) $(CFLAGS) barberry.c  barberry_impl.o: \t$(CC) $(INCLUDEPATH) $(CFLAGS) barberry_impl.c  barberry_test.o: \t$(CC) $(INCLUDEPATH) $(CFLAGS) barberry_test.c  clean: \trm -rf *.o *.so bbtest  rebuild: clean all  install: \tcp *.so \/usr\/lib\/postgresql \tcp *.control \/usr\/share\/postgresql\/extension \tcp *.sql \/usr\/share\/postgresql\/extension <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  <\/p>\n<h4>\u041f\u0440\u0438\u043c\u0435\u0447\u0430\u043d\u0438\u044f<\/h4>\n<p>  <\/p>\n<ul>\n<li>\u0442\u0430\u043a \u043a\u0430\u043a \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u0442\u0441\u044f \u043e\u0442 \u0438\u043c\u0435\u043d\u0438 postgres (\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0434\u043b\u044f \u0421\u0423\u0411\u0414), \u043e\u043d \u0436\u0435 \u0434\u043e\u043b\u0436\u0435\u043d \u0438\u043c\u0435\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u044b\u043c \u0444\u0430\u0439\u043b\u0430\u043c \u0438 \u043f\u0440\u0430\u0432\u043e \u043d\u0430 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u043c\u044b\u0445 \u0444\u0430\u0439\u043b\u043e\u0432<\/li>\n<li>\u043c\u043e\u0436\u043d\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0442\u044c \u0438\u0434\u0435\u044e, \u0441\u0434\u0435\u043b\u0430\u0432 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u0434\u043b\u044f \u0434\u043e\u0441\u0442\u0443\u043f\u0430 \u043a <b>curl<\/b> \u0438\u0437 <b>PostgreSQL<\/b>, \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0432 \u043e\u043f\u0438\u0441\u0430\u043d\u0438\u0435 \u0444\u043e\u0440\u043c\u044b, \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u043e\u0432 \u0438 \u0432\u0441\u0435\u0433\u043e \u043f\u0440\u043e\u0447\u0435\u0433\u043e \u0432 XML-\u0444\u043e\u0440\u043c\u0430\u0442\u0435, \u0440\u0430\u0441\u043f\u0430\u0440\u0441\u0438\u0432\u0430\u044f \u043f\u043e\u0442\u043e\u043c \u0432 C-\u043a\u043e\u0434\u0435 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044f \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0432 <b>curl<\/b><\/li>\n<\/ul>\n<p>  <\/p>\n<h4>\u0421\u043f\u0438\u0441\u043e\u043a \u043b\u0438\u0442\u0435\u0440\u0430\u0442\u0443\u0440\u044b<\/h4>\n<p>  <\/p>\n<ol>\n<li><a href=\"http:\/\/www.postgresql.org\/docs\/9.3\/static\/index.html\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e PostgreSQL<\/a>.<\/li>\n<li><a href=\"http:\/\/curl.haxx.se\/libcurl\/c\/allfuncs.html\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e curl<\/a>.<\/li>\n<li><a href=\"https:\/\/jansson.readthedocs.org\/en\/2.5\/\">\u0414\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e jansson<\/a>.<\/li>\n<li><a href=\"http:\/\/habrahabr.ru\/post\/196544\/\">\u0425\u0440\u0430\u043d\u0438\u043c\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u043d\u0430 C \u0432 PostgreSQL<\/a>.<\/li>\n<li><a href=\"http:\/\/habrahabr.ru\/post\/198332\/\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0432 PostgreSQL<\/a>.<\/li>\n<\/ol>\n<div class=\"clear\"><\/div>\n<\/p><\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"http:\/\/habrahabr.ru\/post\/206576\/\"> http:\/\/habrahabr.ru\/post\/206576\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" align=\"right\" src=\"http:\/\/habr.habrastorage.org\/post_images\/31d\/418\/41f\/31d41841f8783931a3bab223e42d272b.png\"\/><br \/>  \u0414\u043e\u0431\u0440\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0441\u0443\u0442\u043e\u043a. \u041f\u0440\u0438 \u0440\u0430\u0431\u043e\u0442\u0435 \u0441 \u0431\u0430\u0437\u043e\u0439 \u0434\u0430\u043d\u043d\u044b\u0445 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u0430 \u0438\u043d\u043e\u0433\u0434\u0430 \u0432\u043e\u0437\u043d\u0438\u043a\u0430\u0435\u0442 \u0441\u0438\u0442\u0443\u0430\u0446\u0438\u044f, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u0438\u0445\u043e\u0434\u0438\u0442\u0441\u044f \u0432\u044b\u0431\u0438\u0440\u0430\u0442\u044c, \u043a\u0430\u043a \u0438 \u0433\u0434\u0435 \u0445\u0440\u0430\u043d\u0438\u0442\u044c \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f. \u0421\u0440\u0435\u0434\u0438 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0445 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u043e\u0432, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u0438\u043c\u0435\u044e\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435:  <\/p>\n<ul>\n<li>\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0446\u0435\u043b\u0438\u043a\u043e\u043c \u0432 \u0411\u0414<\/li>\n<li>\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u0435, \u0432 \u0411\u0414 \u0445\u0440\u0430\u043d\u0438\u0442\u0441\u044f \u0438\u043c\u044f \u0444\u0430\u0439\u043b\u0430<\/li>\n<li>\u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u043d\u0430\u0445\u043e\u0434\u044f\u0442\u0441\u044f \u0432\u043e \u0432\u043d\u0435\u0448\u043d\u0435\u043c \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u0435<\/li>\n<\/ul>\n<p>  \u0425\u043e\u0442\u044c <b>PostgreSQL<\/b> \u0438 \u043f\u0440\u0435\u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0432 \u0411\u0414 \u0444\u0430\u0439\u043b\u043e\u0432 (\u043d\u0435\u043f\u043e\u0441\u0440\u0435\u0434\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432 <i>bytea<\/i> \u043f\u043e\u043b\u044f\u0445 \u0438\u043b\u0438 \u0447\u0435\u0440\u0435\u0437 <a href=\"http:\/\/www.postgresql.org\/docs\/9.3\/static\/largeobjects.html\">large objects<\/a>), \u044d\u0442\u043e \u043d\u0430\u0438\u043c\u0435\u043d\u0435\u0435 \u043e\u043f\u0442\u0438\u043c\u0430\u043b\u044c\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442, \u043a\u0430\u043a \u0432 \u043f\u043b\u0430\u043d\u0435 \u0441\u043a\u043e\u0440\u043e\u0441\u0442\u0438, \u0442\u0430\u043a \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u044f\u0435\u043c\u043e\u0439 \u043f\u0430\u043c\u044f\u0442\u0438. \u0414\u0440\u0443\u0433\u043e\u0439, \u043e\u0431\u0449\u0435\u043f\u0440\u0438\u043d\u044f\u0442\u043e\u0439 \u043f\u0440\u0430\u043a\u0442\u0438\u043a\u043e\u0439, \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u0435 \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0432 \u0432\u0438\u0434\u0435 \u0444\u0430\u0439\u043b\u043e\u0432 \u043d\u0430 \u0434\u0438\u0441\u043a\u0435, \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u0430 \u0444\u043e\u0440\u043c\u0438\u0440\u0443\u0435\u0442\u0441\u044f \u043f\u0443\u0442\u044c \u043a \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044e. \u0418\u0437 \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432 \u2014 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0439 \u0444\u0430\u0439\u043b\u043e\u0432\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u044b. \u0418 \u0442\u0440\u0435\u0442\u0438\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u2014 \u0434\u043b\u044f \u0438\u0437\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u0439 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u043e\u0442\u0434\u0435\u043b\u044c\u043d\u044b\u0439 \u0441\u0435\u0440\u0432\u0438\u0441, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043c\u043e\u0436\u0435\u0442 \u0431\u044b\u0442\u044c \u043a\u0435\u0448\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043c\u0430\u0448\u0442\u0430\u0431\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043d\u0430 \u043b\u0435\u0442\u0443, \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u0435 \u0444\u043e\u0440\u043c\u0430\u0442\u0430. \u041f\u043e\u043f\u0440\u043e\u0431\u0443\u0435\u043c \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u0437\u0430\u0438\u043c\u043e\u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 <b>PostgreSQL<\/b> \u0441 \u0442\u0430\u043a\u0438\u043c \u0441\u0435\u0440\u0432\u0438\u0441\u043e\u043c.  <\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-206576","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/206576","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=206576"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/206576\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=206576"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=206576"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=206576"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}