* Convert a string value to an SQL string literal and append it to * the given buffer. We assume the specified client_encoding and * standard_conforming_strings settings. * * This is essentially equivalent to libpq's PQescapeStringInternal, * except for the output buffer structure. We need it in situations * where we do not have a PGconn available. Where we do, * appendStringLiteralConn
| 359 | * appendStringLiteralConn is a better choice. |
| 360 | */ |
| 361 | void |
| 362 | appendStringLiteral(PQExpBuffer buf, const char *str, |
| 363 | int encoding, bool std_strings) |
| 364 | { |
| 365 | size_t length = strlen(str); |
| 366 | const char *source = str; |
| 367 | char *target; |
| 368 | size_t remaining = length; |
| 369 | |
| 370 | if (!enlargePQExpBuffer(buf, 2 * length + 2)) |
| 371 | return; |
| 372 | |
| 373 | target = buf->data + buf->len; |
| 374 | *target++ = '\''; |
| 375 | |
| 376 | while (remaining > 0) |
| 377 | { |
| 378 | char c = *source; |
| 379 | int charlen; |
| 380 | int i; |
| 381 | |
| 382 | /* Fast path for plain ASCII */ |
| 383 | if (!IS_HIGHBIT_SET(c)) |
| 384 | { |
| 385 | /* Apply quoting if needed */ |
| 386 | if (SQL_STR_DOUBLE(c, !std_strings)) |
| 387 | *target++ = c; |
| 388 | /* Copy the character */ |
| 389 | *target++ = c; |
| 390 | source++; |
| 391 | remaining--; |
| 392 | continue; |
| 393 | } |
| 394 | |
| 395 | /* Slow path for possible multibyte characters */ |
| 396 | charlen = PQmblen(source, encoding); |
| 397 | |
| 398 | if (remaining < charlen) |
| 399 | { |
| 400 | /* |
| 401 | * If the character is longer than the available input, replace |
| 402 | * the string with an invalid sequence. The invalid sequence |
| 403 | * ensures that the escaped string will trigger an error on the |
| 404 | * server-side, even if we can't directly report an error here. |
| 405 | * |
| 406 | * We know there's enough space for the invalid sequence because |
| 407 | * the "target" buffer is 2 * length + 2 long, and at worst we're |
| 408 | * replacing a single input byte with two invalid bytes. |
| 409 | */ |
| 410 | pg_encoding_set_invalid(encoding, target); |
| 411 | target += 2; |
| 412 | |
| 413 | /* there's no more valid input data, so we can stop */ |
| 414 | break; |
| 415 | } |
| 416 | else if (pg_encoding_verifymbchar(encoding, source, charlen) == -1) |
| 417 | { |
| 418 | /* |