varlena.c
上传用户:blenddy
上传日期:2007-01-07
资源大小:6495k
文件大小:16k
源码类别:

数据库系统

开发平台:

Unix_Linux

  1. /*-------------------------------------------------------------------------
  2.  *
  3.  * varlena.c
  4.  *   Functions for the variable-length built-in types.
  5.  *
  6.  * Copyright (c) 1994, Regents of the University of California
  7.  *
  8.  *
  9.  * IDENTIFICATION
  10.  *   $Header: /usr/local/cvsroot/pgsql/src/backend/utils/adt/varlena.c,v 1.48.2.1 1999/08/02 05:24:58 scrappy Exp $
  11.  *
  12.  *-------------------------------------------------------------------------
  13.  */
  14. #include <ctype.h>
  15. #include "postgres.h"
  16. #include "mb/pg_wchar.h"
  17. #include "utils/builtins.h"
  18. static int text_cmp(text *arg1, text *arg2);
  19. /*****************************************************************************
  20.  *  USER I/O ROUTINES  *
  21.  *****************************************************************************/
  22. #define VAL(CH) ((CH) - '0')
  23. #define DIG(VAL) ((VAL) + '0')
  24. /*
  25.  * byteain - converts from printable representation of byte array
  26.  *
  27.  * Non-printable characters must be passed as 'nnn' (octal) and are
  28.  * converted to internal form.  '' must be passed as '\'.
  29.  * elog(ERROR, ...) if bad form.
  30.  *
  31.  * BUGS:
  32.  * The input is scaned twice.
  33.  * The error checking of input is minimal.
  34.  */
  35. text *
  36. byteain(char *inputText)
  37. {
  38. char    *tp;
  39. char    *rp;
  40. int byte;
  41. text    *result;
  42. if (inputText == NULL)
  43. elog(ERROR, "Bad input string for type bytea");
  44. for (byte = 0, tp = inputText; *tp != ''; byte++)
  45. if (*tp++ == '\')
  46. {
  47. if (*tp == '\')
  48. tp++;
  49. else if (!isdigit(*tp++) ||
  50.  !isdigit(*tp++) ||
  51.  !isdigit(*tp++))
  52. elog(ERROR, "Bad input string for type bytea");
  53. }
  54. tp = inputText;
  55. byte += VARHDRSZ;
  56. result = (text *) palloc(byte);
  57. result->vl_len = byte; /* varlena? */
  58. rp = result->vl_dat;
  59. while (*tp != '')
  60. if (*tp != '\' || *++tp == '\')
  61. *rp++ = *tp++;
  62. else
  63. {
  64. byte = VAL(*tp++);
  65. byte <<= 3;
  66. byte += VAL(*tp++);
  67. byte <<= 3;
  68. *rp++ = byte + VAL(*tp++);
  69. }
  70. return result;
  71. }
  72. /*
  73.  * byteaout - converts to printable representation of byte array
  74.  *
  75.  * Non-printable characters are inserted as 'nnn' (octal) and '' as
  76.  * '\'.
  77.  *
  78.  * NULL vlena should be an error--returning string with NULL for now.
  79.  */
  80. char *
  81. byteaout(text *vlena)
  82. {
  83. char    *result;
  84. char    *vp;
  85. char    *rp;
  86. int val; /* holds unprintable chars */
  87. int i;
  88. int len;
  89. if (vlena == NULL)
  90. {
  91. result = (char *) palloc(2);
  92. result[0] = '-';
  93. result[1] = '';
  94. return result;
  95. }
  96. vp = vlena->vl_dat;
  97. len = 1; /* empty string has 1 char */
  98. for (i = vlena->vl_len - VARHDRSZ; i != 0; i--, vp++)
  99. if (*vp == '\')
  100. len += 2;
  101. else if (isascii(*vp) && isprint(*vp))
  102. len++;
  103. else
  104. len += VARHDRSZ;
  105. rp = result = (char *) palloc(len);
  106. vp = vlena->vl_dat;
  107. for (i = vlena->vl_len - VARHDRSZ; i != 0; i--)
  108. if (*vp == '\')
  109. {
  110. vp++;
  111. *rp++ = '\';
  112. *rp++ = '\';
  113. }
  114. else if (isascii(*vp) && isprint(*vp))
  115. *rp++ = *vp++;
  116. else
  117. {
  118. val = *vp++;
  119. *rp = '\';
  120. rp += 3;
  121. *rp-- = DIG(val & 07);
  122. val >>= 3;
  123. *rp-- = DIG(val & 07);
  124. val >>= 3;
  125. *rp = DIG(val & 03);
  126. rp += 3;
  127. }
  128. *rp = '';
  129. return result;
  130. }
  131. /*
  132.  * textin - converts "..." to internal representation
  133.  */
  134. text *
  135. textin(char *inputText)
  136. {
  137. text    *result;
  138. int len;
  139. if (inputText == NULL)
  140. return NULL;
  141. len = strlen(inputText) + VARHDRSZ;
  142. result = (text *) palloc(len);
  143. VARSIZE(result) = len;
  144. memmove(VARDATA(result), inputText, len - VARHDRSZ);
  145. #ifdef CYR_RECODE
  146. convertstr(VARDATA(result), len - VARHDRSZ, 0);
  147. #endif
  148. return result;
  149. }
  150. /*
  151.  * textout - converts internal representation to "..."
  152.  */
  153. char *
  154. textout(text *vlena)
  155. {
  156. int len;
  157. char    *result;
  158. if (vlena == NULL)
  159. {
  160. result = (char *) palloc(2);
  161. result[0] = '-';
  162. result[1] = '';
  163. return result;
  164. }
  165. len = VARSIZE(vlena) - VARHDRSZ;
  166. result = (char *) palloc(len + 1);
  167. memmove(result, VARDATA(vlena), len);
  168. result[len] = '';
  169. #ifdef CYR_RECODE
  170. convertstr(result, len, 1);
  171. #endif
  172. return result;
  173. }
  174. /* ========== PUBLIC ROUTINES ========== */
  175. /*
  176.  * textlen -
  177.  *   returns the logical length of a text*
  178.  *    (which is less than the VARSIZE of the text*)
  179.  */
  180. int32
  181. textlen(text *t)
  182. {
  183. #ifdef MULTIBYTE
  184. unsigned char *s;
  185. int len,
  186. l,
  187. wl;
  188. #endif
  189. if (!PointerIsValid(t))
  190. elog(ERROR, "Null input to textlen");
  191. #ifdef MULTIBYTE
  192. len = 0;
  193. s = VARDATA(t);
  194. l = VARSIZE(t) - VARHDRSZ;
  195. while (l > 0)
  196. {
  197. wl = pg_mblen(s);
  198. l -= wl;
  199. s += wl;
  200. len++;
  201. }
  202. return (len);
  203. #else
  204. return VARSIZE(t) - VARHDRSZ;
  205. #endif
  206. } /* textlen() */
  207. /*
  208.  * textoctetlen -
  209.  *   returns the physical length of a text*
  210.  *    (which is less than the VARSIZE of the text*)
  211.  */
  212. int32
  213. textoctetlen(text *t)
  214. {
  215. if (!PointerIsValid(t))
  216. elog(ERROR, "Null input to textoctetlen");
  217. return VARSIZE(t) - VARHDRSZ;
  218. } /* textoctetlen() */
  219. /*
  220.  * textcat -
  221.  *   takes two text* and returns a text* that is the concatentation of
  222.  *   the two.
  223.  *
  224.  * Rewritten by Sapa, sapa@hq.icb.chel.su. 8-Jul-96.
  225.  * Updated by Thomas, Thomas.Lockhart@jpl.nasa.gov 1997-07-10.
  226.  * Allocate space for output in all cases.
  227.  * XXX - thomas 1997-07-10
  228.  */
  229. text *
  230. textcat(text *t1, text *t2)
  231. {
  232. int len1,
  233. len2,
  234. len;
  235. char    *ptr;
  236. text    *result;
  237. if (!PointerIsValid(t1) || !PointerIsValid(t2))
  238. return NULL;
  239. len1 = (VARSIZE(t1) - VARHDRSZ);
  240. if (len1 < 0)
  241. len1 = 0;
  242. while (len1 > 0 && VARDATA(t1)[len1 - 1] == '')
  243. len1--;
  244. len2 = (VARSIZE(t2) - VARHDRSZ);
  245. if (len2 < 0)
  246. len2 = 0;
  247. while (len2 > 0 && VARDATA(t2)[len2 - 1] == '')
  248. len2--;
  249. len = len1 + len2 + VARHDRSZ;
  250. result = palloc(len);
  251. /* Set size of result string... */
  252. VARSIZE(result) = len;
  253. /* Fill data field of result string... */
  254. ptr = VARDATA(result);
  255. if (len1 > 0)
  256. memcpy(ptr, VARDATA(t1), len1);
  257. if (len2 > 0)
  258. memcpy(ptr + len1, VARDATA(t2), len2);
  259. return result;
  260. } /* textcat() */
  261. /*
  262.  * text_substr()
  263.  * Return a substring starting at the specified position.
  264.  * - thomas 1997-12-31
  265.  *
  266.  * Input:
  267.  * - string
  268.  * - starting position (is one-based)
  269.  * - string length
  270.  *
  271.  * If the starting position is zero or less, then return from the start of the string
  272.  * adjusting the length to be consistant with the "negative start" per SQL92.
  273.  * If the length is less than zero, return the remaining string.
  274.  *
  275.  * Note that the arguments operate on octet length,
  276.  * so not aware of multi-byte character sets.
  277.  *
  278.  * Added multi-byte support.
  279.  * - Tatsuo Ishii 1998-4-21
  280.  * Changed behavior if starting position is less than one to conform to SQL92 behavior.
  281.  * Formerly returned the entire string; now returns a portion.
  282.  * - Thomas Lockhart 1998-12-10
  283.  */
  284. text *
  285. text_substr(text *string, int32 m, int32 n)
  286. {
  287. text    *ret;
  288. int len;
  289. #ifdef MULTIBYTE
  290. int i;
  291. char    *p;
  292. #endif
  293. if (string == (text *) NULL)
  294. return string;
  295. len = VARSIZE(string) - VARHDRSZ;
  296. #ifdef MULTIBYTE
  297. len = pg_mbstrlen_with_len(VARDATA(string), len);
  298. #endif
  299. /* starting position after the end of the string? */
  300. if (m > len)
  301. {
  302. m = 1;
  303. n = 0;
  304. }
  305. /*
  306.  * starting position before the start of the string? then offset into
  307.  * the string per SQL92 spec...
  308.  */
  309. else if (m < 1)
  310. {
  311. n += (m - 1);
  312. m = 1;
  313. }
  314. /* m will now become a zero-based starting position */
  315. m--;
  316. if (((m + n) > len) || (n < 0))
  317. n = (len - m);
  318. #ifdef MULTIBYTE
  319. p = VARDATA(string);
  320. for (i = 0; i < m; i++)
  321. p += pg_mblen(p);
  322. m = p - VARDATA(string);
  323. for (i = 0; i < n; i++)
  324. p += pg_mblen(p);
  325. n = p - (VARDATA(string) + m);
  326. #endif
  327. ret = (text *) palloc(VARHDRSZ + n);
  328. VARSIZE(ret) = VARHDRSZ + n;
  329. memcpy(VARDATA(ret), VARDATA(string) + m, n);
  330. return ret;
  331. } /* text_substr() */
  332. /*
  333.  * textpos -
  334.  *   Return the position of the specified substring.
  335.  *   Implements the SQL92 POSITION() function.
  336.  *   Ref: A Guide To The SQL Standard, Date & Darwen, 1997
  337.  * - thomas 1997-07-27
  338.  *
  339.  * Added multi-byte support.
  340.  * - Tatsuo Ishii 1998-4-21
  341.  */
  342. int32
  343. textpos(text *t1, text *t2)
  344. {
  345. int pos;
  346. int px,
  347. p;
  348. int len1,
  349. len2;
  350. pg_wchar   *p1,
  351.    *p2;
  352. #ifdef MULTIBYTE
  353. pg_wchar   *ps1,
  354.    *ps2;
  355. #endif
  356. if (!PointerIsValid(t1) || !PointerIsValid(t2))
  357. return 0;
  358. if (VARSIZE(t2) <= 0)
  359. return 1;
  360. len1 = (VARSIZE(t1) - VARHDRSZ);
  361. len2 = (VARSIZE(t2) - VARHDRSZ);
  362. #ifdef MULTIBYTE
  363. ps1 = p1 = (pg_wchar *) palloc((len1 + 1) * sizeof(pg_wchar));
  364. (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t1), p1, len1);
  365. len1 = pg_wchar_strlen(p1);
  366. ps2 = p2 = (pg_wchar *) palloc((len2 + 1) * sizeof(pg_wchar));
  367. (void) pg_mb2wchar_with_len((unsigned char *) VARDATA(t2), p2, len2);
  368. len2 = pg_wchar_strlen(p2);
  369. #else
  370. p1 = VARDATA(t1);
  371. p2 = VARDATA(t2);
  372. #endif
  373. pos = 0;
  374. px = (len1 - len2);
  375. for (p = 0; p <= px; p++)
  376. {
  377. #ifdef MULTIBYTE
  378. if ((*p2 == *p1) && (pg_wchar_strncmp(p1, p2, len2) == 0))
  379. #else
  380. if ((*p2 == *p1) && (strncmp(p1, p2, len2) == 0))
  381. #endif
  382. {
  383. pos = p + 1;
  384. break;
  385. };
  386. p1++;
  387. };
  388. #ifdef MULTIBYTE
  389. pfree(ps1);
  390. pfree(ps2);
  391. #endif
  392. return pos;
  393. } /* textpos() */
  394. /*
  395.  * texteq - returns 1 iff arguments are equal
  396.  * textne - returns 1 iff arguments are not equal
  397.  */
  398. bool
  399. texteq(text *arg1, text *arg2)
  400. {
  401. int len;
  402. char    *a1p,
  403.    *a2p;
  404. if (arg1 == NULL || arg2 == NULL)
  405. return (bool) NULL;
  406. if ((len = arg1->vl_len) != arg2->vl_len)
  407. return (bool) 0;
  408. a1p = arg1->vl_dat;
  409. a2p = arg2->vl_dat;
  410. /*
  411.  * Varlenas are stored as the total size (data + size variable)
  412.  * followed by the data. Use VARHDRSZ instead of explicit sizeof() -
  413.  * thomas 1997-07-10
  414.  */
  415. len -= VARHDRSZ;
  416. while (len-- != 0)
  417. if (*a1p++ != *a2p++)
  418. return (bool) 0;
  419. return (bool) 1;
  420. } /* texteq() */
  421. bool
  422. textne(text *arg1, text *arg2)
  423. {
  424. return (bool) !texteq(arg1, arg2);
  425. }
  426. /* varstr_cmp()
  427.  * Comparison function for text strings with given lengths.
  428.  * Includes locale support, but must copy strings to temporary memory
  429.  * to allow null-termination for inputs to strcoll().
  430.  * Returns -1, 0 or 1
  431.  */
  432. int
  433. varstr_cmp(char *arg1, int len1, char *arg2, int len2)
  434. {
  435. int result;
  436. char    *a1p,
  437.    *a2p;
  438. #ifdef USE_LOCALE
  439. a1p = (unsigned char *) palloc(len1 + 1);
  440. a2p = (unsigned char *) palloc(len2 + 1);
  441. memcpy(a1p, arg1, len1);
  442. *(a1p + len1) = '';
  443. memcpy(a2p, arg2, len2);
  444. *(a2p + len2) = '';
  445. result = strcoll(a1p, a2p);
  446. pfree(a1p);
  447. pfree(a2p);
  448. #else
  449. a1p = arg1;
  450. a2p = arg2;
  451. result = strncmp(a1p, a2p, Min(len1, len2));
  452. if ((result == 0) && (len1 != len2))
  453. result = (len1 < len2) ? -1 : 1;
  454. #endif
  455. return result;
  456. } /* varstr_cmp() */
  457. /* text_cmp()
  458.  * Comparison function for text strings.
  459.  * Includes locale support, but must copy strings to temporary memory
  460.  * to allow null-termination for inputs to strcoll().
  461.  * XXX HACK code for textlen() indicates that there can be embedded nulls
  462.  * but it appears that most routines (incl. this one) assume not! - tgl 97/04/07
  463.  * Returns -1, 0 or 1
  464.  */
  465. static int
  466. text_cmp(text *arg1, text *arg2)
  467. {
  468. char    *a1p,
  469.    *a2p;
  470. int len1,
  471. len2;
  472. if (arg1 == NULL || arg2 == NULL)
  473. return (bool) FALSE;
  474. a1p = VARDATA(arg1);
  475. a2p = VARDATA(arg2);
  476. len1 = VARSIZE(arg1) - VARHDRSZ;
  477. len2 = VARSIZE(arg2) - VARHDRSZ;
  478. return varstr_cmp(a1p, len1, a2p, len2);
  479. } /* text_cmp() */
  480. /* text_lt()
  481.  * Comparison function for text strings.
  482.  */
  483. bool
  484. text_lt(text *arg1, text *arg2)
  485. {
  486. return (bool) (text_cmp(arg1, arg2) < 0);
  487. } /* text_lt() */
  488. /* text_le()
  489.  * Comparison function for text strings.
  490.  */
  491. bool
  492. text_le(text *arg1, text *arg2)
  493. {
  494. return (bool) (text_cmp(arg1, arg2) <= 0);
  495. } /* text_le() */
  496. bool
  497. text_gt(text *arg1, text *arg2)
  498. {
  499. return (bool) !text_le(arg1, arg2);
  500. }
  501. bool
  502. text_ge(text *arg1, text *arg2)
  503. {
  504. return (bool) !text_lt(arg1, arg2);
  505. }
  506. text *
  507. text_larger(text *arg1, text *arg2)
  508. {
  509. text    *result;
  510. text    *temp;
  511. temp = ((text_cmp(arg1, arg2) <= 0) ? arg2 : arg1);
  512. /* Make a copy */
  513. result = (text *) palloc(VARSIZE(temp));
  514. memmove((char *) result, (char *) temp, VARSIZE(temp));
  515. return (result);
  516. }
  517. text *
  518. text_smaller(text *arg1, text *arg2)
  519. {
  520. text    *result;
  521. text    *temp;
  522. temp = ((text_cmp(arg1, arg2) > 0) ? arg2 : arg1);
  523. /* Make a copy */
  524. result = (text *) palloc(VARSIZE(temp));
  525. memmove((char *) result, (char *) temp, VARSIZE(temp));
  526. return (result);
  527. }
  528. /*-------------------------------------------------------------
  529.  * byteaGetSize
  530.  *
  531.  * get the number of bytes contained in an instance of type 'bytea'
  532.  *-------------------------------------------------------------
  533.  */
  534. int32
  535. byteaGetSize(text *v)
  536. {
  537. int len;
  538. len = v->vl_len - sizeof(v->vl_len);
  539. return len;
  540. }
  541. /*-------------------------------------------------------------
  542.  * byteaGetByte
  543.  *
  544.  * this routine treats "bytea" as an array of bytes.
  545.  * It returns the Nth byte (a number between 0 and 255) or
  546.  * it dies if the length of this array is less than n.
  547.  *-------------------------------------------------------------
  548.  */
  549. int32
  550. byteaGetByte(text *v, int32 n)
  551. {
  552. int len;
  553. int byte;
  554. len = byteaGetSize(v);
  555. if (n >= len)
  556. {
  557. elog(ERROR, "byteaGetByte: index (=%d) out of range [0..%d]",
  558.  n, len - 1);
  559. }
  560. #ifdef USE_LOCALE
  561. byte = (unsigned char) (v->vl_dat[n]);
  562. #else
  563. byte = v->vl_dat[n];
  564. #endif
  565. return (int32) byte;
  566. }
  567. /*-------------------------------------------------------------
  568.  * byteaGetBit
  569.  *
  570.  * This routine treats a "bytea" type like an array of bits.
  571.  * It returns the value of the Nth bit (0 or 1).
  572.  * If 'n' is out of range, it dies!
  573.  *
  574.  *-------------------------------------------------------------
  575.  */
  576. int32
  577. byteaGetBit(text *v, int32 n)
  578. {
  579. int byteNo,
  580. bitNo;
  581. int byte;
  582. byteNo = n / 8;
  583. bitNo = n % 8;
  584. byte = byteaGetByte(v, byteNo);
  585. if (byte & (1 << bitNo))
  586. return (int32) 1;
  587. else
  588. return (int32) 0;
  589. }
  590. /*-------------------------------------------------------------
  591.  * byteaSetByte
  592.  *
  593.  * Given an instance of type 'bytea' creates a new one with
  594.  * the Nth byte set to the given value.
  595.  *
  596.  *-------------------------------------------------------------
  597.  */
  598. text *
  599. byteaSetByte(text *v, int32 n, int32 newByte)
  600. {
  601. int len;
  602. text    *res;
  603. len = byteaGetSize(v);
  604. if (n >= len)
  605. {
  606. elog(ERROR,
  607.  "byteaSetByte: index (=%d) out of range [0..%d]",
  608.  n, len - 1);
  609. }
  610. /*
  611.  * Make a copy of the original varlena.
  612.  */
  613. res = (text *) palloc(VARSIZE(v));
  614. if (res == NULL)
  615. {
  616. elog(ERROR, "byteaSetByte: Out of memory (%d bytes requested)",
  617.  VARSIZE(v));
  618. }
  619. memmove((char *) res, (char *) v, VARSIZE(v));
  620. /*
  621.  * Now set the byte.
  622.  */
  623. res->vl_dat[n] = newByte;
  624. return res;
  625. }
  626. /*-------------------------------------------------------------
  627.  * byteaSetBit
  628.  *
  629.  * Given an instance of type 'bytea' creates a new one with
  630.  * the Nth bit set to the given value.
  631.  *
  632.  *-------------------------------------------------------------
  633.  */
  634. text *
  635. byteaSetBit(text *v, int32 n, int32 newBit)
  636. {
  637. text    *res;
  638. int oldByte,
  639. newByte;
  640. int byteNo,
  641. bitNo;
  642. /*
  643.  * sanity check!
  644.  */
  645. if (newBit != 0 && newBit != 1)
  646. elog(ERROR, "byteaSetByte: new bit must be 0 or 1");
  647. /*
  648.  * get the byte where the bit we want is stored.
  649.  */
  650. byteNo = n / 8;
  651. bitNo = n % 8;
  652. oldByte = byteaGetByte(v, byteNo);
  653. /*
  654.  * calculate the new value for that byte
  655.  */
  656. if (newBit == 0)
  657. newByte = oldByte & (~(1 << bitNo));
  658. else
  659. newByte = oldByte | (1 << bitNo);
  660. /*
  661.  * NOTE: 'byteaSetByte' creates a copy of 'v' & sets the byte.
  662.  */
  663. res = byteaSetByte(v, byteNo, newByte);
  664. return res;
  665. }
  666. /* text_name()
  667.  * Converts a text() type to a NameData type.
  668.  */
  669. NameData   *
  670. text_name(text *s)
  671. {
  672. NameData   *result;
  673. int len;
  674. if (s == NULL)
  675. return NULL;
  676. len = VARSIZE(s) - VARHDRSZ;
  677. if (len > NAMEDATALEN)
  678. len = NAMEDATALEN;
  679. #ifdef STRINGDEBUG
  680. printf("text- convert string length %d (%d) ->%dn",
  681.    VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
  682. #endif
  683. result = palloc(NAMEDATALEN);
  684. StrNCpy(result->data, VARDATA(s), NAMEDATALEN);
  685. /* now null pad to full length... */
  686. while (len < NAMEDATALEN)
  687. {
  688. *(result->data + len) = '';
  689. len++;
  690. }
  691. return result;
  692. } /* text_name() */
  693. /* name_text()
  694.  * Converts a NameData type to a text type.
  695.  */
  696. text *
  697. name_text(NameData *s)
  698. {
  699. text    *result;
  700. int len;
  701. if (s == NULL)
  702. return NULL;
  703. len = strlen(s->data);
  704. #ifdef STRINGDEBUG
  705. printf("text- convert string length %d (%d) ->%dn",
  706.    VARSIZE(s) - VARHDRSZ, VARSIZE(s), len);
  707. #endif
  708. result = palloc(VARHDRSZ + len);
  709. strncpy(VARDATA(result), s->data, len);
  710. VARSIZE(result) = len + VARHDRSZ;
  711. return result;
  712. } /* name_text() */