{"id":198332,"date":"2013-10-21T00:54:02","date_gmt":"2013-10-20T20:54:02","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=198332"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=198332","title":{"rendered":"<span class=\"post_title\">\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0432 PostgreSQL<\/span>"},"content":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" src=\"http:\/\/habr.habrastorage.org\/post_images\/890\/a02\/abf\/890a02abf9fb65612c78c7803aaa24c5.jpg\"\/><br \/>  \u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439\u0442\u0435, \u0445\u0430\u0431\u0440\u0430\u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0438! \u0422\u0435\u043c\u043e\u0439 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0434\u043b\u044f <b>PostgreSQL<\/b>. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 3D \u0432\u0435\u043a\u0442\u043e\u0440\u0430\u043c\u0438. \u041f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0442\u0438\u043f\u044b, \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0438 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432. \u041d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043b\u0438\u0448\u043d\u0438\u043c \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0441\u044f \u0441 <a href=\"http:\/\/habrahabr.ru\/post\/196544\">\u044d\u0442\u0438\u043c<\/a> \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 C. \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0434\u0440\u0443\u0437\u044c\u044f \u0441\u043b\u043e\u043d\u043e\u0432 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u0441\u043a\u0440\u0430\u0441\u0438\u0442\u044c \u0441\u0435\u0440\u044b\u0439 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0442\u0435\u043a\u0441\u0442 \u0441\u0442\u0430\u0442\u044c\u0438.<br \/>  <a name=\"habracut\"><\/a>  <\/p>\n<h4><b>\u041e\u043f\u0438\u0441\u0430\u043d\u0438\u0435<\/b><\/h4>\n<p>  <img decoding=\"async\" src=\"http:\/\/habr.habrastorage.org\/post_images\/618\/ede\/48b\/618ede48b4e3907b8bd854bf45bc59f8.jpg\"\/><br \/>  <a href=\"http:\/\/www.postgresql.org\/docs\/9.3\/static\/extend-extensions.html\">\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435<\/a> \u0432 <b>PostgreSQL<\/b> \u2014 \u044d\u0442\u043e \u0441\u043e\u0432\u043e\u043a\u0443\u043f\u043d\u043e\u0441\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u0438\u0445 SQL \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 (\u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445, \u0444\u0443\u043d\u043a\u0446\u0438\u0438, \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b), \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0451\u043d\u043d\u044b\u0445 \u0432 \u0432\u0438\u0434\u0435 \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u0430\u044f \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0430 (\u0435\u0441\u043b\u0438 \u043e\u043d\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u0430) \u0438 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0438\u0439 \u0444\u0430\u0439\u043b, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u043c\u044f \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u043f\u0443\u0442\u044c \u043a \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0435, \u0432\u0435\u0440\u0441\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e \u0438 \u043f\u0440\u043e\u0447\u0438\u0435 \u043e\u043f\u0446\u0438\u0438. \u0418\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043b\u0435\u0433\u043a\u043e \u0440\u0430\u0437\u0432\u043e\u0440\u0430\u0447\u0438\u0432\u0430\u0442\u044c \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u0443\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u0432 \u0411\u0414, \u0434\u0435\u043b\u0430\u0442\u044c \u043c\u0438\u0433\u0440\u0430\u0446\u0438\u044e \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0438, \u043f\u0440\u0438 \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u043a\u043e\u0440\u0440\u0435\u043a\u0442\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u044b. <\/p>\n<p>  \u041d\u0430\u043c \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u043d\u043e\u0432\u044b\u0439 \u0442\u0438\u043f \u0434\u0430\u043d\u043d\u044b\u0445 vector3 \u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c \u0442\u0430\u043a\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438:  <\/p>\n<ul>\n<li>\u0441\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u0432<\/li>\n<li>\u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u0435 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u0432<\/li>\n<li>\u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u043d\u0430 \u0441\u043a\u0430\u043b\u044f\u0440<\/li>\n<li>\u0441\u043a\u0430\u043b\u044f\u0440\u043d\u043e\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/li>\n<li>\u0432\u0435\u043a\u0442\u043e\u0440\u043d\u043e\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435<\/li>\n<li>\u043d\u0430\u0445\u043e\u0436\u0434\u0435\u043d\u0438\u0435 \u0434\u043b\u0438\u043d\u044b \u0432\u0435\u043a\u0442\u043e\u0440\u0430<\/li>\n<li>\u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0435\u043a\u0442\u043e\u0440\u0430<\/li>\n<li>\u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0434\u0438\u0441\u0442\u0430\u043d\u0446\u0438\u0438 \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u043a\u0442\u043e\u0440\u0430\u043c\u0438<\/li>\n<\/ul>\n<p>  \u0414\u043b\u044f \u043f\u043e\u0432\u044b\u0448\u0435\u043d\u0438\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u0438, \u043d\u0430\u043f\u0438\u0448\u0435\u043c \u0432\u0441\u044e \u043b\u043e\u0433\u0438\u043a\u0443 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 C \u0438 \u043e\u0444\u043e\u0440\u043c\u0438\u043c \u0432 \u0432\u0438\u0434\u0435 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 math3d. \u0422\u0430\u043a\u0436\u0435, \u0433\u0434\u0435 \u044d\u0442\u043e \u0431\u0443\u0434\u0435\u0442 \u0438\u043d\u0442\u0443\u0438\u0442\u0438\u0432\u043d\u043e, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b. \u041d\u0443 \u0438, \u043d\u0430\u043f\u043e\u0441\u043b\u0435\u0434\u043e\u043a, \u0437\u0430\u0432\u0435\u0440\u043d\u0451\u043c \u0432\u0441\u0451 \u044d\u0442\u043e \u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435.<\/p>\n<h4><b>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0442\u0438\u043f\u0430<\/b><\/h4>\n<p>  <img decoding=\"async\" src=\"http:\/\/habr.habrastorage.org\/post_images\/585\/b82\/5fd\/585b825fd2c454f3a8cbe0c5ca284440.jpg\"\/><br \/>  \u0421\u0423\u0411\u0414 <b>PostgreSQL<\/b> \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c, \u043f\u043e\u043c\u0438\u043c\u043e \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u043d\u044b\u0445 \u0442\u0438\u043f\u043e\u0432, \u0442\u0438\u043f\u043e\u0432-\u043f\u0435\u0440\u0435\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u0438 \u0442\u0438\u043f\u043e\u0432-\u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u043e\u0432, <a href=\"http:\/\/www.postgresql.org\/docs\/9.3\/static\/sql-createtype.html\">\u043d\u043e\u0432\u044b\u0435 \u0442\u0438\u043f\u044b \u0434\u0430\u043d\u043d\u044b\u0445<\/a>. \u041f\u043e\u0441\u043b\u0435\u0434\u043d\u0438\u0435 \u0442\u0440\u0435\u0431\u0443\u044e\u0442 \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0439, \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0449\u0438\u0445 \u0441 \u0442\u0438\u043f\u043e\u043c, \u043d\u0430 \u0431\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u043e\u0443\u0440\u043e\u0432\u043d\u0435\u0432\u043e\u043c \u044f\u0437\u044b\u043a\u0435, \u0447\u0435\u043c SQL, \u043a\u0430\u043a \u043f\u0440\u0430\u0432\u0438\u043b\u043e, \u043d\u0430 C. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u0442\u0438\u043f\u0430 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043a\u0430\u043a \u043c\u0438\u043d\u0438\u043c\u0443\u043c \u0434\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438: \u0432\u0432\u043e\u0434\u0430 \u0438 \u0432\u044b\u0432\u043e\u0434\u0430. \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u0432\u043e\u0434\u0430 \u0438\u043c\u0435\u0435\u0442 \u043e\u0434\u0438\u043d \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0441 \u0442\u0438\u043f\u043e\u043c C-\u0441\u0442\u0440\u043e\u043a\u0430 (\u043c\u0430\u0441\u0441\u0438\u0432 \u0431\u0430\u0439\u0442\u043e\u0432, \u0437\u0430\u043a\u0430\u043d\u0447\u0438\u0432\u0430\u044e\u0449\u0438\u0439\u0441\u044f \u043d\u0443\u043b\u0435\u043c) \u0438 \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u0442 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0442\u0438\u043f. \u0424\u0443\u043d\u043a\u0446\u0438\u044f \u0432\u044b\u0432\u043e\u0434\u0430 \u0438\u043c\u0435\u0435\u0442 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0441 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0439 \u0442\u0438\u043f\u043e\u043c \u0438 \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u0442 C-\u0441\u0442\u0440\u043e\u043a\u0443. \u042d\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0442\u0440\u0435\u0431\u0443\u044e\u0442\u0441\u044f \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0438\u0437 \u0432\u043d\u0435\u0448\u043d\u0435\u0433\u043e (\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0433\u043e) \u043e\u0442\u043e\u0431\u0440\u0430\u0436\u0435\u043d\u0438\u044f \u0432\u043e \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442.<\/p>\n<p>  \u041d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u0442\u0438\u043f\u0430 \u0441\u043e \u0441\u0442\u043e\u0440\u043e\u043d\u044b \u0421\u0423\u0411\u0414:  <\/p>\n<ul>\n<li><i>internallength<\/i> \u2014 \u0440\u0430\u0437\u043c\u0435\u0440 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f<\/li>\n<li><i>alignment<\/i> \u2014 \u0432\u044b\u0440\u0430\u0432\u043d\u0438\u0432\u0430\u043d\u0438\u0435, \u0434\u043e\u043f\u0443\u0441\u0442\u0438\u043c\u044b\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f 1, 2, 4, 8 \u0431\u0430\u0439\u0442\u0430<\/li>\n<li><i>storage<\/i> \u2014 \u0432\u044b\u0431\u043e\u0440 \u0445\u0440\u0430\u043d\u0438\u043b\u0438\u0449\u0430, plain (\u0435\u0434\u0438\u043d\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u044b\u0439 \u0432\u0430\u0440\u0438\u0430\u043d\u0442 \u0434\u043b\u044f \u0442\u0438\u043f\u043e\u0432 \u0441 \u0444\u0438\u043a\u0441\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c \u0440\u0430\u0437\u043c\u0435\u0440\u043e\u043c) \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0431\u0435\u0437 \u0441\u0436\u0430\u0442\u0438\u044f, extended \u0434\u043e\u043f\u0443\u0441\u043a\u0430\u0435\u0442 \u0441\u0436\u0430\u0442\u0438\u0435 \u0438 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0432\u043d\u0435 \u043f\u0440\u0435\u0434\u0435\u043b\u043e\u0432 \u0441\u0442\u0440\u043e\u043a\u0438 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0433\u0434\u0435 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d \u0442\u0438\u043f, main \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0441\u0436\u0430\u0442\u0438\u0435, \u043d\u043e \u0437\u0430\u043f\u0440\u0435\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435<\/li>\n<li><i>receive<\/i> \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043f\u043e\u043b\u0443\u0447\u0435\u043d\u0438\u044f \u0434\u043b\u044f \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0433\u043e \u0432\u0432\u043e\u0434\u0430\/\u0432\u044b\u0432\u043e\u0434\u0430<\/li>\n<li><i>send<\/i> \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u044f \u043e\u0442\u043f\u0440\u0430\u0432\u043a\u0438 \u0434\u043b\u044f \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0433\u043e \u0432\u0432\u043e\u0434\u0430\/\u0432\u044b\u0432\u043e\u0434\u0430<\/li>\n<\/ul>\n<p>  \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u0432 \u0438\u0441\u0445\u043e\u0434\u043d\u043e\u043c \u0444\u0430\u0439\u043b\u0435 <i>math3d.c<\/i> \u0442\u0438\u043f vector3, \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0433\u043e \u0432\u0432\u043e\u0434\u0430\/\u0432\u044b\u0432\u043e\u0434\u0430 \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0433\u043e \u0432\u0432\u043e\u0434\u0430\/\u0432\u044b\u0432\u043e\u0434\u0430 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0442\u0438\u043f\u0430:  <\/p>\n<pre><code class=\"cpp\">#include &lt;postgres.h&gt; #include &lt;fmgr.h&gt; #include &lt;libpq\/pqformat.h&gt; #include &lt;math.h&gt;  #ifdef PG_MODULE_MAGIC \tPG_MODULE_MAGIC; #endif  typedef struct { \tdouble x, y, z; } vector3;  PG_FUNCTION_INFO_V1(vector3_in); PG_FUNCTION_INFO_V1(vector3_out);  PG_FUNCTION_INFO_V1(vector3_recv); PG_FUNCTION_INFO_V1(vector3_send);  Datum vector3_in(PG_FUNCTION_ARGS) { \tchar *s = PG_GETARG_CSTRING(0);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tif (sscanf(s, &quot;(%lf,%lf,%lf)&quot;, &(v-&gt;x), &(v-&gt;y), &(v-&gt;z)) != 3) \t{ \t\tereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg(&quot;Invalid input syntax for vector3: \\&quot;%s\\&quot;&quot;, s))); \t}  \tPG_RETURN_POINTER(v); }  Datum vector3_out(PG_FUNCTION_ARGS) { \tvector3 *v = (vector3*)PG_GETARG_POINTER(0);  \tchar *s = (char*)palloc(100);  \tsnprintf(s, 100, &quot;(%lf,%lf,%lf)&quot;, v-&gt;x, v-&gt;y, v-&gt;z);  \tPG_RETURN_CSTRING(s); }  Datum vector3_recv(PG_FUNCTION_ARGS) { \tStringInfo buffer = (StringInfo)PG_GETARG_POINTER(0);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = pq_getmsgfloat8(buffer); \tv-&gt;y = pq_getmsgfloat8(buffer); \tv-&gt;z = pq_getmsgfloat8(buffer);  \tPG_RETURN_POINTER(v); }  Datum vector3_send(PG_FUNCTION_ARGS) { \tvector3 *v = (vector3*)PG_GETARG_POINTER(0);  \tStringInfoData buffer;  \tpq_begintypsend(&buffer);  \tpq_sendfloat8(&buffer, v-&gt;x); \tpq_sendfloat8(&buffer, v-&gt;y); \tpq_sendfloat8(&buffer, v-&gt;z);  \tPG_RETURN_BYTEA_P(pq_endtypsend(&buffer)); } <\/code><\/pre>\n<p>  \u0423\u0441\u043b\u043e\u0432\u0438\u043c\u0441\u044f, \u0447\u0442\u043e \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u0430 vector3 \u0431\u0443\u0434\u0435\u0442 \u0432 \u0432\u0438\u0434\u0435 &quot;(x,y,z)&quot;, \u0433\u0434\u0435 x, y, z, \u0441\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0432\u0435\u043a\u0442\u043e\u0440\u0430. \u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <i>vector3_in<\/i> \u0438\u0437 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430, \u0442\u0438\u043f\u0430 C-\u0441\u0442\u0440\u043e\u043a\u0430, \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e sscanf \u0438\u0437\u0432\u043b\u0435\u043a\u0430\u044e\u0442\u0441\u044f \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u0438 \u0441\u043e\u0437\u0434\u0430\u043d\u043d\u044b\u0439 \u0432\u0435\u043a\u0442\u043e\u0440 (\u0442\u043e\u0447\u043d\u0435\u0435 \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u044c \u043d\u0430 \u043d\u0435\u0433\u043e) \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u0430 \u0444\u0443\u043d\u043a\u0446\u0438\u0438. \u0412 <i>vector3_out<\/i> \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u0434\u0435\u0439\u0441\u0442\u0432\u0438\u0435 \u2014 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435 \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u0432 \u0441\u0442\u0440\u043e\u043a\u0443 \u0438 \u0435\u0435 \u0432\u043e\u0437\u0440\u0430\u0442.<\/p>\n<p>  \u041f\u0435\u0440\u0435\u0439\u0434\u0435\u043c \u0442\u0435\u043f\u0435\u0440\u044c \u0432 \u043a\u043e\u043d\u0441\u043e\u043b\u044c, \u0441\u043e\u0431\u0435\u0440\u0451\u043c \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 math3d \u0438 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0435\u0435 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 $libdir (\u0443\u0437\u043d\u0430\u0442\u044c \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043c\u043e\u0436\u043d\u043e, \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0432 \u043a\u043e\u043c\u0430\u043d\u0434\u0443 <i>pg_config &#8212;pkglibdir<\/i>):  <\/p>\n<pre><code class=\"bash\">cc -I\/usr\/local\/pgsql\/include\/server -fpic -c math3d.c cc -shared -L\/usr\/local\/pgsql\/lib -lpq -o math3d.so math3d.o cp math3d.so \/usr\/local\/pgsql\/lib\/ <\/code><\/pre>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0442\u0438\u043f vector3 \u0432 \u0411\u0414:  <\/p>\n<pre><code class=\"sql\">CREATE TYPE vector3;  CREATE OR REPLACE FUNCTION vector3_in ( s cstring ) RETURNS vector3 AS 'math3d', 'vector3_in' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_out ( v vector3 ) RETURNS cstring AS 'math3d', 'vector3_out' LANGUAGE C IMMUTABLE STRICT;  CREATE FUNCTION vector3_recv ( p internal ) RETURNS vector3 AS 'math3d', 'vector3_recv' LANGUAGE C IMMUTABLE STRICT;  CREATE FUNCTION vector3_send ( v vector3 ) RETURNS bytea AS 'math3d', 'vector3_send' LANGUAGE C IMMUTABLE STRICT;  CREATE TYPE vector3 ( \tinternallength = 24, \tinput = vector3_in, \toutput = vector3_out, \treceive = vector3_recv, \tsend = vector3_send ); <\/code><\/pre>\n<p>  \u041e\u0431\u0440\u0430\u0442\u0438\u0442\u0435 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435, \u0447\u0442\u043e \u0441\u043f\u0435\u0440\u0432\u0430 \u043d\u0443\u0436\u043d\u043e \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0442\u0438\u043f, \u0434\u043b\u044f \u0442\u043e\u0433\u043e, \u0447\u0442\u043e\u0431\u044b \u0431\u044b\u043b\u0430 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u0432\u043e\u0434\u0430 \u0438 \u0432\u044b\u0432\u043e\u0434\u0430. \u041f\u0440\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0438 \u0442\u0438\u043f\u0430, \u0438\u0437 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u043c\u044b \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u043c \u0440\u0430\u0437\u043c\u0435\u0440 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0433\u043e \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u0432\u0432\u043e\u0434\u0430\/\u0432\u044b\u0432\u043e\u0434\u0430.<\/p>\n<p>  \u0412\u044b\u043f\u043e\u043b\u043d\u0438\u043c \u0442\u0435\u0441\u0442\u043e\u0432\u044b\u0439 \u0437\u0430\u043f\u0440\u043e\u0441:  <\/p>\n<pre><code class=\"sql\">SELECT '(0.0,1.0,0.0)'::vector3; -- (0.000000,1.000000,0.000000) \u0441 \u0442\u0438\u043f\u043e\u043c vector3 <\/code><\/pre>\n<p>  <\/p>\n<h4><b>\u041e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u0441 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u043c<\/b><\/h4>\n<p>  <img decoding=\"async\" src=\"http:\/\/habr.habrastorage.org\/post_images\/f47\/258\/47f\/f4725847fa6e1407b0cf23be92090288.jpg\"\/><br \/>  \u0422\u0438\u043f \u0441\u043e\u0437\u0434\u0430\u043d, \u043d\u043e \u043d\u0430 \u0431\u043e\u043b\u044c\u0448\u0435, \u0447\u0435\u043c \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043a \u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u043c\u0443 \u0432\u0438\u0434\u0443 \u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442, \u043e\u043d \u043f\u043e\u043a\u0430 \u0447\u0442\u043e \u043d\u0435 \u0441\u043f\u043e\u0441\u043e\u0431\u0435\u043d. \u0421\u0434\u0435\u043b\u0430\u0435\u043c \u0435\u0433\u043e \u0431\u043e\u043b\u0435\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b\u044c\u043d\u044b\u043c, \u0440\u0430\u0441\u0448\u0438\u0440\u0438\u0432 \u0435\u0433\u043e \u0442\u0440\u0435\u0431\u0443\u0435\u043c\u044b\u043c\u0438 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u044f\u043c\u0438:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439 \u0432 math3d.c<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">PG_FUNCTION_INFO_V1(vector3_minus); \/\/ \u0443\u043d\u0430\u0440\u043d\u044b\u0439 \u043c\u0438\u043d\u0443\u0441 PG_FUNCTION_INFO_V1(vector3_add); \/\/ \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u0432 PG_FUNCTION_INFO_V1(vector3_sub); \/\/ \u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u0435 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u0432 PG_FUNCTION_INFO_V1(vector3_mul_left); \/\/ \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u043d\u0430 \u0441\u043a\u0430\u043b\u044f\u0440 PG_FUNCTION_INFO_V1(vector3_mul_right); \/\/ \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043a\u0430\u043b\u044f\u0440\u0430 \u043d\u0430 \u0432\u0435\u043a\u0442\u043e\u0440 PG_FUNCTION_INFO_V1(vector3_div_left); \/\/ \u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u043d\u0430 \u0441\u043a\u0430\u043b\u044f\u0440 PG_FUNCTION_INFO_V1(vector3_div_right); \/\/ \u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u043a\u0430\u043b\u044f\u0440\u0430 \u043d\u0430 \u0432\u0435\u043a\u0442\u043e\u0440  PG_FUNCTION_INFO_V1(vector3_equal); \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u0432 \u043d\u0430 \u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u043e PG_FUNCTION_INFO_V1(vector3_not_equal); \/\/ \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u0432 \u043d\u0430 \u043d\u0435\u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u043e  PG_FUNCTION_INFO_V1(vector3_dot); \/\/ \u0441\u043a\u0430\u043b\u044f\u0440\u043d\u043e\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 PG_FUNCTION_INFO_V1(vector3_cross); \/\/ \u0432\u0435\u043a\u0442\u043e\u0440\u043d\u043e\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435  PG_FUNCTION_INFO_V1(vector3_length); \/\/ \u0434\u043b\u0438\u043d\u0430 \u0432\u0435\u043a\u0442\u043e\u0440\u0430 PG_FUNCTION_INFO_V1(vector3_normalize); \/\/ \u043d\u043e\u0440\u043c\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0432\u0435\u043a\u0442\u043e\u0440\u0430 PG_FUNCTION_INFO_V1(vector3_distance); \/\/ \u0440\u0430\u0441\u0441\u0442\u043e\u044f\u043d\u0438\u0435 \u043c\u0435\u0436\u0434\u0443 \u0432\u0435\u043a\u0442\u043e\u0440\u0430\u043c\u0438  Datum vector3_minus(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = -v0-&gt;x; \tv-&gt;y = -v0-&gt;y; \tv-&gt;z = -v0-&gt;z;  \tPG_RETURN_POINTER(v); }  Datum vector3_add(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = v0-&gt;x + v1-&gt;x; \tv-&gt;y = v0-&gt;y + v1-&gt;y; \tv-&gt;z = v0-&gt;z + v1-&gt;z;  \tPG_RETURN_POINTER(v); }  Datum vector3_sub(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = v0-&gt;x - v1-&gt;x; \tv-&gt;y = v0-&gt;y - v1-&gt;y; \tv-&gt;z = v0-&gt;z - v1-&gt;z;  \tPG_RETURN_POINTER(v); }  Datum vector3_mul_left(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tdouble k = PG_GETARG_FLOAT8(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = v0-&gt;x * k; \tv-&gt;y = v0-&gt;y * k; \tv-&gt;z = v0-&gt;z * k;  \tPG_RETURN_POINTER(v); }  Datum vector3_mul_right(PG_FUNCTION_ARGS) { \tdouble k = PG_GETARG_FLOAT8(0); \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = k * v0-&gt;x; \tv-&gt;y = k * v0-&gt;y; \tv-&gt;z = k * v0-&gt;z;  \tPG_RETURN_POINTER(v); }  Datum vector3_div_left(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tdouble k = PG_GETARG_FLOAT8(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = v0-&gt;x \/ k; \tv-&gt;y = v0-&gt;y \/ k; \tv-&gt;z = v0-&gt;z \/ k;  \tPG_RETURN_POINTER(v); }  Datum vector3_div_right(PG_FUNCTION_ARGS) { \tdouble k = PG_GETARG_FLOAT8(0); \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = k \/ v0-&gt;x; \tv-&gt;y = k \/ v0-&gt;y; \tv-&gt;z = k \/ v0-&gt;z;  \tPG_RETURN_POINTER(v); }  Datum vector3_equal(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tbool equal = true;  \tequal &= v0-&gt;x == v1-&gt;x; \tequal &= v0-&gt;y == v1-&gt;y; \tequal &= v0-&gt;z == v1-&gt;z;  \tPG_RETURN_BOOL(equal); }  Datum vector3_not_equal(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tbool not_equal = false;  \tnot_equal |= v0-&gt;x != v1-&gt;x; \tnot_equal |= v0-&gt;y != v1-&gt;y; \tnot_equal |= v0-&gt;z != v1-&gt;z;  \tPG_RETURN_BOOL(not_equal); }  Datum vector3_dot(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tdouble r = v0-&gt;x * v1-&gt;x + v0-&gt;y * v1-&gt;y + v0-&gt;z * v1-&gt;z;  \tPG_RETURN_FLOAT8(r); }  Datum vector3_cross(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = v0-&gt;y * v1-&gt;z - v0-&gt;z * v1-&gt;y; \tv-&gt;y = v0-&gt;z * v1-&gt;x - v0-&gt;x * v1-&gt;z; \tv-&gt;z = v0-&gt;x * v1-&gt;y - v0-&gt;y * v1-&gt;x;  \tPG_RETURN_POINTER(v); }  Datum vector3_length(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0);  \tdouble len = sqrt(v0-&gt;x * v0-&gt;x + v0-&gt;y * v0-&gt;y + v0-&gt;z * v0-&gt;z);  \tPG_RETURN_FLOAT8(len); }  Datum vector3_normalize(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tdouble len = sqrt(v0-&gt;x * v0-&gt;x + v0-&gt;y * v0-&gt;y + v0-&gt;z * v0-&gt;z);  \tif (len &gt; 0.000001) \t{ \t\tv-&gt;x = v0-&gt;y \/ len; \t\tv-&gt;y = v0-&gt;z \/ len; \t\tv-&gt;z = v0-&gt;x \/ len; \t} \telse \t{ \t\tv-&gt;x = 0.0; \t\tv-&gt;y = 0.0; \t\tv-&gt;z = 0.0; \t}  \tPG_RETURN_POINTER(v); }  Datum vector3_distance(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = v0-&gt;x - v1-&gt;x; \tv-&gt;y = v0-&gt;y - v1-&gt;y; \tv-&gt;z = v0-&gt;z - v1-&gt;z;  \tdouble len = sqrt(v-&gt;x * v-&gt;x + v-&gt;y * v-&gt;y + v-&gt;z * v-&gt;z);  \tpfree(v);  \tPG_RETURN_FLOAT8(len); } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u041d\u0430\u043f\u043e\u043c\u043d\u044e, \u0447\u0442\u043e \u0434\u043b\u044f \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438 \u0441\u043b\u0435\u0434\u0443\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c <i>palloc<\/i>, \u0434\u043b\u044f \u043e\u0441\u0432\u043e\u0431\u043e\u0436\u0434\u0435\u043d\u0438\u044f, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0435\u043d\u043d\u043e <i>pfree<\/i>. \u041f\u043e\u0447\u0435\u043c\u0443 \u043d\u0443\u0436\u043d\u044b \u043f\u0430\u0440\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439 vector3_mul_left\/vector3_mul_right \u0438 vector3_div_left\/vector3_div_right \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u044a\u044f\u0441\u043d\u0435\u043d\u043e \u0434\u0430\u043b\u0435\u0435.<\/p>\n<p>  \u041f\u0435\u0440\u0435\u0441\u043e\u0431\u0435\u0440\u0451\u043c \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 math3d.so \u0438 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u044d\u0442\u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432 \u0411\u0414, \u0432 \u043d\u043e\u0432\u043e\u0439 \u0441\u0435\u0441\u0441\u0438\u044e, \u0447\u0442\u043e\u0431\u044b \u0441\u0435\u0440\u0432\u0435\u0440 <b>PostgreSQL<\/b> \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043b \u043d\u043e\u0432\u0443\u044e \u0432\u0435\u0440\u0441\u0438\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438:<\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">SQL \u043a\u043e\u0434 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0439<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"sql\">CREATE OR REPLACE FUNCTION vector3_minus ( v0 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_minus' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_add ( v0 vector3, v1 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_add' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_sub ( v0 vector3, v1 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_sub' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_mul_left ( v0 vector3, k double precision ) RETURNS vector3 AS 'math3d', 'vector3_mul_left' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_mul_right ( k double precision, v0 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_mul_right' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_div_left ( v0 vector3, k double precision ) RETURNS vector3 AS 'math3d', 'vector3_div_left' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_div_right ( k double precision, v0 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_div_right' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_equal ( v0 vector3, v1 vector3 ) RETURNS boolean AS 'math3d', 'vector3_equal' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_not_equal ( v0 vector3, v1 vector3 ) RETURNS boolean AS 'math3d', 'vector3_not_equal' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_dot ( v0 vector3, v1 vector3 ) RETURNS double precision AS 'math3d', 'vector3_dot' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_cross ( v0 vector3, v1 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_cross' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION length ( v0 vector3 ) RETURNS double precision AS 'math3d', 'vector3_length' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION normalize ( v0 vector3 ) RETURNS vector3 AS 'math3d', 'vector3_normalize' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION distance ( v0 vector3, v1 vector3 ) RETURNS double precision AS 'math3d', 'vector3_distance' LANGUAGE C IMMUTABLE STRICT; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0422\u0435\u043f\u0435\u0440\u044c \u043c\u043e\u0436\u043d\u043e \u0434\u0435\u043b\u0430\u0442\u044c \u0440\u0430\u0437\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0446\u0438\u0438 \u043d\u0430\u0434 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u043c:  <\/p>\n<pre><code class=\"sql\">SELECT vector3_add ( '(0.0,1.0,0.0)'::vector3, '(0.5,0.5,0.0)'::vector3 ); -- (0.500000,1.500000,0.000000) SELECT vector3_mul_right ( 5.0, '(0.2,0.2,1.33)'::vector3 ); -- (1.000000,1.000000,6.650000) SELECT vector3_cross ( '(1.0,0.0,0.0)'::vector3, '(0.0,1.0,0.0)'::vector3 ); -- (0.000000,0.000000,1.000000) SELECT length ( '(0.705,0.705,0.0)'::vector3 ); -- 0.9970206 <\/code><\/pre>\n<p>  \u0424\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b \u0438\u043c\u0435\u0435\u0442\u0441\u044f, \u043d\u043e \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u043e\u043d \u043d\u0435 \u043e\u0447\u0435\u043d\u044c \u0445\u043e\u0440\u043e\u0448\u043e, \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, \u0434\u043b\u044f \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f \u0441\u043a\u0430\u043b\u044f\u0440\u0430 \u043d\u0430 \u0432\u0435\u043a\u0442\u043e\u0440 \u0438\u043d\u0442\u0443\u0442\u0438\u0432\u043d\u0435\u0439 \u0431\u044b\u043b\u0430 \u0431\u044b \u0437\u0430\u043f\u0438\u0441\u044c 5.0 * &#8216;(0.2,0.2,1.33)&#8217;::vector3. \u0414\u0430\u0432\u0430\u0439\u0442\u0435 \u0434\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b.<\/p>\n<h4><b>\u041f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b<\/b><\/h4>\n<p>  <img decoding=\"async\" src=\"http:\/\/habr.habrastorage.org\/post_images\/f4e\/a07\/4c8\/f4ea074c8384374f468328696935753b.jpg\"\/><br \/>  \u0412 <b>PostgreSQL<\/b> \u0435\u0441\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0442\u044c \u0441\u0432\u043e\u0438 <a href=\"http:\/\/www.postgresql.org\/docs\/9.3\/static\/sql-createoperator.html\">\u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b<\/a>, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0438\u0437 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u0432 + \u2014 * \/ &lt; &gt; = ~! @ # % ^ &#038; | `? \u0441 \u043c\u0430\u043a\u0441\u0438\u043c\u0430\u043b\u044c\u043d\u043e\u0439 \u0434\u043b\u0438\u043d\u043e\u0439 63. \u041e\u043d\u0438 \u0431\u044b\u0432\u0430\u044e\u0442 \u0443\u043d\u0430\u0440\u043d\u044b\u043c\u0438 \u0438\u043b\u0438 \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u043c\u0438. \u041c\u043e\u0436\u043d\u043e \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0442\u044c \u043f\u0435\u0440\u0435\u0433\u0440\u0443\u0436\u0435\u043d\u043d\u044b\u0435 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b, \u0438\u043c\u0435\u044e\u0449\u0438\u0435 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0435 \u0438\u043c\u044f, \u043d\u043e \u0440\u0430\u0437\u043d\u044b\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b. \u0412\u043e\u0442 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0432\u0430\u0436\u043d\u044b\u0435 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u044b \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 (\u0434\u043b\u044f \u0443\u043d\u0430\u0440\u043d\u044b\u0445 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e <i>leftarg<\/i> \u0438\u043b\u0438 <i>rightarg<\/i>):  <\/p>\n<ul>\n<li><i>leftarg<\/i> \u2014 \u0442\u0438\u043f \u043b\u0435\u0432\u043e\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430<\/li>\n<li><i>rightarg<\/i> \u2014 \u0442\u0438\u043f \u043f\u0440\u0430\u0432\u043e\u0433\u043e \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430<\/li>\n<li><i>procedure<\/i> \u2014 \u0444\u0443\u043d\u043a\u0446\u0438\u044f, \u0438\u043c\u0435\u044e\u0449\u0430\u044f \u043e\u0434\u0438\u043d (\u0443\u043d\u0430\u0440\u043d\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440) \u0438\u043b\u0438 \u0434\u0432\u0430 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430 (\u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440) \u0441 \u0442\u0438\u043f\u0430\u043c\u0438, \u0441\u043e\u043e\u0442\u0432\u0435\u0442\u0441\u0432\u0443\u044e\u0449\u0438\u043c\u0438 <i>leftarg<\/i> \u0438 <i>rightarg<\/i> \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430<\/li>\n<li><i>commutator<\/i> \u2014 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0443, \u0447\u0442\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 <i>x A y<\/i> \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u043d\u043e <i>y B x<\/i>, \u0433\u0434\u0435 A \u2014 \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440, B \u2014 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u043b\u044f <i>commutator<\/i><\/li>\n<li><i>negator<\/i> \u2014 \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u043a\u0430 \u043e\u043f\u0442\u0438\u043c\u0438\u0437\u0430\u0442\u043e\u0440\u0443, \u0447\u0442\u043e \u0432\u044b\u0440\u0430\u0436\u0435\u043d\u0438\u0435 <i>x A y<\/i> \u044d\u043a\u0432\u0438\u0432\u0430\u043b\u0435\u043d\u0442\u043d\u043e <i>!(x B y)<\/i>, \u0433\u0434\u0435 A \u2014 \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0435\u043c\u044b\u0439 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440, B \u2014 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440 \u0434\u043b\u044f <i>negator<\/i> \u0438 \u043e\u0431\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0434\u043e\u043b\u0436\u043d\u044b \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0442\u044c boolean<\/li>\n<\/ul>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">SQL \u043a\u043e\u0434 \u0434\u043b\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u043e\u0432<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"sql\">-- \u0443\u043d\u0430\u0440\u043d\u044b\u0439 \u043c\u0438\u043d\u0443\u0441 CREATE OPERATOR - (     rightarg = vector3,     procedure = vector3_minus );  -- \u0441\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u0432 CREATE OPERATOR + (     leftarg = vector3,     rightarg = vector3,     procedure = vector3_add,     commutator = + );  -- \u0432\u044b\u0447\u0438\u0442\u0430\u043d\u0438\u0435 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u0432 CREATE OPERATOR - (     leftarg = vector3,     rightarg = vector3,     procedure = vector3_sub );  -- \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435 \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u043d\u0430 \u0441\u043a\u0430\u043b\u044f\u0440 CREATE OPERATOR * (     leftarg = vector3,     rightarg = double precision,     procedure = vector3_mul_left );  -- \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0435 \u0441\u043a\u0430\u043b\u044f\u0440\u0430 \u043d\u0430 \u0432\u0435\u043a\u0442\u043e\u0440 CREATE OPERATOR * (     leftarg = double precision,     rightarg = vector3,     procedure = vector3_mul_right );  -- \u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0432\u0435\u043a\u0442\u043e\u0440\u0430 \u043d\u0430 \u0441\u043a\u0430\u043b\u044f\u0440 CREATE OPERATOR \/ (     leftarg = vector3,     rightarg = double precision,     procedure = vector3_div_left );  -- \u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u0441\u043a\u0430\u043b\u044f\u0440\u0430 \u043d\u0430 \u0432\u0435\u043a\u0442\u043e\u0440 CREATE OPERATOR \/ (     leftarg = double precision,     rightarg = vector3,     procedure = vector3_div_right );  -- \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u0432 \u043d\u0430 \u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u043e CREATE OPERATOR = (     leftarg = vector3,     rightarg = vector3,     procedure = vector3_equal );  -- \u043f\u0440\u043e\u0432\u0435\u0440\u043a\u0430 \u0432\u0435\u043a\u0442\u043e\u0440\u043e\u0432 \u043d\u0430 \u043d\u0435\u0440\u0430\u0432\u0435\u043d\u0441\u0442\u0432\u043e CREATE OPERATOR != (     leftarg = vector3,     rightarg = vector3,     procedure = vector3_not_equal );  -- \u0441\u043a\u0430\u043b\u044f\u0440\u043d\u043e\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 CREATE OPERATOR * (     leftarg = vector3,     rightarg = vector3,     procedure = vector3_dot     commutator =  );  -- \u0432\u0435\u043a\u0442\u043e\u0440\u043d\u043e\u0435 \u043f\u0440\u043e\u0438\u0437\u0432\u0435\u0434\u0435\u043d\u0438\u0435 CREATE OPERATOR ** (     leftarg = vector3,     rightarg = vector3,     procedure = vector3_cross ); <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0418 \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u0438\u0445 \u0440\u0430\u0431\u043e\u0442\u043e\u0441\u043f\u043e\u0441\u043e\u0431\u043d\u043e\u0441\u0442\u044c:  <\/p>\n<pre><code class=\"sql\">SELECT '(0.0,1.0,0.0)'::vector3 + '(0.5,0.5,0.0)'::vector3; -- (0.500000,1.500000,0.000000) SELECT 5.0 * '(0.2,0.2,1.33)'::vector3; -- (1.000000,1.000000,6.650000) SELECT '(1.0,0.5,0.1)'::vector3 * '(0.707,0.707,0.707)'::vector3; -- 1.1312 SELECT '(1.0,0.0,0.0)'::vector3 ** '(0.0,1.0,0.0)'::vector3; -- (0.000000,0.000000,1.000000) <\/code><\/pre>\n<p>  \u0423\u0436\u0435 \u043b\u0443\u0447\u0448\u0435. \u041a\u0441\u0442\u0430\u0442\u0438, \u043c\u044b \u043e\u0431\u044c\u044f\u0432\u0438\u043b\u0438 \u0434\u0432\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0434\u043b\u044f \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u044f \u0441 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c \u0442\u0438\u043f\u0430 \u0441\u043a\u0430\u043b\u044f\u0440, \u0434\u043b\u044f \u0441\u043b\u0443\u0447\u0430\u044f, \u043a\u043e\u0433\u0434\u0430 \u0441\u043a\u0430\u043b\u044f\u0440 \u0441\u043b\u0435\u0432\u0430 \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u0430 \u0438 \u043a\u043e\u0433\u0434\u0430 \u043e\u043d \u0441\u043f\u0440\u0430\u0432\u0430. \u0418 \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0434\u043b\u044f \u0434\u0435\u043b\u0435\u043d\u0438\u044f. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0430\u043c \u0438 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u043b\u0438\u0441\u044c \u043f\u0430\u0440\u044b \u0444\u0443\u043d\u043a\u0446\u0438\u0439 vector3_mul_left\/vector3_mul_right \u0438 vector3_div_left\/vector3_div_right.<\/p>\n<p>  \u041c\u043e\u0436\u0435\u0442 \u0432\u043e\u0437\u043d\u0438\u043a\u043d\u0443\u0442\u044c \u0432\u043e\u043f\u0440\u043e\u0441: \u0430 \u043a\u0430\u043a \u043f\u043e\u043b\u0443\u0447\u0438\u0442\u044c \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0430\u043c \u0432\u0435\u043a\u0442\u043e\u0440\u0430? \u041c\u043e\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u043e\u0431\u044a\u044f\u0432\u0438\u0442\u044c \u0442\u0440\u0438 C-\u0444\u0443\u043d\u043a\u0446\u0438\u0438 vector3_x, vector3_y \u0438 vector3_z, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u0431\u044b \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u043b\u0438 \u043a\u0430\u0436\u0434\u0443\u044e \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u0443, \u043d\u043e \u0435\u0441\u0442\u044c \u0441\u043f\u043e\u0441\u043e\u0431 \u043b\u0443\u0447\u0448\u0435.<\/p>\n<h4><b>\u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432<\/b><\/h4>\n<p>  <img decoding=\"async\" src=\"http:\/\/habr.habrastorage.org\/post_images\/e1b\/751\/a03\/e1b751a0327a55748ab568a7adf88a16.jpg\"\/><br \/>  \u0415\u0449\u0435 \u043e\u0434\u043d\u043e\u0439 \u043f\u0440\u0438\u043c\u0435\u0447\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u044c\u044e \u0432 <b>PostgreSQL<\/b> \u044f\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 <a href=\"http:\/\/www.postgresql.org\/docs\/9.3\/static\/sql-createcast.html\">\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u043e\u0433\u043e \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u044f<\/a> \u0442\u0438\u043f\u043e\u0432. \u0415\u0441\u043b\u0438 \u043e\u0431\u0430 \u0442\u0438\u043f\u0430 \u0438\u043c\u0435\u044e\u0442 \u043e\u0434\u0438\u043d\u0430\u043a\u043e\u0432\u043e\u0435 \u0432\u043d\u0443\u0442\u0440\u0435\u043d\u043d\u0435\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 (\u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, varchar \u0438 text), \u0442\u043e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0434\u043b\u044f \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432 \u043d\u0435\u0442. \u0412 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u044d\u0442\u0443 \u0444\u0443\u043d\u043a\u0446\u0438\u044e \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u0442\u044c. \u041e\u043d\u0430 \u0434\u043e\u043b\u0436\u043d\u0430 \u0432\u043e\u0437\u0440\u0430\u0449\u0430\u0442\u044c \u0442\u0438\u043f, \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0438 \u043c\u043e\u0436\u0435\u0442 \u0438\u043c\u0435\u0442\u044c \u043e\u0442 \u043e\u0434\u043d\u043e\u0433\u043e \u0434\u043e \u0442\u0440\u0451\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432:  <\/p>\n<ul>\n<li><i>\u0442\u0438\u043f \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u0441\u044f<\/i><\/li>\n<li><i>integer<\/i> \u2014 \u043c\u043e\u0434\u0438\u0444\u0438\u043a\u0430\u0442\u043e\u0440, \u0430\u0441\u0441\u043e\u0446\u0438\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u0441 \u0442\u0438\u043f\u043e\u043c \u043a \u043a\u043e\u0442\u043e\u0440\u043e\u043c\u0443 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0438\u043b\u0438 -1<\/li>\n<li><i>boolean<\/i> \u2014 true, \u0435\u0441\u043b\u0438 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u044f\u0432\u043d\u043e\u0435, \u0432 \u043f\u0440\u043e\u0442\u0438\u0432\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 false<\/li>\n<\/ul>\n<p>  \u041f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0443\u0447\u0430\u0432\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u043f\u0440\u0438\u0441\u0432\u0430\u0438\u0432\u0430\u043d\u0438\u044f \u0438\u043b\u0438 \u0436\u0435 \u0432 \u043b\u044e\u0431\u043e\u043c \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435. \u042d\u0442\u043e \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 AS ASSIGNMENT \u0438 AS IMPLICIT. \u041f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 WITH INOUT \u0443\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0432\u0432\u043e\u0434\u0430\/\u0432\u044b\u0432\u043e\u0434\u0430 \u0434\u043b\u044f \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u044f.<\/p>\n<p>  \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043d\u043e\u0432\u044b\u0439 \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u043d\u044b\u0439 \u0442\u0438\u043f vector3c \u0438 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043a \u043d\u0435\u043c\u0443 \u0442\u0438\u043f\u0430 vector3 (\u0438 \u043d\u0430\u043e\u0431\u043e\u0440\u043e\u0442):  <\/p>\n<pre><code class=\"sql\">CREATE TYPE vector3c AS ( \tx double precision, \ty double precision, \tz double precision );  CREATE OR REPLACE FUNCTION vector3_cast_vector3c ( v0 vector3 ) RETURNS vector3c AS $BODY$ DECLARE \ts text[]; \tv vector3c; BEGIN \ts := string_to_array ( trim ( BOTH '()' FROM v0::text ), ',' ); \tv.x := s[1]; \tv.y := s[2]; \tv.z := s[3]; \tRETURN v; END $BODY$ LANGUAGE plpgsql IMMUTABLE;  CREATE OR REPLACE FUNCTION vector3c_cast_vector3 ( v0 vector3c ) RETURNS vector3 AS $BODY$ DECLARE \tv vector3; BEGIN \tv := v0::text; \tRETURN v; END $BODY$ LANGUAGE plpgsql IMMUTABLE;  CREATE CAST ( vector3 AS vector3c ) WITH FUNCTION  vector3_cast_vector3c ( v0 vector3 ) AS IMPLICIT;  CREATE CAST ( vector3c AS vector3 ) WITH FUNCTION  vector3c_cast_vector3 ( v0 vector3c ) AS IMPLICIT; <\/code><\/pre>\n<p>  \u0412 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <i>vector3_cast_vector3c<\/i> \u043c\u044b \u0441\u043f\u0435\u0440\u0432\u0430 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u043c vector3 \u043a \u0442\u0435\u043a\u0441\u0442\u0443, \u0443\u0431\u0438\u0440\u0430\u0435\u043c \u043f\u0435\u0440\u0432\u0443\u044e \u0438 \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u044e\u044e \u0441\u043a\u043e\u0431\u043a\u0438 \u0438 \u0437\u0430\u0442\u0435\u043c, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f \u0440\u0430\u0437\u0434\u0435\u043b\u0438\u0442\u0435\u043b\u044c \u0437\u0430\u043f\u044f\u0442\u0443\u044e, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0435\u043c \u043a \u043c\u0430\u0441\u0441\u0438\u0432\u0443 \u0438\u0437 \u0442\u0440\u0451\u0445 \u0435\u043b\u0435\u043c\u0435\u043d\u0442\u043e\u0432, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0431\u0435\u0440\u0435\u043c \u043a\u043e\u043c\u043f\u043e\u043d\u0435\u043d\u0442\u044b \u0432\u0435\u043a\u0442\u043e\u0440\u0430. \u0412 <i>vector3c_cast_vector3<\/i>, \u0434\u043b\u044f \u043d\u0430\u0433\u043b\u044f\u0434\u043d\u043e\u0441\u0442\u0438, \u043c\u043e\u0436\u043d\u043e \u0441\u0440\u0430\u0437\u0443 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u044b\u0432\u0430\u0442\u044c vector3c \u0432 \u0442\u0435\u043a\u0441\u0442 \u0438 \u0437\u0430\u0442\u0435\u043c \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a vector3 (\u0442\u0435\u043a\u0441\u0442\u043e\u0432\u043e\u0435 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u0434\u043b\u044f vector3c \u0438 vector3 \u0438\u043c\u0435\u0435\u0442 \u043e\u0434\u0438\u043d \u0438 \u0442\u043e\u0442 \u0436\u0435 \u0432\u0438\u0434).<\/p>\n<p>  \u041f\u0440\u043e\u0432\u0435\u0440\u0438\u043c \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0442\u0438\u043f\u043e\u0432:  <\/p>\n<pre><code class=\"sql\">SELECT ('(0.1,1.0,0.5)'::vector3)::vector3c; -- (0.1,1,0.5) SELECT ('(0.707,0.0,0.0)'::vector3c)::vector3; -- (0.707000,0.000000,0.000000) <\/code><\/pre>\n<h4><b>\u0421\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f<\/b><\/h4>\n<p>  <img decoding=\"async\" src=\"http:\/\/habr.habrastorage.org\/post_images\/5d7\/86e\/9e0\/5d786e9e06a3aa079318f3766c355d34.jpg\"\/><br \/>  \u041a\u043e\u0433\u0434\u0430 \u0432\u0441\u0451 \u0433\u043e\u0442\u043e\u0432\u043e \u0438 \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u043e, \u043e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u043e\u0431\u0435\u0440\u043d\u0443\u0442\u044c \u043d\u0430\u0448\u0443 \u0431\u0438\u0431\u043b\u0438\u0442\u0435\u043a\u0443 \u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435. \u0421\u043e\u0431\u0435\u0440\u0435\u043c \u0432\u0435\u0441\u044c \u0421-\u043a\u043e\u0434 \u0432 \u043e\u0434\u0438\u043d \u0444\u0430\u0439\u043b:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0424\u0430\u0439\u043b math3d.c (\u0438\u0441\u0445\u043e\u0434\u043d\u044b\u0439 \u0421-\u043a\u043e\u0434 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f math3d)<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"cpp\">#include &lt;postgres.h&gt; #include &lt;fmgr.h&gt; #include &lt;libpq\/pqformat.h&gt; #include &lt;math.h&gt;  #ifdef PG_MODULE_MAGIC \tPG_MODULE_MAGIC; #endif  \/\/ types  typedef struct { \tdouble x, y, z; } vector3;  \/\/ declarations  PG_FUNCTION_INFO_V1(vector3_in); PG_FUNCTION_INFO_V1(vector3_out);  PG_FUNCTION_INFO_V1(vector3_recv); PG_FUNCTION_INFO_V1(vector3_send);  PG_FUNCTION_INFO_V1(vector3_minus); PG_FUNCTION_INFO_V1(vector3_add); PG_FUNCTION_INFO_V1(vector3_sub); PG_FUNCTION_INFO_V1(vector3_mul_left); PG_FUNCTION_INFO_V1(vector3_mul_right); PG_FUNCTION_INFO_V1(vector3_div_left); PG_FUNCTION_INFO_V1(vector3_div_right);  PG_FUNCTION_INFO_V1(vector3_equal); PG_FUNCTION_INFO_V1(vector3_not_equal);  PG_FUNCTION_INFO_V1(vector3_dot); PG_FUNCTION_INFO_V1(vector3_cross);  PG_FUNCTION_INFO_V1(vector3_length); PG_FUNCTION_INFO_V1(vector3_normalize); PG_FUNCTION_INFO_V1(vector3_distance);  \/\/ implementation  Datum vector3_in(PG_FUNCTION_ARGS) { \tchar *s = PG_GETARG_CSTRING(0);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tif (sscanf(s, &quot;(%lf,%lf,%lf)&quot;, &(v-&gt;x), &(v-&gt;y), &(v-&gt;z)) != 3) \t{ \t\tereport(ERROR, (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION), errmsg(&quot;Invalid input syntax for vector3: \\&quot;%s\\&quot;&quot;, s))); \t}  \tPG_RETURN_POINTER(v); }  Datum vector3_out(PG_FUNCTION_ARGS) { \tvector3 *v = (vector3*)PG_GETARG_POINTER(0);  \tchar *s = (char*)palloc(100);  \tsnprintf(s, 100, &quot;(%lf,%lf,%lf)&quot;, v-&gt;x, v-&gt;y, v-&gt;z);  \tPG_RETURN_CSTRING(s); }   Datum vector3_recv(PG_FUNCTION_ARGS) { \tStringInfo buffer = (StringInfo)PG_GETARG_POINTER(0);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = pq_getmsgfloat8(buffer); \tv-&gt;y = pq_getmsgfloat8(buffer); \tv-&gt;z = pq_getmsgfloat8(buffer);  \tPG_RETURN_POINTER(v); }  Datum vector3_send(PG_FUNCTION_ARGS) { \tvector3 *v = (vector3*)PG_GETARG_POINTER(0);  \tStringInfoData buffer;  \tpq_begintypsend(&buffer);  \tpq_sendfloat8(&buffer, v-&gt;x); \tpq_sendfloat8(&buffer, v-&gt;y); \tpq_sendfloat8(&buffer, v-&gt;z);  \tPG_RETURN_BYTEA_P(pq_endtypsend(&buffer)); }  Datum vector3_minus(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = -v0-&gt;x; \tv-&gt;y = -v0-&gt;y; \tv-&gt;z = -v0-&gt;z;  \tPG_RETURN_POINTER(v); }  Datum vector3_add(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = v0-&gt;x + v1-&gt;x; \tv-&gt;y = v0-&gt;y + v1-&gt;y; \tv-&gt;z = v0-&gt;z + v1-&gt;z;  \tPG_RETURN_POINTER(v); }  Datum vector3_sub(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = v0-&gt;x - v1-&gt;x; \tv-&gt;y = v0-&gt;y - v1-&gt;y; \tv-&gt;z = v0-&gt;z - v1-&gt;z;  \tPG_RETURN_POINTER(v); }  Datum vector3_mul_left(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tdouble k = PG_GETARG_FLOAT8(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = v0-&gt;x * k; \tv-&gt;y = v0-&gt;y * k; \tv-&gt;z = v0-&gt;z * k;  \tPG_RETURN_POINTER(v); }  Datum vector3_mul_right(PG_FUNCTION_ARGS) { \tdouble k = PG_GETARG_FLOAT8(0); \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = k * v0-&gt;x; \tv-&gt;y = k * v0-&gt;y; \tv-&gt;z = k * v0-&gt;z;  \tPG_RETURN_POINTER(v); }  Datum vector3_div_left(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tdouble k = PG_GETARG_FLOAT8(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = v0-&gt;x \/ k; \tv-&gt;y = v0-&gt;y \/ k; \tv-&gt;z = v0-&gt;z \/ k;  \tPG_RETURN_POINTER(v); }  Datum vector3_div_right(PG_FUNCTION_ARGS) { \tdouble k = PG_GETARG_FLOAT8(0); \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = k \/ v0-&gt;x; \tv-&gt;y = k \/ v0-&gt;y; \tv-&gt;z = k \/ v0-&gt;z;  \tPG_RETURN_POINTER(v); }  Datum vector3_equal(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tbool equal = true;  \tequal &= v0-&gt;x == v1-&gt;x; \tequal &= v0-&gt;y == v1-&gt;y; \tequal &= v0-&gt;z == v1-&gt;z;  \tPG_RETURN_BOOL(equal); }  Datum vector3_not_equal(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tbool not_equal = false;  \tnot_equal |= v0-&gt;x != v1-&gt;x; \tnot_equal |= v0-&gt;y != v1-&gt;y; \tnot_equal |= v0-&gt;z != v1-&gt;z;  \tPG_RETURN_BOOL(not_equal); }  Datum vector3_dot(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tdouble r = v0-&gt;x * v1-&gt;x + v0-&gt;y * v1-&gt;y + v0-&gt;z * v1-&gt;z;  \tPG_RETURN_FLOAT8(r); }  Datum vector3_cross(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = v0-&gt;y * v1-&gt;z - v0-&gt;z * v1-&gt;y; \tv-&gt;y = v0-&gt;z * v1-&gt;x - v0-&gt;x * v1-&gt;z; \tv-&gt;z = v0-&gt;x * v1-&gt;y - v0-&gt;y * v1-&gt;x;  \tPG_RETURN_POINTER(v); }  Datum vector3_length(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0);  \tdouble len = sqrt(v0-&gt;x * v0-&gt;x + v0-&gt;y * v0-&gt;y + v0-&gt;z * v0-&gt;z);  \tPG_RETURN_FLOAT8(len); }  Datum vector3_normalize(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tdouble len = sqrt(v0-&gt;x * v0-&gt;x + v0-&gt;y * v0-&gt;y + v0-&gt;z * v0-&gt;z);  \tif (len &gt; 0.000001) \t{ \t\tv-&gt;x = v0-&gt;y \/ len; \t\tv-&gt;y = v0-&gt;z \/ len; \t\tv-&gt;z = v0-&gt;x \/ len; \t} \telse \t{ \t\tv-&gt;x = 0.0; \t\tv-&gt;y = 0.0; \t\tv-&gt;z = 0.0; \t}  \tPG_RETURN_POINTER(v); }  Datum vector3_distance(PG_FUNCTION_ARGS) { \tvector3 *v0 = (vector3*)PG_GETARG_POINTER(0); \tvector3 *v1 = (vector3*)PG_GETARG_POINTER(1);  \tvector3 *v = (vector3*)palloc(sizeof(vector3));  \tv-&gt;x = v0-&gt;x - v1-&gt;x; \tv-&gt;y = v0-&gt;y - v1-&gt;y; \tv-&gt;z = v0-&gt;z - v1-&gt;z;  \tdouble len = sqrt(v-&gt;x * v-&gt;x + v-&gt;y * v-&gt;y + v-&gt;z * v-&gt;z);  \tpfree(v);  \tPG_RETURN_FLOAT8(len); } <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0421\u043e\u0431\u0435\u0440\u0451\u043c \u0441\u0430\u043c\u0443 \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0438 \u043f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0435\u0435 \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 PGDIR\/lib. \u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e, \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0444\u0430\u0439\u043b \u0441 SQL \u043a\u043e\u0434\u043e\u043c:  <\/p>\n<div class=\"spoiler\"><b class=\"spoiler_title\">\u0424\u0430\u0439\u043b math3d&#8212;1.0.sql (\u0441\u043a\u0440\u0438\u043f\u0442 SQL \u0434\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f math3d)<\/b><\/p>\n<div class=\"spoiler_text\">\n<pre><code class=\"sql\">CREATE TYPE vector3;  CREATE OR REPLACE FUNCTION vector3_in ( s cstring ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_in' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_out ( v vector3 ) RETURNS cstring AS 'MODULE_PATHNAME', 'vector3_out' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_recv ( p internal ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_recv' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION vector3_send ( v vector3 ) RETURNS bytea AS 'MODULE_PATHNAME', 'vector3_send' LANGUAGE C IMMUTABLE STRICT;  CREATE TYPE vector3 ( \tinternallength = 24, \tinput = vector3_in, \toutput = vector3_out, \treceive = vector3_recv, \tsend = vector3_send );  CREATE OR REPLACE FUNCTION vector3_minus ( v0 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_minus' LANGUAGE C IMMUTABLE STRICT;  CREATE OPERATOR - (     rightarg = vector3,     procedure = vector3_minus );  CREATE OR REPLACE FUNCTION vector3_add ( v0 vector3, v1 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_add' LANGUAGE C IMMUTABLE STRICT;  CREATE OPERATOR + (     leftarg = vector3,     rightarg = vector3,     procedure = vector3_add,     commutator = + );  CREATE OR REPLACE FUNCTION vector3_sub ( v0 vector3, v1 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_sub' LANGUAGE C IMMUTABLE STRICT;  CREATE OPERATOR - (     leftarg = vector3,     rightarg = vector3,     procedure = vector3_sub );  CREATE OR REPLACE FUNCTION vector3_mul_left ( v0 vector3, k double precision ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_mul_left' LANGUAGE C IMMUTABLE STRICT;  CREATE OPERATOR * (     leftarg = vector3,     rightarg = double precision,     procedure = vector3_mul_left,     commutator = * );  CREATE OR REPLACE FUNCTION vector3_mul_right ( k double precision, v0 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_mul_right' LANGUAGE C IMMUTABLE STRICT;  CREATE OPERATOR * (     leftarg = double precision,     rightarg = vector3,     procedure = vector3_mul_right,     commutator = * );  CREATE OR REPLACE FUNCTION vector3_div_left ( v0 vector3, k double precision ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_div_left' LANGUAGE C IMMUTABLE STRICT;  CREATE OPERATOR \/ (     leftarg = vector3,     rightarg = double precision,     procedure = vector3_div_left );  CREATE OR REPLACE FUNCTION vector3_div_right ( k double precision, v0 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_div_right' LANGUAGE C IMMUTABLE STRICT;  CREATE OPERATOR \/ (     leftarg = double precision,     rightarg = vector3,     procedure = vector3_div_right );  CREATE OR REPLACE FUNCTION vector3_equal ( v0 vector3, v1 vector3 ) RETURNS boolean AS 'MODULE_PATHNAME', 'vector3_equal' LANGUAGE C IMMUTABLE STRICT;  CREATE OPERATOR = (     leftarg = vector3,     rightarg = vector3,     procedure = vector3_equal );  CREATE OR REPLACE FUNCTION vector3_not_equal ( v0 vector3, v1 vector3 ) RETURNS boolean AS 'MODULE_PATHNAME', 'vector3_not_equal' LANGUAGE C IMMUTABLE STRICT;  CREATE OPERATOR != (     leftarg = vector3,     rightarg = vector3,     procedure = vector3_not_equal );  CREATE OR REPLACE FUNCTION vector3_dot ( v0 vector3, v1 vector3 ) RETURNS double precision AS 'MODULE_PATHNAME', 'vector3_dot' LANGUAGE C IMMUTABLE STRICT;  CREATE OPERATOR * (     leftarg = vector3,     rightarg = vector3,     procedure = vector3_dot,     commutator = * );  CREATE OR REPLACE FUNCTION vector3_cross ( v0 vector3, v1 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_cross' LANGUAGE C IMMUTABLE STRICT;  CREATE OPERATOR ** (     leftarg = vector3,     rightarg = vector3,     procedure = vector3_cross,     commutator = ** );  CREATE OR REPLACE FUNCTION length ( v0 vector3 ) RETURNS double precision AS 'MODULE_PATHNAME', 'vector3_length' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION normalize ( v0 vector3 ) RETURNS vector3 AS 'MODULE_PATHNAME', 'vector3_normalize' LANGUAGE C IMMUTABLE STRICT;  CREATE OR REPLACE FUNCTION distance ( v0 vector3, v1 vector3 ) RETURNS double precision AS 'MODULE_PATHNAME', 'vector3_distance' LANGUAGE C IMMUTABLE STRICT;  CREATE TYPE vector3c AS ( \tx double precision, \ty double precision, \tz double precision );  CREATE OR REPLACE FUNCTION vector3_cast_vector3c ( v0 vector3 ) RETURNS vector3c AS $BODY$ DECLARE \ts text[]; \tv vector3c; BEGIN \ts := string_to_array ( trim ( BOTH '()' FROM v0::text ), ',' ); \tv.x := s[1]; \tv.y := s[2]; \tv.z := s[3]; \tRETURN v; END $BODY$ LANGUAGE plpgsql IMMUTABLE;  CREATE OR REPLACE FUNCTION vector3c_cast_vector3 ( v0 vector3c ) RETURNS vector3 AS $BODY$ DECLARE \tv vector3; BEGIN \tv := v0::text; \tRETURN v; END $BODY$ LANGUAGE plpgsql IMMUTABLE;  CREATE CAST ( vector3 AS vector3c ) WITH FUNCTION  vector3_cast_vector3c ( v0 vector3 ) AS IMPLICIT;  CREATE CAST ( vector3c AS vector3 ) WITH FUNCTION  vector3c_cast_vector3 ( v0 vector3c ) AS IMPLICIT; <\/code><\/pre>\n<p>  <\/div>\n<\/div>\n<p>  \u0418\u043c\u044f \u0444\u0430\u0439\u043b\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432 \u0432\u0438\u0434\u0435 &lt;\u0438\u043c\u044f_\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f&gt;&#8212;&lt;\u0432\u0435\u0440\u0441\u0438\u044f&gt;.sql. \u0412\u0435\u0440\u0441\u0438\u044f \u0443 \u043d\u0430\u0441 \u0431\u0443\u0434\u0435\u0442 1.0. \u041f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 PGDIR\/share\/extension. \u0417\u0430\u043c\u0435\u0442\u044c\u0442\u0435, \u0447\u0442\u043e \u0438\u043c\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 \u0432 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0438\u044f\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0438\u0437\u043c\u0435\u043d\u0438\u043b\u043e\u0441\u044c \u043d\u0430 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e MODULE_PATHNAME, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0431\u0443\u0434\u0435\u0442 \u043e\u0431\u044a\u044f\u0432\u043b\u0435\u043d\u0430 \u0432 \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u043c \u0444\u0430\u0439\u043b\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f. \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u044d\u0442\u043e\u0442 \u0444\u0430\u0439\u043b:  <\/p>\n<pre><code class=\"bash\"># math3d extension comment = '3D mathematics' default_version = '1.0' module_pathname = '$libdir\/math3d' relocatable = true <\/code><\/pre>\n<p>  \u0421\u0440\u0435\u0434\u0438 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u043e\u0432 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0435:  <\/p>\n<ul>\n<li><i>default_version<\/i> \u2014 \u0432\u0435\u0440\u0441\u0438\u044f \u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e<\/li>\n<li><i>comment<\/i> \u2014 \u043a\u043e\u043c\u043c\u0435\u043d\u0442\u0430\u0440\u0438\u0439<\/li>\n<li><i>encoding<\/i> \u2014 \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u0441\u043a\u0440\u0438\u043f\u0442\u0430, \u0435\u0441\u043b\u0438 \u043d\u0435 \u0443\u043a\u0430\u0437\u0430\u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0443\u0435\u0442\u0441\u044f \u043a\u043e\u0434\u0438\u0440\u043e\u0432\u043a\u0430 \u0411\u0414<\/li>\n<li><i>module_pathname<\/i> \u2014 \u0438\u043c\u044f \u0434\u0438\u043d\u0430\u043c\u0438\u0447\u0435\u0441\u043a\u0438 \u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0435\u043c\u043e\u0439 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 (\u043f\u043e\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u0432 \u043f\u0435\u0440\u0435\u043c\u0435\u043d\u043d\u0443\u044e MODULE_PATHNAME \u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u0435)<\/li>\n<li><i>requires<\/i> \u2014 \u0441\u043f\u0438\u0441\u043e\u043a \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u0442\u0435\u043a\u0443\u0449\u0435\u0435<\/li>\n<li><i>relocatable<\/i> \u2014 \u0435\u0441\u043b\u0438 true, \u0442\u043e \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043d\u0435 \u043f\u0440\u0438\u0432\u044f\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0439 \u0441\u0445\u0435\u043c\u0435 \u0438 \u043e\u0431\u044a\u0435\u043a\u0442\u044b, \u043f\u043e\u0441\u043b\u0435 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u044f, \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u044b \u0432 \u0434\u0440\u0443\u0433\u0443\u044e \u0441\u0445\u0435\u043c\u0443 (\u043f\u043e \u0443\u043c\u043e\u043b\u0447\u0430\u043d\u0438\u044e false)<\/li>\n<li><i>schema<\/i> \u2014 \u0441\u0445\u0435\u043c\u0430, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u0439 \u0441\u043e\u0437\u0434\u0430\u044e\u0442\u0441\u044f \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f (\u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 \u0438\u043c\u0435\u0435\u0442 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435, \u0435\u0441\u043b\u0438 <i>relocatable<\/i> \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043b\u0435\u043d\u043e \u0432 false)<\/li>\n<\/ul>\n<p>  \u0418\u043c\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0449\u0435\u0433\u043e \u0444\u0430\u0439\u043b\u0430 \u0434\u043e\u043b\u0436\u043d\u043e \u0431\u044b\u0442\u044c \u0432 \u0432\u0438\u0434\u0435 &lt;\u0438\u043c\u044f_\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f&gt;.control, \u0432 \u0434\u0430\u043d\u043d\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 math3d.control. \u041f\u043e\u043c\u0435\u0441\u0442\u0438\u043c \u0435\u0433\u043e \u0432 \u043a\u0430\u0442\u0430\u043b\u043e\u0433 PGDIR\/share\/extension. \u0412 \u043f\u0440\u0438\u043d\u0446\u0438\u043f\u0435, \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u0433\u043e\u0442\u043e\u0432\u043e \u043a \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044e.<\/p>\n<p>  \u0421\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u043d\u043e\u0432\u0443\u044e \u0411\u0414, \u0441\u043e\u0435\u0434\u0438\u043d\u0438\u043c\u0441\u044f \u0441 \u043d\u0435\u0439 \u0438 \u0437\u0430\u0433\u0440\u0443\u0437\u0438\u043c \u043d\u0430\u0448\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435:  <\/p>\n<pre><code class=\"sql\">CREATE EXTENSION math3d; <\/code><\/pre>\n<p>  \u0415\u0441\u043b\u0438 \u043f\u0440\u043e\u0431\u043b\u0435\u043c \u043d\u0435\u0442, \u043c\u043e\u0436\u043d\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0441\u044f \u043d\u0430\u0448\u0438\u043c \u043d\u043e\u0432\u044b\u043c \u0442\u0438\u043f\u043e\u043c vector3 \u2014 \u043e\u0431\u044a\u044f\u0432\u043b\u044f\u0442\u044c \u043a\u0430\u043a \u043f\u043e\u043b\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u0438\u043b\u0438 \u043a\u043e\u043c\u043f\u043e\u0437\u0438\u0442\u043d\u043e\u0433\u043e \u0442\u0438\u043f\u0430, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440\u0430\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0438 \u0432 \u043f\u0440\u043e\u0447\u0438\u0445 \u043c\u0435\u0441\u0442\u0430\u0445. \u0423\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0438 \u0437\u0430\u0432\u0438\u0441\u0438\u043c\u044b\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0434\u0435\u043b\u0430\u0435\u0442\u0441\u044f \u0430\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439:  <\/p>\n<pre><code class=\"sql\">DROP EXTENSION math3d; <\/code><\/pre>\n<p>  \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0438\u0437\u043c\u0435\u043d\u044f\u0435\u043c\u044b\u0435 \u043f\u043e\u0441\u043b\u0435 \u0443\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f. \u0422\u0430\u043a \u043a\u0430\u043a \u043e\u0431\u044b\u0447\u043d\u044b\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b, \u0441\u043e\u0437\u0434\u0430\u0432\u0430\u0435\u043c\u044b\u0435 \u0432 \u0441\u043a\u0440\u0438\u043f\u0442\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0438 \u0435\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u043d\u0435 \u043f\u043e\u043f\u0430\u0434\u0430\u044e\u0442 \u0432 \u0434\u0430\u043c\u043f, \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0435 \u0442\u0430\u0431\u043b\u0438\u0446\u044b \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e \u0441\u043f\u0435\u0446\u0438\u0430\u043b\u044c\u043d\u044b\u043c \u043e\u0431\u0440\u0430\u0437\u043e\u043c \u043f\u043e\u043c\u0435\u0442\u0438\u0442\u044c:  <\/p>\n<pre><code class=\"sql\">CREATE TABLE user_setting ( username text, key text, value text ); SELECT pg_catalog.pg_extension_config_dump ( 'user_setting', '' ); <\/code><\/pre>\n<p>  \u0412\u0442\u043e\u0440\u043e\u0439 \u043f\u0430\u0440\u0430\u043c\u0435\u0442\u0440 pg_catalog.pg_extension_config_dump \u043c\u043e\u0436\u0435\u0442 \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u044c \u0443\u0441\u043b\u043e\u0432\u0438\u0435, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 \u0444\u0438\u043b\u044c\u0442\u0440\u0443\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435, \u043f\u043e\u043f\u0430\u0434\u0430\u0435\u043c\u044b\u0435 \u0432 \u0434\u0430\u043c\u043f, \u043a \u043f\u0440\u0438\u043c\u0435\u0440\u0443, &#8216;WHERE username = &#187;administrator&#187;&#8217;. \u0412 \u043d\u0430\u0448\u0435\u043c \u0441\u043b\u0443\u0447\u0430\u0435, \u043d\u0435\u0442 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432 \u043a\u043e\u043d\u0444\u0438\u0433\u0443\u0440\u0430\u0446\u0438\u043e\u043d\u043d\u044b\u0445 \u0442\u0430\u0431\u043b\u0438\u0446\u0430\u0445.<\/p>\n<p>  \u041f\u0440\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0434\u043e \u0431\u043e\u043b\u0435\u0435 \u043d\u043e\u0432\u043e\u0439 \u0432\u0435\u0440\u0441\u0438\u0438 \u0441\u043e\u0437\u0434\u0430\u0435\u0442\u0441\u044f \u0441\u043a\u0440\u0438\u043f\u0442, \u0438\u043c\u0435\u044e\u0449\u0438\u0439 \u0438\u043c\u044f \u0432 \u0432\u0438\u0434\u0435 &lt;\u0438\u043c\u044f_\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f&gt;&#8212;&lt;\u0441\u0442\u0430\u0440\u0430\u044f_\u0432\u0435\u0440\u0441\u0438\u044f&gt;&#8212;&lt;\u043d\u043e\u0432\u0430\u044f_\u0432\u0435\u0440\u0441\u0438\u044f&gt;.sql, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u043e\u0434\u0435\u0440\u0436\u0430\u0442\u0441\u044f SQL \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f. \u0415\u0441\u043b\u0438 \u0431\u044b \u043c\u044b \u0437\u0430\u0445\u043e\u0442\u0435\u043b\u0438 \u043e\u0431\u043d\u043e\u0432\u0438\u0442\u044c math3d \u0434\u043e \u0432\u0435\u0440\u0441\u0438\u0438 1.1, \u043d\u0430\u043c \u043d\u0443\u0436\u043d\u043e \u0431\u044b\u043b\u043e \u0431\u044b \u0441\u043e\u0437\u0434\u0430\u0442\u044c \u0444\u0430\u0439\u043b math3d&#8212;1.0&#8212;1.1.sql \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442\u044c SQL \u043a\u043e\u043c\u0430\u043d\u0434\u0443 \u0432 \u0411\u0414:  <\/p>\n<pre><code class=\"sql\">ALTER EXTENSION math3d UPDATE TO '1.1' <\/code><\/pre>\n<p>  \u041e\u0441\u0442\u0430\u043b\u044c\u043d\u044b\u0435 \u043a\u043e\u043c\u0430\u043d\u0434\u044b \u0434\u043b\u044f \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f (\u043f\u043e\u0434\u0440\u043e\u0431\u043d\u0435\u0439 \u043e\u043f\u0438\u0441\u0430\u043d\u043e <a href=\"http:\/\/www.postgresql.org\/docs\/9.3\/static\/sql-alterextension.html\">\u0442\u0443\u0442<\/a>):  <\/p>\n<pre><code class=\"sql\">ALTER EXTENSION &lt;\u0438\u043c\u044f_\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f&gt; SET SCHEMA &lt;\u043d\u043e\u0432\u0430\u044f \u0441\u0445\u0435\u043c\u0430&gt;; -- \u043f\u0435\u0440\u0435\u043c\u0435\u0449\u0435\u043d\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0432 \u0443\u043a\u0430\u0437\u0430\u043d\u043d\u0443\u044e \u0441\u0445\u0435\u043c\u0443 ALTER EXTENSION &lt;\u0438\u043c\u044f_\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f&gt; ADD &lt;\u043e\u0431\u044a\u0435\u043a\u0442&gt;; -- \u0434\u043e\u0431\u0430\u0432\u043b\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435 ALTER EXTENSION &lt;\u0438\u043c\u044f_\u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f&gt; DROP &lt;\u043e\u0431\u044a\u0435\u043a\u0442&gt;; -- \u0443\u0434\u0430\u043b\u0435\u043d\u0438\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 \u0438\u0437 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f <\/code><\/pre>\n<p>  \u0415\u0449\u0435 \u043e\u0434\u043d\u043e\u0439 \u0445\u043e\u0440\u043e\u0448\u0435\u0439 \u0432\u0435\u0449\u044c\u044e \u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0438 \u0435\u0441\u0442\u044c \u0442\u043e, \u0447\u0442\u043e \u043d\u0435\u043b\u044c\u0437\u044f \u043e\u0431\u044b\u0447\u043d\u043e\u0439 \u043a\u043e\u043c\u0430\u043d\u0434\u043e\u0439 (DROP TABLE, DROP FUNCTION \u0438 \u0442.\u0434.) \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e \u0443\u0434\u0430\u043b\u0438\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442, \u0432\u0445\u043e\u0434\u044f\u0449\u0438\u0439 \u0432 \u0441\u043e\u0441\u0442\u0430\u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f.<\/p>\n<h4><b>\u0417\u0430\u043a\u043b\u044e\u0447\u0435\u043d\u0438\u0435<\/b><\/h4>\n<p>  <img decoding=\"async\" src=\"http:\/\/habr.habrastorage.org\/post_images\/851\/8e2\/2ce\/8518e22ce7dfed64eab826028f5cdbaf.jpg\"\/><br \/>  \u0415\u0441\u043b\u0438 \u0432 \u0412\u0430\u0448\u0435\u0439 \u0411\u0414 \u0430\u043a\u0442\u0438\u0432\u043d\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u043e\u043d\u0430\u043b, \u043e\u0441\u043d\u043e\u0432\u0430\u043d\u043d\u044b\u0439 \u043d\u0430 \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u044f\u0445 \u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0435\u043c\u044b\u0445 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u044f\u0445, \u0435\u0433\u043e \u043c\u043e\u0436\u043d\u043e \u0432\u044b\u043d\u0435\u0441\u0442\u0438 \u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0435, \u043f\u043e\u043b\u0443\u0447\u0438\u0432 \u043d\u0435\u043a\u043e\u0442\u043e\u0440\u0443\u044e \u043e\u0431\u043e\u0441\u043e\u0431\u043b\u0435\u043d\u043d\u043e\u0441\u0442\u044c \u043e\u0442 \u0434\u0440\u0443\u0433\u0438\u0445 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u0432 \u0432 \u0411\u0414 \u0438 \u0443\u043f\u0440\u043e\u0441\u0442\u0438\u0432 \u0440\u0430\u0441\u0448\u0438\u0440\u044f\u0435\u043c\u043e\u0441\u0442\u044c.<\/p>\n<p>  P.S. \u0421\u043f\u0430\u0441\u0438\u0431\u043e \u0437\u0430 \u0432\u043d\u0438\u043c\u0430\u043d\u0438\u0435.<\/p>\n<p>  \u0421\u0441\u044b\u043b\u043a\u0438:  <\/p>\n<ul>\n<li><a href=\"http:\/\/www.postgresql.org\/docs\/9.3\/static\">\u041e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u0430\u044f \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u044f \u043f\u043e PostgreSQL<\/a><\/li>\n<\/ul>\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\/198332\/\"> http:\/\/habrahabr.ru\/post\/198332\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"content html_format\">   \t<img decoding=\"async\" src=\"http:\/\/habr.habrastorage.org\/post_images\/890\/a02\/abf\/890a02abf9fb65612c78c7803aaa24c5.jpg\"\/><br \/>  \u0417\u0434\u0440\u0430\u0432\u0441\u0442\u0432\u0443\u0439\u0442\u0435, \u0445\u0430\u0431\u0440\u0430\u0447\u0435\u043b\u043e\u0432\u0435\u043a\u0438! \u0422\u0435\u043c\u043e\u0439 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u0431\u0443\u0434\u0435\u0442 \u0441\u043e\u0437\u0434\u0430\u043d\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0434\u043b\u044f <b>PostgreSQL<\/b>. \u0412 \u043a\u0430\u0447\u0435\u0441\u0442\u0432\u0435 \u043f\u0440\u0438\u043c\u0435\u0440\u0430, \u043c\u044b \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u0435\u043c \u043d\u0435\u0431\u043e\u043b\u044c\u0448\u0443\u044e \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0443 \u0434\u043b\u044f \u0440\u0430\u0431\u043e\u0442\u044b \u0441 3D \u0432\u0435\u043a\u0442\u043e\u0440\u0430\u043c\u0438. \u041f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0431\u0443\u0434\u0443\u0442 \u0440\u0430\u0441\u0441\u043c\u043e\u0442\u0440\u0435\u043d\u044b \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u0441\u043a\u0438\u0435 \u0442\u0438\u043f\u044b, \u043e\u043f\u0435\u0440\u0430\u0442\u043e\u0440\u044b \u0438 \u043f\u0440\u0438\u0432\u0435\u0434\u0435\u043d\u0438\u044f \u0442\u0438\u043f\u043e\u0432. \u041d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043b\u0438\u0448\u043d\u0438\u043c \u043e\u0437\u043d\u0430\u043a\u043e\u043c\u0438\u0441\u044f \u0441 <a href=\"http:\/\/habrahabr.ru\/post\/196544\">\u044d\u0442\u0438\u043c<\/a> \u043c\u0430\u0442\u0435\u0440\u0438\u0430\u043b\u043e\u043c, \u0442\u0430\u043a \u043a\u0430\u043a \u0440\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u0445\u0440\u0430\u043d\u0438\u043c\u044b\u0445 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0431\u0443\u0434\u0435\u0442 \u043d\u0430 \u044f\u0437\u044b\u043a\u0435 C. \u041d\u0430\u0434\u0435\u044e\u0441\u044c, \u0434\u0440\u0443\u0437\u044c\u044f \u0441\u043b\u043e\u043d\u043e\u0432 \u043f\u043e\u043c\u043e\u0433\u0443\u0442 \u0441\u043a\u0440\u0430\u0441\u0438\u0442\u044c \u0441\u0435\u0440\u044b\u0439 \u0442\u0435\u0445\u043d\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0442\u0435\u043a\u0441\u0442 \u0441\u0442\u0430\u0442\u044c\u0438.  <\/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-198332","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/198332","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=198332"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/198332\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=198332"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=198332"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=198332"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}