@effect/sql-pg 4.0.0-rc.112 → 4.0.0-rc.114
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +24 -9
- package/CLAUDE.md +24 -9
- package/ai-docs/package.json +2 -2
- package/ai-docs/src/01_effect/01_basics/02_effect-fn.ts +18 -5
- package/ai-docs/src/01_effect/01_basics/index.md +5 -3
- package/ai-docs/src/01_effect/03_services/20_layer-composition.ts +1 -1
- package/ai-docs/src/01_effect/03_services/20_layer-unwrap.ts +2 -2
- package/ai-docs/src/01_effect/05_resources/10_acquire-release.ts +2 -2
- package/ai-docs/src/03_stream/30_encoding.ts +5 -7
- package/ai-docs/src/08_observability/10_logging.ts +1 -1
- package/ai-docs/src/70_cli/10_basics.ts +7 -7
- package/ai-docs/src/71_ai/10_language-model.ts +2 -2
- package/ai-docs/src/71_ai/20_tools.ts +1 -1
- package/ai-docs/src/71_ai/30_chat.ts +1 -1
- package/dist/PgAuth.d.ts +24 -0
- package/dist/PgAuth.d.ts.map +1 -1
- package/dist/PgAuth.js +29 -2
- package/dist/PgAuth.js.map +1 -1
- package/dist/PgClient.d.ts +49 -82
- package/dist/PgClient.d.ts.map +1 -1
- package/dist/PgClient.js +58 -510
- package/dist/PgClient.js.map +1 -1
- package/dist/PgConnection.d.ts +177 -0
- package/dist/PgConnection.d.ts.map +1 -0
- package/dist/PgConnection.js +1788 -0
- package/dist/PgConnection.js.map +1 -0
- package/dist/PgPool.d.ts +107 -0
- package/dist/PgPool.d.ts.map +1 -0
- package/dist/PgPool.js +124 -0
- package/dist/PgPool.js.map +1 -0
- package/dist/PgProtocol.d.ts +63 -30
- package/dist/PgProtocol.d.ts.map +1 -1
- package/dist/PgProtocol.js +64 -22
- package/dist/PgProtocol.js.map +1 -1
- package/dist/PgTypes.d.ts +85 -17
- package/dist/PgTypes.d.ts.map +1 -1
- package/dist/PgTypes.js +166 -169
- package/dist/PgTypes.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/connection.d.ts +2 -0
- package/dist/internal/connection.d.ts.map +1 -0
- package/dist/internal/connection.js +5 -0
- package/dist/internal/connection.js.map +1 -0
- package/dist/internal/sqlError.d.ts +10 -0
- package/dist/internal/sqlError.d.ts.map +1 -0
- package/dist/internal/sqlError.js +57 -0
- package/dist/internal/sqlError.js.map +1 -0
- package/package.json +6 -14
- package/src/PgAuth.ts +33 -2
- package/src/PgClient.ts +138 -681
- package/src/PgConnection.ts +2296 -0
- package/src/PgPool.ts +231 -0
- package/src/PgProtocol.ts +93 -50
- package/src/PgTypes.ts +254 -186
- package/src/index.ts +10 -0
- package/src/internal/connection.ts +26 -0
- package/src/internal/sqlError.ts +75 -0
package/dist/PgTypes.js
CHANGED
|
@@ -18,6 +18,9 @@
|
|
|
18
18
|
*/
|
|
19
19
|
import * as Data from "effect/Data";
|
|
20
20
|
import * as Result from "effect/Result";
|
|
21
|
+
import * as IpInterface from "effect/unstable/net/IpInterface";
|
|
22
|
+
import * as IpNetwork from "effect/unstable/net/IpNetwork";
|
|
23
|
+
import * as NetAddress from "effect/unstable/net/NetAddress";
|
|
21
24
|
/**
|
|
22
25
|
* Failure returned when a value cannot be encoded or decoded for its OID.
|
|
23
26
|
*
|
|
@@ -293,7 +296,7 @@ const elementToArray = /*#__PURE__*/new Map(/*#__PURE__*/Array.from(arrayToEleme
|
|
|
293
296
|
* @category getters
|
|
294
297
|
* @since 4.0.0
|
|
295
298
|
*/
|
|
296
|
-
export const arrayOidFor = elementOid => elementToArray.get(elementOid);
|
|
299
|
+
export const arrayOidFor = (elementOid, registry) => registry === undefined ? elementToArray.get(elementOid) : getRegistryState(registry).elementToArray.get(elementOid);
|
|
297
300
|
// -----------------------------------------------------------------------------
|
|
298
301
|
// calendar helpers
|
|
299
302
|
// -----------------------------------------------------------------------------
|
|
@@ -533,112 +536,26 @@ const decodeNumeric = (bytes, offset, size) => {
|
|
|
533
536
|
// -----------------------------------------------------------------------------
|
|
534
537
|
const PGSQL_AF_INET = 2;
|
|
535
538
|
const PGSQL_AF_INET6 = 3;
|
|
536
|
-
const parseIPv4 = text => {
|
|
537
|
-
const parts = text.split(".");
|
|
538
|
-
if (parts.length !== 4) return undefined;
|
|
539
|
-
const bytes = new Uint8Array(4);
|
|
540
|
-
for (let i = 0; i < 4; i++) {
|
|
541
|
-
if (!/^\d{1,3}$/.test(parts[i])) return undefined;
|
|
542
|
-
const value = Number(parts[i]);
|
|
543
|
-
if (value > 255) return undefined;
|
|
544
|
-
bytes[i] = value;
|
|
545
|
-
}
|
|
546
|
-
return bytes;
|
|
547
|
-
};
|
|
548
|
-
const parseIPv6 = text => {
|
|
549
|
-
const halves = text.split("::");
|
|
550
|
-
if (halves.length > 2) return undefined;
|
|
551
|
-
const toGroups = part => part === "" ? [] : part.split(":");
|
|
552
|
-
const head = toGroups(halves[0]);
|
|
553
|
-
const tail = halves.length === 2 ? toGroups(halves[1]) : [];
|
|
554
|
-
const bytes = new Uint8Array(16);
|
|
555
|
-
const trailing = tail.length > 0 ? tail[tail.length - 1] : head.length > 0 ? head[head.length - 1] : "";
|
|
556
|
-
const embedded = trailing.includes(".") ? parseIPv4(trailing) : undefined;
|
|
557
|
-
if (trailing.includes(".") && embedded === undefined) return undefined;
|
|
558
|
-
if (embedded !== undefined) {
|
|
559
|
-
if (tail.length > 0) tail.pop();else head.pop();
|
|
560
|
-
}
|
|
561
|
-
const groupCount = embedded === undefined ? 8 : 6;
|
|
562
|
-
if (head.length + tail.length > groupCount) return undefined;
|
|
563
|
-
if (halves.length === 1 && head.length !== groupCount) return undefined;
|
|
564
|
-
const writeGroup = (group, offset) => {
|
|
565
|
-
if (!/^[0-9a-fA-F]{1,4}$/.test(group)) return false;
|
|
566
|
-
const value = Number.parseInt(group, 16);
|
|
567
|
-
bytes[offset] = value >> 8;
|
|
568
|
-
bytes[offset + 1] = value & 0xff;
|
|
569
|
-
return true;
|
|
570
|
-
};
|
|
571
|
-
for (let i = 0; i < head.length; i++) {
|
|
572
|
-
if (!writeGroup(head[i], i * 2)) return undefined;
|
|
573
|
-
}
|
|
574
|
-
for (let i = 0; i < tail.length; i++) {
|
|
575
|
-
if (!writeGroup(tail[i], (groupCount - tail.length + i) * 2)) return undefined;
|
|
576
|
-
}
|
|
577
|
-
if (embedded !== undefined) bytes.set(embedded, 12);
|
|
578
|
-
return bytes;
|
|
579
|
-
};
|
|
580
|
-
const formatIPv4 = (bytes, offset) => `${bytes[offset]}.${bytes[offset + 1]}.${bytes[offset + 2]}.${bytes[offset + 3]}`;
|
|
581
|
-
const formatIPv6 = (bytes, offset) => {
|
|
582
|
-
let isV4Mapped = bytes[offset + 10] === 0xff && bytes[offset + 11] === 0xff;
|
|
583
|
-
for (let i = 0; isV4Mapped && i < 10; i++) isV4Mapped = bytes[offset + i] === 0;
|
|
584
|
-
if (isV4Mapped) return `::ffff:${formatIPv4(bytes, offset + 12)}`;
|
|
585
|
-
const groups = [];
|
|
586
|
-
for (let i = 0; i < 8; i++) groups.push(readUint16(bytes, offset + i * 2));
|
|
587
|
-
let bestStart = -1;
|
|
588
|
-
let bestLength = 0;
|
|
589
|
-
let start = -1;
|
|
590
|
-
for (let i = 0; i <= 8; i++) {
|
|
591
|
-
if (i < 8 && groups[i] === 0) {
|
|
592
|
-
if (start === -1) start = i;
|
|
593
|
-
} else if (start !== -1) {
|
|
594
|
-
if (i - start > bestLength) {
|
|
595
|
-
bestStart = start;
|
|
596
|
-
bestLength = i - start;
|
|
597
|
-
}
|
|
598
|
-
start = -1;
|
|
599
|
-
}
|
|
600
|
-
}
|
|
601
|
-
if (bestLength < 2) {
|
|
602
|
-
return groups.map(group => group.toString(16)).join(":");
|
|
603
|
-
}
|
|
604
|
-
const head = groups.slice(0, bestStart).map(group => group.toString(16)).join(":");
|
|
605
|
-
const tail = groups.slice(bestStart + bestLength).map(group => group.toString(16)).join(":");
|
|
606
|
-
return `${head}::${tail}`;
|
|
607
|
-
};
|
|
608
|
-
const hasHostBits = (bytes, offset, length, bits) => {
|
|
609
|
-
const wholeBytes = Math.floor(bits / 8);
|
|
610
|
-
const partialBits = bits % 8;
|
|
611
|
-
if (partialBits !== 0 && (bytes[offset + wholeBytes] & (1 << 8 - partialBits) - 1) !== 0) {
|
|
612
|
-
return true;
|
|
613
|
-
}
|
|
614
|
-
for (let index = wholeBytes + (partialBits === 0 ? 0 : 1); index < length; index++) {
|
|
615
|
-
if (bytes[offset + index] !== 0) return true;
|
|
616
|
-
}
|
|
617
|
-
return false;
|
|
618
|
-
};
|
|
619
539
|
const encodeInet = (value, isCidr) => {
|
|
620
|
-
const
|
|
621
|
-
const
|
|
622
|
-
const
|
|
623
|
-
|
|
624
|
-
const
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
return fail(`Invalid netmask length in "${text}"`);
|
|
632
|
-
}
|
|
633
|
-
if (isCidr && hasHostBits(bytes, 0, bytes.length, bits)) {
|
|
634
|
-
return fail(`CIDR address has host bits set in "${text}"`);
|
|
540
|
+
const type = isCidr ? "cidr" : "inet";
|
|
541
|
+
const text = requireString(value, type);
|
|
542
|
+
const parsed = IpInterface.fromString(text);
|
|
543
|
+
if (Result.isFailure(parsed)) return fail(`Invalid ${type} value ${JSON.stringify(text)}: ${parsed.failure.message}`);
|
|
544
|
+
const address = parsed.success.address;
|
|
545
|
+
const bits = parsed.success.prefixLength;
|
|
546
|
+
if (isCidr) {
|
|
547
|
+
const network = IpNetwork.make(address, bits);
|
|
548
|
+
if (Result.isFailure(network)) {
|
|
549
|
+
return fail(`Invalid ${type} value ${JSON.stringify(text)}: ${network.failure.message}`);
|
|
550
|
+
}
|
|
635
551
|
}
|
|
636
|
-
const
|
|
637
|
-
result
|
|
552
|
+
const octets = NetAddress.isIpv4Address(address) ? NetAddress.ipv4ToOctets(address) : NetAddress.ipv6ToOctets(address);
|
|
553
|
+
const result = new Uint8Array(4 + octets.length);
|
|
554
|
+
result[0] = NetAddress.isIpv4Address(address) ? PGSQL_AF_INET : PGSQL_AF_INET6;
|
|
638
555
|
result[1] = bits;
|
|
639
556
|
result[2] = isCidr ? 1 : 0;
|
|
640
|
-
result[3] =
|
|
641
|
-
result.set(
|
|
557
|
+
result[3] = octets.length;
|
|
558
|
+
result.set(octets, 4);
|
|
642
559
|
return result;
|
|
643
560
|
};
|
|
644
561
|
const decodeInet = (bytes, offset, size) => {
|
|
@@ -655,11 +572,14 @@ const decodeInet = (bytes, offset, size) => {
|
|
|
655
572
|
}
|
|
656
573
|
requireSize(size, 4 + addressSize, "inet");
|
|
657
574
|
if (bits > addressSize * 8) return fail(`Invalid inet netmask length: ${bits}`);
|
|
658
|
-
|
|
659
|
-
|
|
575
|
+
const addressBytes = bytes.slice(offset + 4, offset + 4 + addressSize);
|
|
576
|
+
const address = family === PGSQL_AF_INET ? NetAddress.ipv4FromBytesUnsafe(addressBytes) : NetAddress.ipv6FromBytesUnsafe(addressBytes);
|
|
577
|
+
if (isCidr) {
|
|
578
|
+
const network = IpNetwork.make(address, bits);
|
|
579
|
+
if (Result.isFailure(network)) return fail(network.failure.message);
|
|
580
|
+
return IpNetwork.format(network.success);
|
|
660
581
|
}
|
|
661
|
-
|
|
662
|
-
return isCidr || bits !== addressSize * 8 ? `${text}/${bits}` : text;
|
|
582
|
+
return bits === addressSize * 8 ? NetAddress.formatIp(address) : IpInterface.format(IpInterface.makeUnsafe(address, bits));
|
|
663
583
|
};
|
|
664
584
|
// -----------------------------------------------------------------------------
|
|
665
585
|
// uuid
|
|
@@ -762,6 +682,31 @@ const decodeUuid = (bytes, offset, size) => {
|
|
|
762
682
|
const b15 = bytes[offset + 15];
|
|
763
683
|
return String.fromCharCode(hexHigh[b0], hexLow[b0], hexHigh[b1], hexLow[b1], hexHigh[b2], hexLow[b2], hexHigh[b3], hexLow[b3], 45, hexHigh[b4], hexLow[b4], hexHigh[b5], hexLow[b5], 45, hexHigh[b6], hexLow[b6], hexHigh[b7], hexLow[b7], 45, hexHigh[b8], hexLow[b8], hexHigh[b9], hexLow[b9], 45, hexHigh[b10], hexLow[b10], hexHigh[b11], hexLow[b11], hexHigh[b12], hexLow[b12], hexHigh[b13], hexLow[b13], hexHigh[b14], hexLow[b14], hexHigh[b15], hexLow[b15]);
|
|
764
684
|
};
|
|
685
|
+
const toUnsafeCodec = codec => ({
|
|
686
|
+
encode(value) {
|
|
687
|
+
const encoded = codec.encode(value);
|
|
688
|
+
if (Result.isFailure(encoded)) throw encoded.failure;
|
|
689
|
+
return encoded.success;
|
|
690
|
+
},
|
|
691
|
+
decode(bytes) {
|
|
692
|
+
const decoded = codec.decode(bytes);
|
|
693
|
+
if (Result.isFailure(decoded)) throw decoded.failure;
|
|
694
|
+
return decoded.success;
|
|
695
|
+
},
|
|
696
|
+
...(codec.write === undefined ? undefined : {
|
|
697
|
+
write(sink, value) {
|
|
698
|
+
const written = codec.write(sink, value);
|
|
699
|
+
if (Result.isFailure(written)) throw written.failure;
|
|
700
|
+
}
|
|
701
|
+
}),
|
|
702
|
+
...(codec.read === undefined ? undefined : {
|
|
703
|
+
read(bytes, offset, size) {
|
|
704
|
+
const decoded = codec.read(bytes, offset, size);
|
|
705
|
+
if (Result.isFailure(decoded)) throw decoded.failure;
|
|
706
|
+
return decoded.success;
|
|
707
|
+
}
|
|
708
|
+
})
|
|
709
|
+
});
|
|
765
710
|
/** A codec whose `decode` is its `read` over the whole of its bytes. */
|
|
766
711
|
const codecOf = (read, encode, write) => {
|
|
767
712
|
const decode = bytes => read(bytes, 0, bytes.length);
|
|
@@ -954,7 +899,7 @@ const jsonbCodec = /*#__PURE__*/codecOf((bytes, offset, size) => {
|
|
|
954
899
|
sink.uint8(1);
|
|
955
900
|
sink.utf8(text);
|
|
956
901
|
});
|
|
957
|
-
const
|
|
902
|
+
const builtinScalars = /*#__PURE__*/new Map([[OID.bool, /*#__PURE__*/codecOf((bytes, offset, size) => {
|
|
958
903
|
requireSize(size, 1, "bool");
|
|
959
904
|
return bytes[offset] !== 0;
|
|
960
905
|
}, value => {
|
|
@@ -1025,9 +970,8 @@ const builtins = /*#__PURE__*/new Map([[OID.bool, /*#__PURE__*/codecOf((bytes, o
|
|
|
1025
970
|
scratchView8.setBigInt64(0, timeValue(value));
|
|
1026
971
|
return takeScratch8();
|
|
1027
972
|
}, (sink, value) => sink.bigInt64(timeValue(value)))], [OID.numeric, /*#__PURE__*/codecOf(decodeNumeric, encodeNumeric)], [OID.text, utf8Codec], [OID.varchar, utf8Codec], [OID.bpchar, utf8Codec], [OID.name, utf8Codec], [OID.json, jsonCodec], [OID.jsonb, jsonbCodec], [OID.uuid, /*#__PURE__*/codecOf(decodeUuid, encodeUuid, writeUuid)], [OID.inet, /*#__PURE__*/codecOf(decodeInet, value => encodeInet(value, false))], [OID.cidr, /*#__PURE__*/codecOf(decodeInet, value => encodeInet(value, true))], [OID.date, dateCodec], [OID.timetz, timetzCodec], [OID.timestamp, timestampCodec], [OID.timestamptz, timestampCodec]]);
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
}
|
|
973
|
+
const makeArrayCodec = (elementOid, lookup) => codecOf((bytes, offset, size) => decodeArray(bytes, offset, size, elementOid, lookup), value => encodeArray(value, elementOid, lookup), (sink, value) => writeArray(sink, value, elementOid, lookup));
|
|
974
|
+
const builtins = /*#__PURE__*/new Map(builtinScalars);
|
|
1031
975
|
/**
|
|
1032
976
|
* Built-ins with registered codecs layered over them, so `encode` and `decode`
|
|
1033
977
|
* resolve an OID with a single lookup.
|
|
@@ -1040,8 +984,49 @@ const codecs = /*#__PURE__*/new Map(builtins);
|
|
|
1040
984
|
*/
|
|
1041
985
|
const tableSize = 4096;
|
|
1042
986
|
const table = /*#__PURE__*/new Array(tableSize);
|
|
1043
|
-
for (const [oid, codec] of codecs) table[oid] = codec;
|
|
1044
987
|
const lookup = oid => oid >= 0 && oid < tableSize ? table[oid] : codecs.get(oid);
|
|
988
|
+
for (const [arrayOid, elementOid] of arrayToElement) {
|
|
989
|
+
const codec = /*#__PURE__*/makeArrayCodec(elementOid, lookup);
|
|
990
|
+
builtins.set(arrayOid, codec);
|
|
991
|
+
codecs.set(arrayOid, codec);
|
|
992
|
+
}
|
|
993
|
+
for (const [oid, codec] of codecs) table[oid] = codec;
|
|
994
|
+
const registryStates = /*#__PURE__*/new WeakMap();
|
|
995
|
+
const getRegistryState = registry => {
|
|
996
|
+
const state = registryStates.get(registry);
|
|
997
|
+
if (state === undefined) return fail("Invalid PgTypes Registry");
|
|
998
|
+
return state;
|
|
999
|
+
};
|
|
1000
|
+
const registerInState = (state, oid, codec, options) => {
|
|
1001
|
+
state.codecs.set(oid, toUnsafeCodec(codec));
|
|
1002
|
+
if (options?.arrayOid !== undefined) {
|
|
1003
|
+
state.elementToArray.set(oid, options.arrayOid);
|
|
1004
|
+
state.codecs.set(options.arrayOid, makeArrayCodec(oid, state.lookup));
|
|
1005
|
+
}
|
|
1006
|
+
};
|
|
1007
|
+
/**
|
|
1008
|
+
* Creates a client-specific registry containing the built-in codecs.
|
|
1009
|
+
*
|
|
1010
|
+
* @category constructors
|
|
1011
|
+
* @since 4.0.0
|
|
1012
|
+
*/
|
|
1013
|
+
export const makeRegistry = () => {
|
|
1014
|
+
const codecs = new Map(builtinScalars);
|
|
1015
|
+
const state = {
|
|
1016
|
+
codecs,
|
|
1017
|
+
elementToArray: new Map(elementToArray),
|
|
1018
|
+
lookup: oid => codecs.get(oid)
|
|
1019
|
+
};
|
|
1020
|
+
for (const [arrayOid, elementOid] of arrayToElement) {
|
|
1021
|
+
codecs.set(arrayOid, makeArrayCodec(elementOid, state.lookup));
|
|
1022
|
+
}
|
|
1023
|
+
const registry = {
|
|
1024
|
+
register: (oid, codec, options) => registerInState(state, oid, codec, options)
|
|
1025
|
+
};
|
|
1026
|
+
registryStates.set(registry, state);
|
|
1027
|
+
return registry;
|
|
1028
|
+
};
|
|
1029
|
+
const lookupFor = registry => registry === undefined ? lookup : getRegistryState(registry).lookup;
|
|
1045
1030
|
/**
|
|
1046
1031
|
* Registers a binary codec for an OID the built-in catalogue does not cover,
|
|
1047
1032
|
* or overrides a built-in one. Registered codecs take precedence.
|
|
@@ -1050,31 +1035,7 @@ const lookup = oid => oid >= 0 && oid < tableSize ? table[oid] : codecs.get(oid)
|
|
|
1050
1035
|
* @since 4.0.0
|
|
1051
1036
|
*/
|
|
1052
1037
|
export const register = (oid, codec) => {
|
|
1053
|
-
const unsafe =
|
|
1054
|
-
encode(value) {
|
|
1055
|
-
const encoded = codec.encode(value);
|
|
1056
|
-
if (Result.isFailure(encoded)) throw encoded.failure;
|
|
1057
|
-
return encoded.success;
|
|
1058
|
-
},
|
|
1059
|
-
decode(bytes) {
|
|
1060
|
-
const decoded = codec.decode(bytes);
|
|
1061
|
-
if (Result.isFailure(decoded)) throw decoded.failure;
|
|
1062
|
-
return decoded.success;
|
|
1063
|
-
},
|
|
1064
|
-
...(codec.write === undefined ? undefined : {
|
|
1065
|
-
write(sink, value) {
|
|
1066
|
-
const written = codec.write(sink, value);
|
|
1067
|
-
if (Result.isFailure(written)) throw written.failure;
|
|
1068
|
-
}
|
|
1069
|
-
}),
|
|
1070
|
-
...(codec.read === undefined ? undefined : {
|
|
1071
|
-
read(bytes, offset, size) {
|
|
1072
|
-
const decoded = codec.read(bytes, offset, size);
|
|
1073
|
-
if (Result.isFailure(decoded)) throw decoded.failure;
|
|
1074
|
-
return decoded.success;
|
|
1075
|
-
}
|
|
1076
|
-
})
|
|
1077
|
-
};
|
|
1038
|
+
const unsafe = toUnsafeCodec(codec);
|
|
1078
1039
|
codecs.set(oid, unsafe);
|
|
1079
1040
|
if (oid >= 0 && oid < tableSize) table[oid] = unsafe;
|
|
1080
1041
|
};
|
|
@@ -1092,7 +1053,7 @@ export const unregister = oid => {
|
|
|
1092
1053
|
// -----------------------------------------------------------------------------
|
|
1093
1054
|
// arrays
|
|
1094
1055
|
// -----------------------------------------------------------------------------
|
|
1095
|
-
const encodeArray = (value, elementOid) => {
|
|
1056
|
+
const encodeArray = (value, elementOid, lookup) => {
|
|
1096
1057
|
if (!Array.isArray(value)) {
|
|
1097
1058
|
return fail("Expected an array");
|
|
1098
1059
|
}
|
|
@@ -1143,7 +1104,7 @@ const encodeArray = (value, elementOid) => {
|
|
|
1143
1104
|
* and written in place, so neither the elements nor the array itself needs an
|
|
1144
1105
|
* array of bytes of its own.
|
|
1145
1106
|
*/
|
|
1146
|
-
const writeArray = (sink, value, elementOid) => {
|
|
1107
|
+
const writeArray = (sink, value, elementOid, lookup) => {
|
|
1147
1108
|
if (!Array.isArray(value)) {
|
|
1148
1109
|
return fail("Expected an array");
|
|
1149
1110
|
}
|
|
@@ -1174,7 +1135,7 @@ const writeArray = (sink, value, elementOid) => {
|
|
|
1174
1135
|
sink.int32(-1);
|
|
1175
1136
|
} else {
|
|
1176
1137
|
const token = sink.beginLength();
|
|
1177
|
-
if (write === undefined) writeValue(sink, element, elementOid);else write(sink, element);
|
|
1138
|
+
if (write === undefined) writeValue(sink, element, elementOid, lookup);else write(sink, element);
|
|
1178
1139
|
sink.endLength(token);
|
|
1179
1140
|
}
|
|
1180
1141
|
}
|
|
@@ -1184,7 +1145,7 @@ const writeArray = (sink, value, elementOid) => {
|
|
|
1184
1145
|
* where it can be, so a thousand elements cost a thousand reads rather than a
|
|
1185
1146
|
* thousand lookups and a thousand views.
|
|
1186
1147
|
*/
|
|
1187
|
-
const decodeArray = (bytes, start, size, elementOid) => {
|
|
1148
|
+
const decodeArray = (bytes, start, size, elementOid, lookup) => {
|
|
1188
1149
|
if (size < 12) return fail("Truncated array value");
|
|
1189
1150
|
const dimensions = readInt32(bytes, start);
|
|
1190
1151
|
const wireElementOid = readUint32(bytes, start + 8);
|
|
@@ -1225,18 +1186,15 @@ const decodeArray = (bytes, start, size, elementOid) => {
|
|
|
1225
1186
|
return values;
|
|
1226
1187
|
};
|
|
1227
1188
|
/**
|
|
1228
|
-
*
|
|
1229
|
-
*
|
|
1189
|
+
* Creates a field reader for `PgProtocol.makeParser`.
|
|
1190
|
+
*
|
|
1191
|
+
* **Details**
|
|
1230
1192
|
*
|
|
1231
|
-
*
|
|
1232
|
-
*
|
|
1233
|
-
*
|
|
1193
|
+
* Codecs are resolved once per column. SQL `NULL` becomes `null`, and columns
|
|
1194
|
+
* without a registered codec return a copy of their bytes. Text-format columns
|
|
1195
|
+
* fail with `CodecError`.
|
|
1234
1196
|
*
|
|
1235
|
-
*
|
|
1236
|
-
* `CodecError` failure here rather than once per row. A successful result
|
|
1237
|
-
* contains the parser's internal throwing fast path; its failures are terminal
|
|
1238
|
-
* for that parser. The standalone `encode` and `decode` APIs remain typed
|
|
1239
|
-
* `Result` values.
|
|
1197
|
+
* **Example** (Updating the reader after `RowDescription`)
|
|
1240
1198
|
*
|
|
1241
1199
|
* ```ts
|
|
1242
1200
|
* import { PgProtocol, PgTypes } from "@effect/sql-pg"
|
|
@@ -1250,7 +1208,8 @@ const decodeArray = (bytes, start, size, elementOid) => {
|
|
|
1250
1208
|
* @category decoding
|
|
1251
1209
|
* @since 4.0.0
|
|
1252
1210
|
*/
|
|
1253
|
-
export const makeFieldReader = columns => result(() => {
|
|
1211
|
+
export const makeFieldReader = (columns, registry) => result(() => {
|
|
1212
|
+
const lookup = lookupFor(registry);
|
|
1254
1213
|
const codecs = columns.map((column, index) => {
|
|
1255
1214
|
if (column.format !== 1) {
|
|
1256
1215
|
return fail(`Only the binary format is supported, column ${index} has format ${column.format}`);
|
|
@@ -1268,45 +1227,75 @@ export const makeFieldReader = columns => result(() => {
|
|
|
1268
1227
|
/**
|
|
1269
1228
|
* Encodes a JavaScript value as the binary representation of the given OID.
|
|
1270
1229
|
*
|
|
1230
|
+
* **Details**
|
|
1231
|
+
*
|
|
1271
1232
|
* Returns a `CodecError` failure when the value has the wrong JavaScript type,
|
|
1272
1233
|
* or when the OID is neither built in nor registered.
|
|
1273
1234
|
*
|
|
1274
1235
|
* @category encoding
|
|
1275
1236
|
* @since 4.0.0
|
|
1276
1237
|
*/
|
|
1277
|
-
export const encode = (value, oid) => result(() => {
|
|
1278
|
-
const codec =
|
|
1238
|
+
export const encode = (value, oid, registry) => result(() => {
|
|
1239
|
+
const codec = lookupFor(registry)(oid);
|
|
1279
1240
|
if (codec === undefined) return fail(`No codec registered for OID ${oid}`);
|
|
1280
1241
|
return codec.encode(value);
|
|
1281
1242
|
});
|
|
1282
1243
|
/**
|
|
1283
1244
|
* Decodes the binary representation of the given OID.
|
|
1284
1245
|
*
|
|
1246
|
+
* **Details**
|
|
1247
|
+
*
|
|
1285
1248
|
* `format` must be `1`; the text format is not implemented. An OID that is
|
|
1286
1249
|
* neither built in nor registered decodes to the raw bytes.
|
|
1287
1250
|
*
|
|
1288
1251
|
* @category decoding
|
|
1289
1252
|
* @since 4.0.0
|
|
1290
1253
|
*/
|
|
1291
|
-
export const decode = (bytes, oid, format) => result(() => {
|
|
1254
|
+
export const decode = (bytes, oid, format, registry) => result(() => {
|
|
1292
1255
|
if (format !== 1) {
|
|
1293
1256
|
return fail(`Only the binary format is supported, received format ${format}`);
|
|
1294
1257
|
}
|
|
1295
|
-
const codec =
|
|
1258
|
+
const codec = lookupFor(registry)(oid);
|
|
1296
1259
|
return codec === undefined ? bytes : codec.decode(bytes);
|
|
1297
1260
|
});
|
|
1261
|
+
// -----------------------------------------------------------------------------
|
|
1262
|
+
// parameter constructors
|
|
1263
|
+
// -----------------------------------------------------------------------------
|
|
1264
|
+
/**
|
|
1265
|
+
* The runtime type identifier for PostgreSQL parameters.
|
|
1266
|
+
*
|
|
1267
|
+
* @category type IDs
|
|
1268
|
+
* @since 4.0.0
|
|
1269
|
+
*/
|
|
1270
|
+
export const ParameterTypeId = "~@effect/sql-pg/PgTypes/Parameter";
|
|
1271
|
+
/**
|
|
1272
|
+
* Returns whether a value is a parameter created by this module.
|
|
1273
|
+
*
|
|
1274
|
+
* @category guards
|
|
1275
|
+
* @since 4.0.0
|
|
1276
|
+
*/
|
|
1277
|
+
export const isParameter = value => typeof value === "object" && value !== null && value[ParameterTypeId] === ParameterTypeId;
|
|
1298
1278
|
/**
|
|
1299
1279
|
* Encodes a parameter for a `Bind` message. SQL NULL stays `null`.
|
|
1300
1280
|
*
|
|
1301
1281
|
* @category encoding
|
|
1302
1282
|
* @since 4.0.0
|
|
1303
1283
|
*/
|
|
1304
|
-
export const encodeParameter = parameter => parameter.value === null ? Result.succeed(null) : encode(parameter.value, parameter.oid);
|
|
1305
|
-
const writeValue = (sink, value, oid) => {
|
|
1284
|
+
export const encodeParameter = (parameter, registry) => parameter.value === null ? Result.succeed(null) : encode(parameter.value, parameter.oid, registry);
|
|
1285
|
+
const writeValue = (sink, value, oid, lookup) => {
|
|
1306
1286
|
const codec = lookup(oid);
|
|
1307
1287
|
if (codec === undefined) return fail(`No codec registered for OID ${oid}`);
|
|
1308
1288
|
if (codec.write === undefined) sink.raw(codec.encode(value));else codec.write(sink, value);
|
|
1309
1289
|
};
|
|
1290
|
+
/**
|
|
1291
|
+
* Returns whether a parameter uses the text format in a `Bind` message.
|
|
1292
|
+
* Untyped parameters (OID `0`) use text so PostgreSQL can infer their type;
|
|
1293
|
+
* typed parameters use the binary format.
|
|
1294
|
+
*
|
|
1295
|
+
* @category encoding
|
|
1296
|
+
* @since 4.0.0
|
|
1297
|
+
*/
|
|
1298
|
+
export const isTextFormat = parameter => parameter.oid === 0;
|
|
1310
1299
|
/**
|
|
1311
1300
|
* Writes a parameter into a `Bind` frame, for `PgProtocol.makeBindEncoder`.
|
|
1312
1301
|
* Codecs that can write their bytes in place do; the rest fall back to
|
|
@@ -1315,10 +1304,19 @@ const writeValue = (sink, value, oid) => {
|
|
|
1315
1304
|
* @category encoding
|
|
1316
1305
|
* @since 4.0.0
|
|
1317
1306
|
*/
|
|
1318
|
-
const writeParameterUnsafe = (sink, parameter) => parameter.value === null ? sink.sqlNull()
|
|
1319
|
-
|
|
1307
|
+
const writeParameterUnsafe = (sink, parameter, lookup) => parameter.value === null ? sink.sqlNull()
|
|
1308
|
+
// An untyped parameter is the value's text representation; see
|
|
1309
|
+
// `isTextFormat`.
|
|
1310
|
+
: parameter.oid === 0 ? sink.utf8(String(parameter.value)) : writeValue(sink, parameter.value, parameter.oid, lookup);
|
|
1311
|
+
/**
|
|
1312
|
+
* Writes a parameter into a `Bind` frame.
|
|
1313
|
+
*
|
|
1314
|
+
* @category encoding
|
|
1315
|
+
* @since 4.0.0
|
|
1316
|
+
*/
|
|
1317
|
+
export const writeParameter = (sink, parameter, registry) => {
|
|
1320
1318
|
try {
|
|
1321
|
-
writeParameterUnsafe(sink, parameter);
|
|
1319
|
+
writeParameterUnsafe(sink, parameter, lookupFor(registry));
|
|
1322
1320
|
return Result.void;
|
|
1323
1321
|
} catch (error) {
|
|
1324
1322
|
if (error instanceof CodecError) return Result.fail(error);
|
|
@@ -1327,12 +1325,14 @@ export const writeParameter = (sink, parameter) => {
|
|
|
1327
1325
|
};
|
|
1328
1326
|
const valueWriterUnsafe = /*#__PURE__*/Symbol.for("@effect/sql-pg/PgProtocol/ValueWriter/unsafe");
|
|
1329
1327
|
Object.defineProperty(writeParameter, valueWriterUnsafe, {
|
|
1330
|
-
value: writeParameterUnsafe
|
|
1328
|
+
value: (sink, parameter) => writeParameterUnsafe(sink, parameter, lookup)
|
|
1331
1329
|
});
|
|
1332
|
-
const
|
|
1330
|
+
const makeParameter = (oid, value) => ({
|
|
1331
|
+
[ParameterTypeId]: ParameterTypeId,
|
|
1333
1332
|
oid,
|
|
1334
1333
|
value
|
|
1335
1334
|
});
|
|
1335
|
+
const parameter = oid => value => makeParameter(oid, value);
|
|
1336
1336
|
/**
|
|
1337
1337
|
* A `bool` parameter.
|
|
1338
1338
|
*
|
|
@@ -1501,14 +1501,11 @@ export const timestamptz = /*#__PURE__*/parameter(OID.timestamptz);
|
|
|
1501
1501
|
* @category constructors
|
|
1502
1502
|
* @since 4.0.0
|
|
1503
1503
|
*/
|
|
1504
|
-
export const array = (values, elementOid) => result(() => {
|
|
1505
|
-
const arrayOid =
|
|
1504
|
+
export const array = (values, elementOid, registry) => result(() => {
|
|
1505
|
+
const arrayOid = arrayOidFor(elementOid, registry);
|
|
1506
1506
|
if (arrayOid === undefined) {
|
|
1507
1507
|
return fail(`No array type known for element OID ${elementOid}`);
|
|
1508
1508
|
}
|
|
1509
|
-
return
|
|
1510
|
-
oid: arrayOid,
|
|
1511
|
-
value: values
|
|
1512
|
-
};
|
|
1509
|
+
return makeParameter(arrayOid, values);
|
|
1513
1510
|
});
|
|
1514
1511
|
//# sourceMappingURL=PgTypes.js.map
|