udflib.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470
  1. /*====================================================================
  2. File Name: udflib.c
  3. Description:
  4. This module contains some user defined functions (UDF).
  5. The test suite for UDF will use udf.sql
  6. to define UDF to the database using SQL statements.
  7. * The contents of this file are subject to the Interbase Public
  8. * License Version 1.0 (the "License"); you may not use this file
  9. * except in compliance with the License. You may obtain a copy
  10. * of the License at http://www.Inprise.com/IPL.html
  11. *
  12. * Software distributed under the License is distributed on an
  13. * "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express
  14. * or implied. See the License for the specific language governing
  15. * rights and limitations under the License.
  16. *
  17. * The Original Code was created by Inprise Corporation
  18. * and its predecessors. Portions created by Inprise Corporation are
  19. * Copyright (C) Inprise Corporation.
  20. *
  21. * All Rights Reserved.
  22. * Contributor(s): ______________________________________.
  23. ====================================================================== */
  24. #include <stdlib.h>
  25. #if TIME_WITH_SYS_TIME
  26. # include <sys/time.h>
  27. # include <time.h>
  28. #else
  29. # if HAVE_SYS_TIME_H
  30. # include <sys/time.h>
  31. # else
  32. # include <time.h>
  33. # endif
  34. #endif
  35. #include <string.h>
  36. #include <math.h>
  37. #include "firebird/ibase.h"
  38. #include "example.h"
  39. #include "firebird/ib_util.h"
  40. #define BADVAL -9999L
  41. #define MYBUF_LEN 15 /* number of chars to get for */
  42. typedef struct blob {
  43. short (*blob_get_segment) ();
  44. void *blob_handle;
  45. int blob_number_segments;
  46. int blob_max_segment;
  47. int blob_total_length;
  48. void (*blob_put_segment) ();
  49. } *BLOB;
  50. time_t time();
  51. char *ctime();
  52. /* variable to return values in. Needs to be static so it doesn't go
  53. away as soon as the function invocation is finished */
  54. char buffer[256];
  55. char buffer2[512]; /* for string concatenation */
  56. char datebuf[12]; /* for date string */
  57. int r_long;
  58. double r_double;
  59. float r_float;
  60. short r_short;
  61. struct tm *tbuf;
  62. int time_sec;
  63. ISC_QUAD newdate;
  64. /*===============================================================
  65. fn_lower_c() - Puts its argument longo lower case, for C programs
  66. Input is of VARCHAR, output is of CSTRING.
  67. Not international or non-ascii friendly.
  68. ================================================================= */
  69. char* EXPORT fn_lower_c(char* s) /* VARCHAR input */
  70. {
  71. char *buf;
  72. short length = 0;
  73. char *buffer = (char *)ib_util_malloc(256);
  74. length = (short)*s;
  75. s += 2;
  76. buf = buffer;
  77. while (*s)
  78. if (*s >= 'A' && *s <= 'Z')
  79. *buf++ = *s++ - 'A' + 'a';
  80. else
  81. *buf++ = *s++;
  82. *buf = '\0';
  83. buffer [length] = '\0';
  84. return buffer;
  85. }
  86. /*===============================================================
  87. fn_strcat(s1, s2) - Returns concatenated string.
  88. s1 and s2 are varchar to get a length count
  89. ================================================================= */
  90. char* EXPORT fn_strcat(char* s1, char* s2)
  91. {
  92. short j = 0;
  93. short length1, length2;
  94. char *p;
  95. char *buffer2 = (char *)ib_util_malloc(512);
  96. length1 = (short)*s1;
  97. length2 = (short)*s2;
  98. s1 += 2;
  99. s2 += 2;
  100. /* strip trailing blanks of s1 */
  101. p = s1 + length1 - 1;
  102. while (*p && *p == ' ')
  103. p--;
  104. p++;
  105. *p = '\0';
  106. p = buffer2;
  107. while (*s1)
  108. *p++ = *s1++;
  109. for (j = 0; j < length2; j++)
  110. if (*s2)
  111. *p++ = *s2++;
  112. *p = '\0';
  113. return buffer2;
  114. }
  115. /*===============================================================
  116. fn_substr(s, m, n) - Returns the substr starting m ending n in s.
  117. ================================================================= */
  118. char* EXPORT fn_substr(char* s,
  119. short* m, /* starting position */
  120. short* n) /* ending position */
  121. {
  122. short i = 0;
  123. short j = 0;
  124. char *buffer = (char *)ib_util_malloc(256);
  125. if (*m > *n || *m < 1 || *n < 1) return "Bad parameters in substring";
  126. while (*s && i++ < *m-1) /* skip */
  127. s++;
  128. while (*s && i++ <= *n) /* copy */
  129. buffer[j++] = *s++;
  130. buffer[j] = '\0';
  131. return buffer;
  132. }
  133. /*===============================================================
  134. fn_trim(s) - Returns string that has leading blanks trimmed.
  135. ================================================================= */
  136. char* EXPORT fn_trim(char* s)
  137. {
  138. short j = 0;
  139. char *buffer = (char *)ib_util_malloc(256);
  140. while (*s == ' ') /* skip leading blanks */
  141. s++;
  142. while (*s) /* copy the rest */
  143. buffer[j++] = *s++;
  144. buffer[j] = '\0';
  145. return buffer;
  146. }
  147. /*===============================================================
  148. fn_trunc(s, m) - Returns the string truncated at position m;
  149. Input is of CSTRING, output is of VARCHAR.
  150. ================================================================= */
  151. char* EXPORT fn_trunc(char* s, short* m)
  152. {
  153. short j = 2; /* leave 1st 2 bytes for VARCHAR output */
  154. char *buffer = (char *)ib_util_malloc(256);
  155. while (*s && j < *m + 2) /* need to add 2 */
  156. buffer[j++] = *s++;
  157. buffer[j] = '\0';
  158. buffer[0] = (unsigned short) strlen(s) + 2;
  159. buffer[1] = ' '; /* anything other than \0 */
  160. /*
  161. *((unsigned short *)buffer) = (unsigned short) (strlen(buffer) + 2);
  162. */
  163. return buffer; /* VARCHAR output */
  164. }
  165. /* ==============================================================
  166. fn_doy() return the nth day of the year, by value.
  167. ============================================================== */
  168. int EXPORT fn_doy()
  169. {
  170. char buf[4]; /* for day */
  171. int i;
  172. time (&time_sec);
  173. tbuf = localtime(&time_sec);
  174. i = strftime(buf, 4, "%j", tbuf);
  175. return atoi (buf);
  176. }
  177. /* ==============================================================
  178. fn_moy() return the nth month of the year. e.g. 1,2,3,...12.
  179. Return by reference.
  180. ============================================================== */
  181. short* EXPORT fn_moy()
  182. {
  183. time (&time_sec);
  184. tbuf = localtime(&time_sec);
  185. r_short = (short) tbuf->tm_mon + 1;
  186. return &r_short;
  187. }
  188. /* ==============================================================
  189. fn_dow() return the day of today. e.g., Monday, Friday. ...
  190. ============================================================== */
  191. char* EXPORT fn_dow()
  192. {
  193. time (&time_sec);
  194. tbuf = localtime(&time_sec);
  195. switch (tbuf->tm_wday) {
  196. case 1: return "Monday";
  197. case 2: return "Tuesday";
  198. case 3: return "Wednesday";
  199. case 4: return "Thursday";
  200. case 5: return "Friday";
  201. case 6: return "Saturday";
  202. case 7: return "Sunday";
  203. default: return "Error in Date";
  204. }
  205. }
  206. /*===============================================================
  207. fn_sysdate() - Returns the system date in the "MMM-DD-YYYY" format.
  208. ================================================================= */
  209. char* EXPORT fn_sysdate()
  210. {
  211. short len, i, j = 0;
  212. char *time_str;
  213. char *datebuf = (char *)ib_util_malloc(12);
  214. time (&time_sec);
  215. time_str = ctime (&time_sec);
  216. len = strlen(time_str);
  217. for (i = 4; i <= 10; i++) {
  218. if (*(time_str + i) != ' ')
  219. datebuf[j++] = *(time_str+i);
  220. else if (i == 7 || i == 10)
  221. datebuf[j++] = '-';
  222. else
  223. datebuf[j++] = '0';
  224. }
  225. for (i = 20; i < len-1 ; i++)
  226. datebuf[j++] = *(time_str+i);
  227. datebuf[j] = '\0';
  228. return datebuf;
  229. }
  230. /* ==============================================
  231. fn_add2 (a, b) - returns a + b
  232. =============================================== */
  233. int EXPORT fn_add2(int* a, int* b)
  234. {
  235. return (*a + *b);
  236. }
  237. /* ==================================================
  238. fn_mul (a, b) - returns a * b
  239. =================================================== */
  240. double EXPORT fn_mul(double* a, double* b)
  241. {
  242. return (*a * *b);
  243. }
  244. /* ==============================================
  245. fn_fact (n) - return factorial of n
  246. ================================================ */
  247. double EXPORT fn_fact(double* n)
  248. {
  249. double k;
  250. if (*n > 100) return BADVAL;
  251. if (*n < 0) return BADVAL;
  252. if (*n == 0) return 1L;
  253. else {
  254. k = *n - 1L;
  255. return (*n * fn_fact(&k));
  256. }
  257. }
  258. /*===============================================================
  259. fn_abs() - returns the absolute value of its argument.
  260. ================================================================= */
  261. double EXPORT fn_abs(double* x)
  262. {
  263. return (*x < 0.0) ? -*x : *x;
  264. }
  265. /*===============================================================
  266. fn_max() - Returns the greater of its two arguments
  267. ================================================================ */
  268. double EXPORT fn_max(double* a, double* b)
  269. {
  270. return (*a > *b) ? *a : *b;
  271. }
  272. /*===============================================================
  273. fn_sqrt() - Returns square root of n
  274. ================================================================ */
  275. double* EXPORT fn_sqrt(double* n)
  276. {
  277. r_double = sqrt(*n);
  278. return &r_double;
  279. }
  280. /*=============================================================
  281. fn_blob_linecount() returns the number of lines in a blob
  282. =============================================================*/
  283. int EXPORT fn_blob_linecount(BLOB b)
  284. {
  285. char *buf, *p;
  286. short length, actual_length;
  287. /* Null values */
  288. if (!b->blob_handle)
  289. return 0L;
  290. length = b->blob_max_segment + 1L;
  291. buf = (char *) malloc (length);
  292. r_long = 0;
  293. while ((*b->blob_get_segment) (b->blob_handle, buf, length, &actual_length))
  294. {
  295. buf [actual_length] = 0;
  296. p = buf;
  297. while (*p)
  298. if (*p++ == '\n')
  299. r_long++;
  300. }
  301. free (buf);
  302. return r_long;
  303. }
  304. /*=============================================================
  305. fn_blob_bytecount() returns the number of bytes in a blob
  306. do not count newlines, so get rid of the newlines.
  307. ==============================================================*/
  308. int EXPORT fn_blob_bytecount(BLOB b)
  309. {
  310. /* Null values */
  311. if (!b->blob_handle)
  312. return 0L;
  313. return (b->blob_total_length - fn_blob_linecount(b));
  314. }
  315. /*=============================================================
  316. fn_substr_blob() returns portion of TEXT blob beginning at m th
  317. character and ended at n th character.
  318. Newlines are eliminated to make for better printing.
  319. =============================================================*/
  320. char* EXPORT fn_blob_substr(BLOB b, int* m, int* n)
  321. {
  322. char *buf, *p, *q;
  323. int i = 0;
  324. int curr_bytecount = 0;
  325. int begin, end;
  326. short length, actual_length;
  327. char *buffer = (char *)malloc(256);
  328. if (!b->blob_handle)
  329. return "<null>";
  330. length = b->blob_max_segment + 1L;
  331. buf = (char *) malloc (length);
  332. if (*m > *n || *m < 1L || *n < 1L)
  333. return "";
  334. if (b->blob_total_length < (int)*m)
  335. return "";
  336. begin = *m; /* beginning position */
  337. if (b->blob_total_length < (int)*n)
  338. end = b->blob_total_length; /* ending position */
  339. else
  340. end = *n;
  341. /* Limit the return string to 255 bytes */
  342. if (end - begin + 1L > 255L)
  343. end = begin + 254L;
  344. q = buffer;
  345. while ((*b->blob_get_segment) (b->blob_handle, buf, length,
  346. &actual_length))
  347. {
  348. buf [actual_length] = 0;
  349. p = buf;
  350. while (*p && (curr_bytecount <= end))
  351. {
  352. curr_bytecount++;
  353. if (*p == '\n')
  354. *p = ' ';
  355. if (curr_bytecount >= begin)
  356. *q++ = *p;
  357. p++;
  358. }
  359. if (curr_bytecount >= end)
  360. {
  361. *q = 0;
  362. break;
  363. }
  364. }
  365. free (buf);
  366. return buffer;
  367. }