PostgreSQL Source Code: src/fe_utils/string_utils.c Source File (original) (raw)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

17

18#include <ctype.h>

19

23

25

26

29

30static int fmtIdEncoding = -1;

31

32

33

34

35

36

37

38

39

40

43{

45

46 if (id_return)

47 {

48

50 }

51 else

52 {

53

55 }

56

57 return id_return;

58}

59

60

61

62

63

64

65

66

67

68void

70{

72}

73

74

75

76

77static int

79{

80 if (fmtIdEncoding != -1)

81 return fmtIdEncoding;

82

83

84

85

86

87

88

89 Assert(fmtIdEncoding != -1);

90

92}

93

94

95

96

97

98

99

100const char *

102{

104

105 const char *cp;

106 bool need_quotes = false;

107 size_t remaining = strlen(rawid);

108

109

110

111

112

114 need_quotes = true;

115

116 else if (!((rawid[0] >= 'a' && rawid[0] <= 'z') || rawid[0] == '_'))

117 need_quotes = true;

118 else

119 {

120

121 cp = rawid;

123 {

124 if (!((*cp >= 'a' && *cp <= 'z')

125 || (*cp >= '0' && *cp <= '9')

126 || (*cp == '_')))

127 {

128 need_quotes = true;

129 break;

130 }

131 }

132 }

133

134 if (!need_quotes)

135 {

136

137

138

139

140

141

142

143

145

147 need_quotes = true;

148 }

149

150 if (!need_quotes)

151 {

152

154 }

155 else

156 {

158

159 cp = &rawid[0];

161 {

162 int charlen;

163

164

166 {

167

168

169

170

171

172 if (*cp == '"')

176 cp++;

177 continue;

178 }

179

180

182

185 {

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

204 {

206 id_return->data + id_return->len);

207 id_return->len += 2;

208 id_return->data[id_return->len] = '\0';

209 }

210

211

212

213

214

215

216

218 cp++;

219 }

220 else

221 {

222 for (int i = 0; i < charlen; i++)

223 {

226 cp++;

227 }

228 }

229 }

230

232 }

233

234 return id_return->data;

235}

236

237

238

239

240

241

242

243

244

245

246

247const char *

249{

251}

252

253

254

255

256

257

258

259

260

261

262const char *

264{

267

268

269 if (schema && *schema)

270 {

272 }

274

276

279

280 return id_return->data;

281}

282

283

284

285

286

287

288

289

290

291

292

293

294

295const char *

297{

299}

300

301

302

303

304

305

306

307

308

309

310

311

312char *

314 char *buf, size_t buflen)

315{

316 if (version_number >= 100000)

317 {

318

319 if (include_minor)

320 snprintf(buf, buflen, "%d.%d", version_number / 10000,

321 version_number % 10000);

322 else

323 snprintf(buf, buflen, "%d", version_number / 10000);

324 }

325 else

326 {

327

328 if (include_minor)

329 snprintf(buf, buflen, "%d.%d.%d", version_number / 10000,

330 (version_number / 100) % 100,

331 version_number % 100);

332 else

333 snprintf(buf, buflen, "%d.%d", version_number / 10000,

334 (version_number / 100) % 100);

335 }

336 return buf;

337}

338

339

340

341

342

343

344

345

346

347

348

349

350void

352 int encoding, bool std_strings)

353{

354 size_t length = strlen(str);

356 char *target;

358

360 return;

361

362 target = buf->data + buf->len;

363 *target++ = '\'';

364

366 {

368 int charlen;

369 int i;

370

371

373 {

374

376 *target++ = c;

377

378 *target++ = c;

381 continue;

382 }

383

384

386

389 {

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

411 target += 2;

412

413

414

415

416

417

420 }

421 else

422 {

423

424 for (i = 0; i < charlen; i++)

425 {

426 *target++ = *source++;

428 }

429 }

430 }

431

432

433 *target++ = '\'';

434 *target = '\0';

435

436 buf->len = target - buf->data;

437}

438

439

440

441

442

443

444

445void

447{

448 size_t length = strlen(str);

449

450

451

452

453

455 {

456

457 if (buf->len > 0 && buf->data[buf->len - 1] != ' ')

461 return;

462 }

463

464

466 return;

469 str, length, NULL);

471}

472

473

474

475

476

477

478

479

480

481

482

483void

485{

486 static const char suffixes[] = "_XXXXXXX";

487 int nextchar = 0;

489

490

492 if (dqprefix)

494

495

496

497

498

499

500 while (strstr(str, delimBuf->data) != NULL)

501 {

503 nextchar %= sizeof(suffixes) - 1;

504 }

505

506

508

509

513

515}

516

517

518

519

520

521

522

523

524

525

526void

528 bool std_strings)

529{

530 const unsigned char *source = str;

531 char *target;

532

533 static const char hextbl[] = "0123456789abcdef";

534

535

536

537

538

539

540

542 return;

543

544 target = buf->data + buf->len;

545 *target++ = '\'';

546 if (!std_strings)

547 *target++ = '\\';

548 *target++ = '\\';

549 *target++ = 'x';

550

551 while (length-- > 0)

552 {

553 unsigned char c = *source++;

554

555 *target++ = hextbl[(c >> 4) & 0xF];

556 *target++ = hextbl[c & 0xF];

557 }

558

559

560 *target++ = '\'';

561 *target = '\0';

562

563 buf->len = target - buf->data;

564}

565

566

567

568

569

570

571

572

573

574

575

576

577

578

579

580

581void

583{

585 {

587 _("shell command argument contains a newline or carriage return: \"%s\"\n"),

590 }

591}

592

593bool

595{

596#ifdef WIN32

597 int backslash_run_length = 0;

598#endif

599 bool ok = true;

600 const char *p;

601

602

603

604

605

606 if (*str != '\0' &&

607 strspn(str, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_./:") == strlen(str))

608 {

610 return ok;

611 }

612

613#ifndef WIN32

615 for (p = str; *p; p++)

616 {

617 if (*p == '\n' || *p == '\r')

618 {

619 ok = false;

620 continue;

621 }

622

623 if (*p == '\'')

625 else

627 }

629#else

630

631

632

633

634

635

636

637

638

639

640

641

643 for (p = str; *p; p++)

644 {

645 if (*p == '\n' || *p == '\r')

646 {

647 ok = false;

648 continue;

649 }

650

651

652 if (*p == '"')

653 {

654 while (backslash_run_length)

655 {

657 backslash_run_length--;

658 }

660 }

661 else if (*p == '\\')

662 backslash_run_length++;

663 else

664 backslash_run_length = 0;

665

666

667

668

669

670 if (!((*p >= 'a' && *p <= 'z') ||

671 (*p >= 'A' && *p <= 'Z') ||

672 (*p >= '0' && *p <= '9')))

675 }

676

677

678

679

680

681 while (backslash_run_length)

682 {

684 backslash_run_length--;

685 }

687#endif

688

689 return ok;

690}

691

692

693

694

695

696

697void

699{

700 const char *s;

701 bool needquotes;

702

703

704

705

706

707 needquotes = true;

708 for (s = str; *s; s++)

709 {

710 if (!((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z') ||

711 (*s >= '0' && *s <= '9') || *s == '_' || *s == '.'))

712 {

713 needquotes = true;

714 break;

715 }

716 needquotes = false;

717 }

718

719 if (needquotes)

720 {

722 while (*str)

723 {

724

725 if (*str == '\'' || *str == '\\')

727

730 }

732 }

733 else

735}

736

737

738

739

740

741

742void

744{

745 const char *s;

746 bool complex;

747

748

749

750

751

752

753 complex = false;

754

755 for (s = dbname; *s; s++)

756 {

757 if (*s == '\n' || *s == '\r')

758 {

760 _("database name contains a newline or carriage return: \"%s\"\n"),

763 }

764

765 if (!((*s >= 'a' && *s <= 'z') || (*s >= 'A' && *s <= 'Z') ||

766 (*s >= '0' && *s <= '9') || *s == '_' || *s == '.'))

767 {

768 complex = true;

769 }

770 }

771

772 if (complex)

773 {

775

777

778

779

780

781

782

785

788

789

790

791

792

793

794

796

798 }

799 else

800 {

803 }

805}

806

807

808

809

810

811

812

813

814

815

816

817

818bool

820{

821 int inputlen;

823 char *strings;

824 int curitem;

825

826

827

828

829

830

831

832

833

834

835

836 *itemarray = NULL;

838 inputlen = strlen(atext);

839 if (inputlen < 2 || atext[0] != '{' || atext[inputlen - 1] != '}')

840 return false;

841 items = (char **) malloc(inputlen * (sizeof(char *) + sizeof(char)));

842 if (items == NULL)

843 return false;

844 *itemarray = items;

845 strings = (char *) (items + inputlen);

846

847 atext++;

848 curitem = 0;

849 while (*atext != '}')

850 {

851 if (*atext == '\0')

852 return false;

853 items[curitem] = strings;

854 while (*atext != '}' && *atext != ',')

855 {

856 if (*atext == '\0')

857 return false;

858 if (*atext != '"')

859 *strings++ = *atext++;

860 else

861 {

862

863 atext++;

864 while (*atext != '"')

865 {

866 if (*atext == '\0')

867 return false;

868 if (*atext == '\\')

869 {

870 atext++;

871 if (*atext == '\0')

872 return false;

873 }

874 *strings++ = *atext++;

875 }

876 atext++;

877 }

878 }

879 *strings++ = '\0';

880 if (*atext == ',')

881 atext++;

882 curitem++;

883 }

884 if (atext[1] != '\0')

885 return false;

887 return true;

888}

889

890

891

892

893

894

895

896

897

898

899

900

901void

903{

904 bool needquote;

905 const char *tmp;

906

907 if (buffer->data[buffer->len - 1] != '{')

909

910

911 if (value[0] == '\0')

912 needquote = true;

914 needquote = true;

915 else

916 needquote = false;

917

918 if (!needquote)

919 {

920 for (tmp = value; *tmp; tmp++)

921 {

922 char ch = *tmp;

923

924 if (ch == '"' || ch == '\\' ||

925 ch == '{' || ch == '}' || ch == ',' ||

926

927 ch == ' ' || ch == '\t' || ch == '\n' ||

928 ch == '\r' || ch == '\v' || ch == '\f')

929 {

930 needquote = true;

931 break;

932 }

933 }

934 }

935

936 if (needquote)

937 {

939 for (tmp = value; *tmp; tmp++)

940 {

941 char ch = *tmp;

942

943 if (ch == '"' || ch == '\\')

946 }

948 }

949 else

951}

952

953

954

955

956

957

958

959

960

961

962

963

964

965bool

967 const char *prefix, int encoding, bool std_strings)

968{

971 int i;

972

974 {

976 return false;

977 }

978

980 {

985

986

987

988

989

993 {

996 }

997 else

999

1000 if (i > 0)

1003

1004

1005

1006

1007

1008

1009

1010

1011

1014 else

1016 }

1017

1019

1020 return true;

1021}

1022

1023

1024

1025

1026

1027

1028

1029

1030

1031

1032

1033

1034

1035

1036

1037

1038

1039

1040

1041

1042

1043

1044

1045

1046

1047

1048

1049

1050

1051

1052bool

1054 bool have_where, bool force_escape,

1055 const char *schemavar, const char *namevar,

1056 const char *altnamevar, const char *visibilityrule,

1058{

1061 bool added_clause = false;

1062 int dcnt;

1063

1064#define WHEREAND() \

1065 (appendPQExpBufferStr(buf, have_where ? " AND " : "WHERE "), \

1066 have_where = true, added_clause = true)

1067

1068 if (dotcnt == NULL)

1069 dotcnt = &dcnt;

1070 *dotcnt = 0;

1071 if (pattern == NULL)

1072 {

1073

1074 if (visibilityrule)

1075 {

1078 }

1079 return added_clause;

1080 }

1081

1084

1085

1086

1087

1088

1089

1090

1091

1092

1094 (schemavar ? dbnamebuf : NULL),

1095 (schemavar ? &schemabuf : NULL),

1096 &namebuf,

1097 pattern, force_escape, true, dotcnt);

1098

1099

1100

1101

1102

1103

1104

1105

1106

1107

1108

1109

1110 if (namevar && namebuf.len > 2)

1111 {

1112

1113

1114

1115 if (strcmp(namebuf.data, "^(.*)$") != 0)

1116 {

1118 if (altnamevar)

1119 {

1121 "(%s OPERATOR(pg_catalog.~) ", namevar);

1126 "\n OR %s OPERATOR(pg_catalog.~) ",

1127 altnamevar);

1132 }

1133 else

1134 {

1140 }

1141 }

1142 }

1143

1144 if (schemavar && schemabuf.len > 2)

1145 {

1146

1147

1148

1149 if (strcmp(schemabuf.data, "^(.*)$") != 0 && schemavar)

1150 {

1157 }

1158 }

1159 else

1160 {

1161

1162 if (visibilityrule)

1163 {

1166 }

1167 }

1168

1171

1172 return added_clause;

1173#undef WHEREAND

1174}

1175

1176

1177

1178

1179

1180

1181

1182

1183

1184

1185

1186

1187

1188

1189

1190

1191

1192

1193

1194

1195

1196

1197

1198

1199

1200

1201

1202

1203

1204

1205

1206

1207

1208

1209

1210

1211

1212

1213

1214

1215

1216

1217

1218

1219

1220

1221

1222

1223

1224void

1226 PQExpBuffer namebuf, const char *pattern, bool force_escape,

1227 bool want_literal_dbname, int *dotcnt)

1228{

1233 int i;

1234 bool inquotes;

1235 bool left;

1236 const char *cp;

1237

1238 Assert(pattern != NULL);

1239 Assert(namebuf != NULL);

1240

1241

1242 Assert(dbnamebuf == NULL || schemabuf != NULL);

1243 Assert(dotcnt != NULL);

1244

1245 *dotcnt = 0;

1246 inquotes = false;

1247 cp = pattern;

1248

1249 if (dbnamebuf != NULL)

1250 maxbuf = &buf[2];

1251 else if (schemabuf != NULL)

1252 maxbuf = &buf[1];

1253 else

1254 maxbuf = &buf[0];

1255

1256 curbuf = &buf[0];

1257 if (want_literal_dbname)

1258 {

1259 left = true;

1261 }

1262 else

1263 left = false;

1266 while (*cp)

1267 {

1268 char ch = *cp;

1269

1270 if (ch == '"')

1271 {

1272 if (inquotes && cp[1] == '"')

1273 {

1274

1276 if (left)

1278 cp++;

1279 }

1280 else

1281 inquotes = !inquotes;

1282 cp++;

1283 }

1284 else if (!inquotes && isupper((unsigned char) ch))

1285 {

1288 if (left)

1291 cp++;

1292 }

1293 else if (!inquotes && ch == '*')

1294 {

1296 if (left)

1298 cp++;

1299 }

1300 else if (!inquotes && ch == '?')

1301 {

1303 if (left)

1305 cp++;

1306 }

1307 else if (!inquotes && ch == '.')

1308 {

1309 left = false;

1310 if (dotcnt)

1311 (*dotcnt)++;

1312 if (curbuf < maxbuf)

1313 {

1315 curbuf++;

1318 cp++;

1319 }

1320 else

1322 }

1323 else if (ch == '$')

1324 {

1325

1326

1327

1328

1329

1330

1331

1333 if (left)

1335 cp++;

1336 }

1337 else

1338 {

1339

1340

1341

1342

1343

1344

1345

1346

1347

1348

1349

1350

1351

1352 if ((inquotes || force_escape) &&

1353 strchr("|*+?()[]{}.^$\\", ch))

1355 else if (ch == '[' && cp[1] == ']')

1358 while (i--)

1359 {

1360 if (left)

1363 }

1364 }

1365 }

1367

1368 if (namebuf)

1369 {

1372 curbuf--;

1373 }

1374

1375 if (schemabuf && curbuf >= buf)

1376 {

1379 curbuf--;

1380 }

1381

1382 if (dbnamebuf && curbuf >= buf)

1383 {

1384 if (want_literal_dbname)

1386 else

1389 }

1390

1391 if (want_literal_dbname)

1393}

#define IS_HIGHBIT_SET(ch)

#define ESCAPE_STRING_SYNTAX

#define SQL_STR_DOUBLE(ch, escape_backslash)

const uint8 ScanKeywordCategories[SCANKEYWORDS_NUM_KEYWORDS]

#define fprintf(file, fmt, msg)

int PQserverVersion(const PGconn *conn)

int PQclientEncoding(const PGconn *conn)

size_t PQescapeStringConn(PGconn *conn, char *to, const char *from, size_t length, int *error)

int PQmblen(const char *s, int encoding)

int PQmblenBounded(const char *s, int encoding)

Assert(PointerIsAligned(start, uint64))

PGDLLIMPORT const ScanKeywordList ScanKeywords

#define UNRESERVED_KEYWORD

int ScanKeywordLookup(const char *str, const ScanKeywordList *keywords)

static const char * connstr

static rewind_source * source

static const char hextbl[]

int pg_strcasecmp(const char *s1, const char *s2)

unsigned char pg_tolower(unsigned char ch)

PQExpBuffer createPQExpBuffer(void)

void initPQExpBuffer(PQExpBuffer str)

int enlargePQExpBuffer(PQExpBuffer str, size_t needed)

void resetPQExpBuffer(PQExpBuffer str)

void appendPQExpBuffer(PQExpBuffer str, const char *fmt,...)

void destroyPQExpBuffer(PQExpBuffer str)

void appendPQExpBufferChar(PQExpBuffer str, char ch)

void appendPQExpBufferStr(PQExpBuffer str, const char *data)

void termPQExpBuffer(PQExpBuffer str)

PQExpBufferData * PQExpBuffer

const char * fmtQualifiedId(const char *schema, const char *id)

bool appendShellStringNoError(PQExpBuffer buf, const char *str)

const char * fmtIdEnc(const char *rawid, int encoding)

const char * fmtId(const char *rawid)

const char * fmtQualifiedIdEnc(const char *schema, const char *id, int encoding)

void setFmtEncoding(int encoding)

void appendShellString(PQExpBuffer buf, const char *str)

void appendStringLiteralConn(PQExpBuffer buf, const char *str, PGconn *conn)

void appendPGArray(PQExpBuffer buffer, const char *value)

bool processSQLNamePattern(PGconn *conn, PQExpBuffer buf, const char *pattern, bool have_where, bool force_escape, const char *schemavar, const char *namevar, const char *altnamevar, const char *visibilityrule, PQExpBuffer dbnamebuf, int *dotcnt)

void appendPsqlMetaConnect(PQExpBuffer buf, const char *dbname)

void appendByteaLiteral(PQExpBuffer buf, const unsigned char *str, size_t length, bool std_strings)

bool parsePGArray(const char *atext, char ***itemarray, int *nitems)

void appendStringLiteral(PQExpBuffer buf, const char *str, int encoding, bool std_strings)

void patternToSQLRegex(int encoding, PQExpBuffer dbnamebuf, PQExpBuffer schemabuf, PQExpBuffer namebuf, const char *pattern, bool force_escape, bool want_literal_dbname, int *dotcnt)

bool appendReloptionsArray(PQExpBuffer buffer, const char *reloptions, const char *prefix, int encoding, bool std_strings)

static PQExpBuffer defaultGetLocalPQExpBuffer(void)

static int getFmtEncoding(void)

PQExpBuffer(* getLocalPQExpBuffer)(void)

void appendStringLiteralDQ(PQExpBuffer buf, const char *str, const char *dqprefix)

void appendConnStrVal(PQExpBuffer buf, const char *str)

int quote_all_identifiers

char * formatPGVersionNumber(int version_number, bool include_minor, char *buf, size_t buflen)

void pg_encoding_set_invalid(int encoding, char *dst)

int pg_encoding_mblen(int encoding, const char *mbstr)

int pg_encoding_verifymbchar(int encoding, const char *mbstr, int len)