pgsql_function.sql 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  1. CREATE OR REPLACE FUNCTION FIND_IN_SET(
  2. target text,
  3. list text
  4. ) RETURNS boolean AS $$
  5. DECLARE
  6. arr text[];
  7. i integer;
  8. BEGIN
  9. IF list IS NULL OR list = '' THEN
  10. RETURN false;
  11. END IF;
  12. arr := string_to_array(list, ',');
  13. FOR i IN 1..array_length(arr, 1) LOOP
  14. IF arr[i] = target THEN
  15. RETURN true;
  16. END IF;
  17. END LOOP;
  18. RETURN false;
  19. END;
  20. $$ LANGUAGE plpgsql IMMUTABLE;
  21. --
  22. CREATE OR REPLACE FUNCTION FIND_IN_SET(
  23. target integer,
  24. list text
  25. ) RETURNS boolean AS $$
  26. BEGIN
  27. RETURN FIND_IN_SET(target::text, list);
  28. END;
  29. $$ LANGUAGE plpgsql IMMUTABLE;
  30. --
  31. CREATE OR REPLACE FUNCTION GROUP_CONCAT(
  32. input text,
  33. delimiter text = ','
  34. ) RETURNS text AS $$
  35. BEGIN
  36. RETURN string_agg(input, delimiter);
  37. END;
  38. $$ LANGUAGE plpgsql IMMUTABLE;
  39. CREATE OR REPLACE FUNCTION GROUP_CONCAT(
  40. input numeric,
  41. delimiter text = ','
  42. ) RETURNS text AS $$
  43. BEGIN
  44. RETURN string_agg(input::text, delimiter);
  45. END;
  46. $$ LANGUAGE plpgsql IMMUTABLE;
  47. CREATE OR REPLACE FUNCTION GROUP_CONCAT(
  48. input integer,
  49. delimiter text = ','
  50. ) RETURNS text AS $$
  51. BEGIN
  52. RETURN string_agg(input::text, delimiter);
  53. END;
  54. $$ LANGUAGE plpgsql IMMUTABLE;
  55. --
  56. CREATE OR REPLACE FUNCTION ROUND(
  57. num float,
  58. decimals integer
  59. ) RETURNS numeric AS $$
  60. BEGIN
  61. RETURN ROUND(num::numeric, decimals);
  62. END;
  63. $$ LANGUAGE plpgsql IMMUTABLE;
  64. --
  65. CREATE OR REPLACE FUNCTION ROUND(
  66. num double precision,
  67. decimals integer
  68. ) RETURNS numeric AS $$
  69. BEGIN
  70. RETURN ROUND(num::numeric, decimals);
  71. END;
  72. $$ LANGUAGE plpgsql IMMUTABLE;
  73. --
  74. CREATE OR REPLACE FUNCTION ROUND(
  75. num text,
  76. decimals integer
  77. ) RETURNS numeric AS $$
  78. BEGIN
  79. RETURN ROUND(num::numeric, decimals);
  80. END;
  81. $$ LANGUAGE plpgsql IMMUTABLE;
  82. --
  83. CREATE OR REPLACE FUNCTION TIMESTAMPDIFF(
  84. unit TEXT,
  85. start_time TIMESTAMP,
  86. end_time TIMESTAMP
  87. ) RETURNS INTEGER AS $$
  88. DECLARE
  89. diff_interval INTERVAL;
  90. diff_seconds NUMERIC;
  91. BEGIN
  92. diff_interval := end_time - start_time;
  93. CASE lower(unit)
  94. WHEN 'year' THEN
  95. RETURN EXTRACT(YEAR FROM end_time) - EXTRACT(YEAR FROM start_time)
  96. - CASE WHEN (EXTRACT(MONTH FROM end_time) < EXTRACT(MONTH FROM start_time))
  97. OR (EXTRACT(MONTH FROM end_time) = EXTRACT(MONTH FROM start_time)
  98. AND EXTRACT(DAY FROM end_time) < EXTRACT(DAY FROM start_time))
  99. THEN 1 ELSE 0 END;
  100. WHEN 'month' THEN
  101. RETURN (EXTRACT(YEAR FROM end_time) - EXTRACT(YEAR FROM start_time)) * 12
  102. + (EXTRACT(MONTH FROM end_time) - EXTRACT(MONTH FROM start_time))
  103. - CASE WHEN EXTRACT(DAY FROM end_time) < EXTRACT(DAY FROM start_time)
  104. THEN 1 ELSE 0 END;
  105. WHEN 'day' THEN
  106. RETURN EXTRACT(DAY FROM diff_interval);
  107. WHEN 'hour' THEN
  108. diff_seconds := EXTRACT(EPOCH FROM diff_interval);
  109. RETURN floor(diff_seconds / 3600);
  110. WHEN 'minute' THEN
  111. diff_seconds := EXTRACT(EPOCH FROM diff_interval);
  112. RETURN floor(diff_seconds / 60);
  113. WHEN 'second' THEN
  114. RETURN EXTRACT(EPOCH FROM diff_interval);
  115. ELSE
  116. RETURN NULL;
  117. END CASE;
  118. END;
  119. $$ LANGUAGE plpgsql IMMUTABLE;
  120. --
  121. CREATE OR REPLACE FUNCTION IFNULL(bigint, integer)
  122. RETURNS bigint AS $$
  123. BEGIN
  124. RETURN COALESCE($1, $2::bigint);
  125. END;
  126. $$ LANGUAGE plpgsql IMMUTABLE;
  127. --
  128. CREATE OR REPLACE FUNCTION IFNULL(double precision, integer)
  129. RETURNS double precision AS $$
  130. BEGIN
  131. RETURN COALESCE($1, $2::double precision);
  132. END;
  133. $$ LANGUAGE plpgsql IMMUTABLE;
  134. --
  135. CREATE OR REPLACE FUNCTION IFNULL(integer, bigint)
  136. RETURNS bigint AS $$
  137. BEGIN
  138. RETURN COALESCE($1::bigint, $2);
  139. END;
  140. $$ LANGUAGE plpgsql IMMUTABLE;
  141. --
  142. CREATE OR REPLACE FUNCTION IFNULL(bigint, bigint)
  143. RETURNS bigint AS $$
  144. BEGIN
  145. RETURN COALESCE($1, $2);
  146. END;
  147. $$ LANGUAGE plpgsql IMMUTABLE;
  148. --
  149. CREATE OR REPLACE FUNCTION IFNULL(integer, integer)
  150. RETURNS integer AS $$
  151. BEGIN
  152. RETURN COALESCE($1, $2);
  153. END;
  154. $$ LANGUAGE plpgsql IMMUTABLE;
  155. --
  156. CREATE OR REPLACE FUNCTION IFNULL(numeric, numeric)
  157. RETURNS numeric AS $$
  158. BEGIN
  159. RETURN COALESCE($1, $2);
  160. END;
  161. $$ LANGUAGE plpgsql IMMUTABLE;
  162. --
  163. CREATE OR REPLACE FUNCTION IFNULL(text, text)
  164. RETURNS text AS $$
  165. BEGIN
  166. RETURN COALESCE($1, $2);
  167. END;
  168. $$ LANGUAGE plpgsql IMMUTABLE;
  169. --
  170. CREATE OR REPLACE FUNCTION day(date_val DATE)
  171. RETURNS INTEGER AS $$ BEGIN RETURN EXTRACT(DAY FROM date_val)::INTEGER; END; $$ LANGUAGE plpgsql;
  172. --
  173. CREATE OR REPLACE FUNCTION day(date_val TIMESTAMP)
  174. RETURNS INTEGER AS $$ BEGIN RETURN EXTRACT(DAY FROM date_val)::INTEGER; END; $$ LANGUAGE plpgsql;
  175. --
  176. CREATE OR REPLACE FUNCTION day(date_val TIMESTAMPTZ)
  177. RETURNS INTEGER AS $$ BEGIN RETURN EXTRACT(DAY FROM date_val)::INTEGER; END; $$ LANGUAGE plpgsql;
  178. --
  179. CREATE OR REPLACE FUNCTION MONTH(date_val DATE)
  180. RETURNS INTEGER AS $$ BEGIN RETURN EXTRACT(MONTH FROM date_val)::INTEGER; END; $$ LANGUAGE plpgsql;
  181. --
  182. CREATE OR REPLACE FUNCTION MONTH(date_val TIMESTAMP)
  183. RETURNS INTEGER AS $$ BEGIN RETURN EXTRACT(MONTH FROM date_val)::INTEGER; END; $$ LANGUAGE plpgsql;
  184. --
  185. CREATE OR REPLACE FUNCTION MONTH(date_val TIMESTAMPTZ)
  186. RETURNS INTEGER AS $$ BEGIN RETURN EXTRACT(MONTH FROM date_val)::INTEGER; END; $$ LANGUAGE plpgsql;
  187. --
  188. CREATE OR REPLACE FUNCTION YEAR(date_val DATE)
  189. RETURNS INTEGER AS $$ BEGIN RETURN EXTRACT(YEAR FROM date_val)::INTEGER; END; $$ LANGUAGE plpgsql;
  190. --
  191. CREATE OR REPLACE FUNCTION YEAR(date_val TIMESTAMP)
  192. RETURNS INTEGER AS $$ BEGIN RETURN EXTRACT(YEAR FROM date_val)::INTEGER; END; $$ LANGUAGE plpgsql;
  193. --
  194. CREATE OR REPLACE FUNCTION YEAR(date_val TIMESTAMPTZ)
  195. RETURNS INTEGER AS $$ BEGIN RETURN EXTRACT(YEAR FROM date_val)::INTEGER; END; $$ LANGUAGE plpgsql;
  196. --
  197. CREATE OR REPLACE FUNCTION DATEDIFF(
  198. end_date ANYELEMENT,
  199. start_date ANYELEMENT
  200. ) RETURNS INTEGER AS $$
  201. BEGIN
  202. RETURN (end_date - start_date)::INTEGER;
  203. END;
  204. $$ LANGUAGE plpgsql;
  205. --
  206. CREATE OR REPLACE FUNCTION "IF"(
  207. condition BOOLEAN,
  208. true_val BOOLEAN,
  209. false_val BOOLEAN
  210. ) RETURNS BOOLEAN AS $$
  211. BEGIN
  212. IF condition THEN
  213. RETURN true_val;
  214. ELSE
  215. RETURN false_val;
  216. END IF;
  217. END;
  218. $$ LANGUAGE plpgsql;
  219. --
  220. CREATE OR REPLACE FUNCTION "IF"(
  221. condition BOOLEAN,
  222. true_val DOUBLE PRECISION,
  223. false_val INTEGER
  224. ) RETURNS DOUBLE PRECISION AS $$
  225. BEGIN
  226. IF condition THEN
  227. RETURN true_val;
  228. ELSE
  229. RETURN false_val::DOUBLE PRECISION;
  230. END IF;
  231. END;
  232. $$ LANGUAGE plpgsql;
  233. --
  234. CREATE OR REPLACE FUNCTION "IF"(
  235. condition BOOLEAN,
  236. true_val DOUBLE PRECISION,
  237. false_val DOUBLE PRECISION
  238. ) RETURNS DOUBLE PRECISION AS $$
  239. BEGIN
  240. IF condition THEN
  241. RETURN true_val;
  242. ELSE
  243. RETURN false_val;
  244. END IF;
  245. END;
  246. $$ LANGUAGE plpgsql;
  247. --
  248. CREATE OR REPLACE FUNCTION "IF"(
  249. condition BOOLEAN,
  250. true_val TEXT,
  251. false_val TEXT
  252. ) RETURNS TEXT AS $$
  253. BEGIN
  254. IF condition THEN
  255. RETURN true_val;
  256. ELSE
  257. RETURN false_val;
  258. END IF;
  259. END;
  260. $$ LANGUAGE plpgsql;
  261. --
  262. CREATE OR REPLACE FUNCTION "IF"(
  263. condition BOOLEAN,
  264. true_val INTEGER,
  265. false_val INTEGER
  266. ) RETURNS INTEGER AS $$
  267. BEGIN
  268. IF condition THEN
  269. RETURN true_val;
  270. ELSE
  271. RETURN false_val;
  272. END IF;
  273. END;
  274. $$ LANGUAGE plpgsql;
  275. --
  276. CREATE OR REPLACE FUNCTION "IF"(
  277. condition BOOLEAN,
  278. true_val TEXT,
  279. false_val DATE
  280. ) RETURNS DATE AS $$
  281. BEGIN
  282. IF condition THEN
  283. RETURN true_val;
  284. ELSE
  285. RETURN false_val::DATE;
  286. END IF;
  287. END;
  288. $$ LANGUAGE plpgsql;
  289. --
  290. CREATE OR REPLACE FUNCTION "IF"(
  291. condition BOOLEAN,
  292. true_val DATE,
  293. false_val DATE
  294. ) RETURNS DATE AS $$
  295. BEGIN
  296. IF condition THEN
  297. RETURN true_val;
  298. ELSE
  299. RETURN false_val;
  300. END IF;
  301. END;
  302. $$ LANGUAGE plpgsql;
  303. --
  304. CREATE OR REPLACE FUNCTION "IF"(
  305. condition BOOLEAN,
  306. true_val timestamp without time zone,
  307. false_val DATE
  308. ) RETURNS DATE AS $$
  309. BEGIN
  310. IF condition THEN
  311. RETURN true_val::DATE;
  312. ELSE
  313. RETURN false_val;
  314. END IF;
  315. END;
  316. $$ LANGUAGE plpgsql;
  317. --
  318. CREATE OR REPLACE FUNCTION "IF"(
  319. condition BOOLEAN,
  320. true_val timestamp without time zone,
  321. false_val timestamp without time zone
  322. ) RETURNS DATE AS $$
  323. BEGIN
  324. IF condition THEN
  325. RETURN true_val;
  326. ELSE
  327. RETURN false_val;
  328. END IF;
  329. END;
  330. $$ LANGUAGE plpgsql;
  331. --
  332. CREATE OR REPLACE FUNCTION DATE_FORMAT(
  333. date_val DATE,
  334. format_str TEXT
  335. ) RETURNS TEXT AS $$
  336. DECLARE
  337. pg_format TEXT;
  338. BEGIN
  339. pg_format := REPLACE(format_str, '%Y', 'YYYY');
  340. pg_format := REPLACE(pg_format, '%y', 'YY');
  341. pg_format := REPLACE(pg_format, '%m', 'MM');
  342. pg_format := REPLACE(pg_format, '%c', 'MM');
  343. pg_format := REPLACE(pg_format, '%d', 'DD');
  344. pg_format := REPLACE(pg_format, '%e', 'DD');
  345. pg_format := REPLACE(pg_format, '%H', 'HH24');
  346. pg_format := REPLACE(pg_format, '%h', 'HH12');
  347. pg_format := REPLACE(pg_format, '%i', 'MI');
  348. pg_format := REPLACE(pg_format, '%s', 'SS');
  349. pg_format := REPLACE(pg_format, '%W', 'Day');
  350. pg_format := REPLACE(pg_format, '%a', 'Dy');
  351. pg_format := REPLACE(pg_format, '%M', 'Month');
  352. pg_format := REPLACE(pg_format, '%b', 'Mon');
  353. RETURN TO_CHAR(date_val, pg_format);
  354. END;
  355. $$ LANGUAGE plpgsql IMMUTABLE;
  356. --
  357. CREATE OR REPLACE FUNCTION instr(
  358. str TEXT,
  359. sub_str TEXT
  360. )
  361. RETURNS INTEGER AS $$
  362. BEGIN
  363. IF str IS NULL OR sub_str IS NULL OR sub_str = '' THEN
  364. RETURN 0;
  365. END IF;
  366. RETURN strpos(LOWER(str), LOWER(sub_str));
  367. END;
  368. $$ LANGUAGE plpgsql IMMUTABLE;
  369. --
  370. CREATE OR REPLACE FUNCTION left(
  371. str TEXT,
  372. length INT
  373. )
  374. RETURNS TEXT AS $$
  375. BEGIN
  376. IF str IS NULL OR length IS NULL THEN
  377. RETURN NULL;
  378. END IF;
  379. IF length <= 0 THEN
  380. RETURN '';
  381. END IF;
  382. RETURN pg_catalog.left(str, length);
  383. END;
  384. $$ LANGUAGE plpgsql IMMUTABLE;
  385. --
  386. CREATE OR REPLACE FUNCTION left(
  387. str DATE,
  388. length INT
  389. )
  390. RETURNS TEXT AS $$
  391. BEGIN
  392. RETURN left(str::TEXT, length);
  393. END;
  394. $$ LANGUAGE plpgsql IMMUTABLE;
  395. --
  396. CREATE OR REPLACE FUNCTION left(
  397. str NUMERIC,
  398. length INT
  399. )
  400. RETURNS TEXT AS $$
  401. BEGIN
  402. RETURN left(str::TEXT, length);
  403. END;
  404. $$ LANGUAGE plpgsql IMMUTABLE;
  405. --
  406. CREATE OR REPLACE FUNCTION left(
  407. str TIMESTAMP,
  408. length INT
  409. )
  410. RETURNS TEXT AS $$
  411. BEGIN
  412. RETURN left(str::TEXT, length);
  413. END;
  414. $$ LANGUAGE plpgsql IMMUTABLE;
  415. --
  416. CREATE OR REPLACE FUNCTION date_format(
  417. input_date TIMESTAMP WITHOUT TIME ZONE,
  418. format_str TEXT
  419. ) RETURNS TEXT AS $$
  420. DECLARE
  421. mapped_format TEXT := format_str;
  422. BEGIN
  423. mapped_format := REPLACE(mapped_format, '%Y', 'YYYY');
  424. mapped_format := REPLACE(mapped_format, '%y', 'YY');
  425. mapped_format := REPLACE(mapped_format, '%m', 'MM');
  426. mapped_format := REPLACE(mapped_format, '%c', 'FM MM');
  427. mapped_format := REPLACE(mapped_format, '%d', 'DD');
  428. mapped_format := REPLACE(mapped_format, '%e', 'FM DD');
  429. mapped_format := REPLACE(mapped_format, '%H', 'HH24');
  430. mapped_format := REPLACE(mapped_format, '%h', 'HH12');
  431. mapped_format := REPLACE(mapped_format, '%i', 'MI');
  432. mapped_format := REPLACE(mapped_format, '%s', 'SS');
  433. mapped_format := REPLACE(mapped_format, '%W', 'Day');
  434. mapped_format := REPLACE(mapped_format, '%w', 'D');
  435. mapped_format := REPLACE(mapped_format, '%M', 'Month');
  436. mapped_format := REPLACE(mapped_format, '%b', 'Mon');
  437. mapped_format := REPLACE(mapped_format, '%p', 'AM');
  438. mapped_format := REPLACE(mapped_format, '%T', 'HH24:MI:SS');
  439. mapped_format := REPLACE(mapped_format, '%j', 'DDD');
  440. mapped_format := REPLACE(mapped_format, 'FM MM', 'FMMM');
  441. mapped_format := REPLACE(mapped_format, 'FM DD', 'FMDD');
  442. RETURN TO_CHAR(input_date, mapped_format);
  443. END;
  444. $$ LANGUAGE plpgsql IMMUTABLE;
  445. --
  446. CREATE OR REPLACE FUNCTION update_tables_seq ( )
  447. RETURNS void AS $$
  448. DECLARE
  449. seq_name_cursor CURSOR FOR
  450. SELECT a.attname AS column_name, c.relname AS table_name, s.relname AS seq_name
  451. FROM pg_class c
  452. JOIN pg_depend d ON d.refobjid = c.oid
  453. JOIN pg_class s ON d.objid = s.oid
  454. JOIN pg_namespace n ON s.relnamespace = n.oid
  455. JOIN pg_attribute a ON a.attrelid = c.oid AND a.attnum = d.refobjsubid
  456. WHERE d.classid = 'pg_class'::regclass
  457. AND d.refclassid = 'pg_class'::regclass
  458. AND s.relkind = 'S'
  459. AND n.nspname = 'public';
  460. prepared_sql VARCHAR(255);
  461. BEGIN
  462. FOR ref_record in seq_name_cursor LOOP
  463. prepared_sql := 'SELECT setval( ''' || ref_record.seq_name;
  464. prepared_sql := prepared_sql || ''','||'( SELECT MAX ( ' || ref_record.column_name || ' ) FROM "'||ref_record.table_name||'") );';
  465. RAISE NOTICE '%', prepared_sql;
  466. EXECUTE prepared_sql;
  467. END LOOP;
  468. END;
  469. $$ LANGUAGE plpgsql;