type_module.ex (24603B)
1 defmodule Postgrex.TypeModule do 2 @moduledoc false 3 4 alias Postgrex.TypeInfo 5 6 def define(module, extensions, opts) do 7 opts = 8 opts 9 |> Keyword.put_new(:decode_binary, :copy) 10 11 config = configure(extensions, opts) 12 define_inline(module, config, opts) 13 end 14 15 ## Helpers 16 17 defp directives(config, opts) do 18 requires = 19 for {extension, _} <- config do 20 quote do: require(unquote(extension)) 21 end 22 23 preludes = 24 for {extension, {state, _, _}} <- config, 25 function_exported?(extension, :prelude, 1), 26 do: extension.prelude(state) 27 28 null = Keyword.get(opts, :null) 29 30 moduledoc = Keyword.get(opts, :moduledoc, false) 31 32 quote do 33 @moduledoc unquote(moduledoc) 34 import Postgrex.BinaryUtils 35 require unquote(__MODULE__) 36 unquote(requires) 37 unquote(preludes) 38 unquote(bin_opt_info(opts)) 39 @compile {:inline, [encode_value: 2]} 40 @dialyzer {:no_opaque, [decode_tuple: 5]} 41 @null unquote(Macro.escape(null)) 42 end 43 end 44 45 defp bin_opt_info(opts) do 46 if Keyword.get(opts, :bin_opt_info) do 47 quote do: @compile(:bin_opt_info) 48 else 49 [] 50 end 51 end 52 53 @anno [generated: true] 54 55 defp find(config) do 56 clauses = Enum.flat_map(config, &find_clauses/1) 57 clauses = clauses ++ quote do: (_ -> nil) 58 59 quote @anno do 60 @doc false 61 def find(type_info, formats) do 62 case {type_info, formats} do 63 unquote(clauses) 64 end 65 end 66 end 67 end 68 69 defp find_clauses({extension, {opts, matching, format}}) do 70 for {key, value} <- matching do 71 [clause] = find_clause(extension, opts, key, value, format) 72 clause 73 end 74 end 75 76 defp find_clause(extension, opts, key, value, :super_binary) do 77 quote do 78 {%{unquote(key) => unquote(value)} = type_info, formats} 79 when formats in [:any, :binary] -> 80 oids = unquote(extension).oids(type_info, unquote(opts)) 81 {:super_binary, unquote(extension), oids} 82 end 83 end 84 85 defp find_clause(extension, _opts, key, value, format) do 86 quote do 87 {%{unquote(key) => unquote(value)}, formats} 88 when formats in [:any, unquote(format)] -> 89 {unquote(format), unquote(extension)} 90 end 91 end 92 93 defp maybe_rewrite(ast, extension, cases, opts) do 94 if Postgrex.Utils.default_extension?(extension) and 95 not Keyword.get(opts, :debug_defaults, false) do 96 ast 97 else 98 rewrite(ast, cases) 99 end 100 end 101 102 defp rewrite(ast, [{:->, clause_meta, _} | _original]) do 103 Macro.prewalk(ast, fn 104 {kind, meta, [{fun, _, args}, block]} when kind in [:def, :defp] and is_list(args) -> 105 {kind, meta, [{fun, clause_meta, args}, block]} 106 107 other -> 108 other 109 end) 110 end 111 112 defp encode(config, define_opts) do 113 encodes = 114 for {extension, {opts, [_ | _], format}} <- config do 115 encode = extension.encode(opts) 116 117 clauses = 118 for clause <- encode do 119 encode_type(extension, format, clause) 120 end 121 122 clauses = [encode_null(extension, format) | clauses] 123 124 quote do 125 unquote(encode_value(extension, format)) 126 127 unquote(encode_inline(extension, format)) 128 129 unquote(clauses |> maybe_rewrite(extension, encode, define_opts)) 130 end 131 end 132 133 quote location: :keep do 134 unquote(encodes) 135 136 @doc false 137 def encode_params(params, types) do 138 encode_params(params, types, []) 139 end 140 141 defp encode_params([param | params], [type | types], encoded) do 142 encode_params(params, types, [encode_value(param, type) | encoded]) 143 end 144 145 defp encode_params([], [], encoded), do: Enum.reverse(encoded) 146 defp encode_params(params, _, _) when is_list(params), do: :error 147 148 @doc false 149 def encode_tuple(tuple, nil, _types) do 150 raise DBConnection.EncodeError, """ 151 cannot encode anonymous tuple #{inspect(tuple)}. \ 152 Please define a custom Postgrex extension that matches on its underlying type: 153 154 use Postgrex.BinaryExtension, type: "typeinthedb" 155 """ 156 end 157 158 def encode_tuple(tuple, oids, types) do 159 encode_tuple(tuple, 1, oids, types, []) 160 end 161 162 defp encode_tuple(tuple, n, [oid | oids], [type | types], acc) do 163 param = :erlang.element(n, tuple) 164 acc = [acc, <<oid::uint32()>> | encode_value(param, type)] 165 encode_tuple(tuple, n + 1, oids, types, acc) 166 end 167 168 defp encode_tuple(tuple, n, [], [], acc) when tuple_size(tuple) < n do 169 acc 170 end 171 172 defp encode_tuple(tuple, n, [], [], _) when is_tuple(tuple) do 173 raise DBConnection.EncodeError, 174 "expected a tuple of size #{n - 1}, got: #{inspect(tuple)}" 175 end 176 177 @doc false 178 def encode_list(list, type) do 179 encode_list(list, type, []) 180 end 181 182 defp encode_list([value | rest], type, acc) do 183 encode_list(rest, type, [acc | encode_value(value, type)]) 184 end 185 186 defp encode_list([], _, acc) do 187 acc 188 end 189 end 190 end 191 192 defp encode_type(extension, :super_binary, clause) do 193 encode_super(extension, clause) 194 end 195 196 defp encode_type(extension, _, clause) do 197 encode_extension(extension, clause) 198 end 199 200 defp encode_extension(extension, clause) do 201 case split_extension(clause) do 202 {pattern, guard, body} -> 203 encode_extension(extension, pattern, guard, body) 204 205 {pattern, body} -> 206 encode_extension(extension, pattern, body) 207 end 208 end 209 210 defp encode_extension(extension, pattern, guard, body) do 211 quote do 212 defp unquote(extension)(unquote(pattern)) when unquote(guard) do 213 unquote(body) 214 end 215 end 216 end 217 218 defp encode_extension(extension, pattern, body) do 219 quote do 220 defp unquote(extension)(unquote(pattern)) do 221 unquote(body) 222 end 223 end 224 end 225 226 defp encode_super(extension, clause) do 227 case split_super(clause) do 228 {pattern, sub_oids, sub_types, guard, body} -> 229 encode_super(extension, pattern, sub_oids, sub_types, guard, body) 230 231 {pattern, sub_oids, sub_types, body} -> 232 encode_super(extension, pattern, sub_oids, sub_types, body) 233 end 234 end 235 236 defp encode_super(extension, pattern, sub_oids, sub_types, guard, body) do 237 quote do 238 defp unquote(extension)(unquote(pattern), unquote(sub_oids), unquote(sub_types)) 239 when unquote(guard) do 240 unquote(body) 241 end 242 end 243 end 244 245 defp encode_super(extension, pattern, sub_oids, sub_types, body) do 246 quote do 247 defp unquote(extension)(unquote(pattern), unquote(sub_oids), unquote(sub_types)) do 248 unquote(body) 249 end 250 end 251 end 252 253 defp encode_inline(extension, :super_binary) do 254 quote do 255 @compile {:inline, [{unquote(extension), 3}]} 256 end 257 end 258 259 defp encode_inline(extension, _) do 260 quote do 261 @compile {:inline, [{unquote(extension), 1}]} 262 end 263 end 264 265 defp encode_null(extension, :super_binary) do 266 quote do 267 defp unquote(extension)(@null, _sub_oids, _sub_types), do: <<-1::int32()>> 268 end 269 end 270 271 defp encode_null(extension, _) do 272 quote do 273 defp unquote(extension)(@null), do: <<-1::int32()>> 274 end 275 end 276 277 defp encode_value(extension, :super_binary) do 278 quote do 279 @doc false 280 def encode_value(value, {unquote(extension), sub_oids, sub_types}) do 281 unquote(extension)(value, sub_oids, sub_types) 282 end 283 end 284 end 285 286 defp encode_value(extension, _) do 287 quote do 288 @doc false 289 def encode_value(value, unquote(extension)) do 290 unquote(extension)(value) 291 end 292 end 293 end 294 295 defp decode(config, define_opts) do 296 rest = quote do: rest 297 acc = quote do: acc 298 rem = quote do: rem 299 full = quote do: full 300 rows = quote do: rows 301 302 row_dispatch = 303 for {extension, {_, [_ | _], format}} <- config do 304 decode_row_dispatch(extension, format, rest, acc, rem, full, rows) 305 end 306 307 next_dispatch = decode_rows_dispatch(rest, acc, rem, full, rows) 308 row_dispatch = row_dispatch ++ next_dispatch 309 310 decodes = 311 for {extension, {opts, [_ | _], format}} <- config do 312 decode = extension.decode(opts) 313 314 clauses = 315 for clause <- decode do 316 decode_type(extension, format, clause, row_dispatch, rest, acc, rem, full, rows) 317 end 318 319 null_clauses = decode_null(extension, format, row_dispatch, rest, acc, rem, full, rows) 320 321 quote location: :keep do 322 unquote(clauses |> maybe_rewrite(extension, decode, define_opts)) 323 324 unquote(null_clauses) 325 end 326 end 327 328 quote location: :keep do 329 unquote(decode_rows(row_dispatch, rest, acc, rem, full, rows)) 330 331 unquote(decode_simple()) 332 333 unquote(decode_list(config)) 334 335 unquote(decode_tuple(config)) 336 337 unquote(decodes) 338 end 339 end 340 341 defp decode_rows(dispatch, rest, acc, rem, full, rows) do 342 quote location: :keep, generated: true do 343 @doc false 344 def decode_rows(binary, types, rows) do 345 decode_rows(binary, byte_size(binary), types, rows) 346 end 347 348 defp decode_rows( 349 <<?D, size::int32(), _::int16(), unquote(rest)::binary>>, 350 rem, 351 unquote(full), 352 unquote(rows) 353 ) 354 when rem > size do 355 unquote(rem) = rem - (1 + size) 356 unquote(acc) = [] 357 358 case unquote(full) do 359 unquote(dispatch) 360 end 361 end 362 363 defp decode_rows(<<?D, size::int32(), rest::binary>>, rem, _, rows) do 364 more = size + 1 - rem 365 {:more, [?D, <<size::int32()>> | rest], rows, more} 366 end 367 368 defp decode_rows(<<?D, rest::binary>>, _, _, rows) do 369 {:more, [?D | rest], rows, 0} 370 end 371 372 defp decode_rows(<<rest::binary-size(0)>>, _, _, rows) do 373 {:more, [], rows, 0} 374 end 375 376 defp decode_rows(<<rest::binary>>, _, _, rows) do 377 {:ok, rows, rest} 378 end 379 end 380 end 381 382 defp decode_row_dispatch(extension, :super_binary, rest, acc, rem, full, rows) do 383 [clause] = 384 quote do 385 [{unquote(extension), sub_oids, sub_types} | types] -> 386 unquote(extension)( 387 unquote(rest), 388 sub_oids, 389 sub_types, 390 types, 391 unquote(acc), 392 unquote(rem), 393 unquote(full), 394 unquote(rows) 395 ) 396 end 397 398 clause 399 end 400 401 defp decode_row_dispatch(extension, _, rest, acc, rem, full, rows) do 402 [clause] = 403 quote do 404 [unquote(extension) | types2] -> 405 unquote(extension)( 406 unquote(rest), 407 types2, 408 unquote(acc), 409 unquote(rem), 410 unquote(full), 411 unquote(rows) 412 ) 413 end 414 415 clause 416 end 417 418 defp decode_rows_dispatch(rest, acc, rem, full, rows) do 419 quote do 420 [] -> 421 rows = [Enum.reverse(unquote(acc)) | unquote(rows)] 422 decode_rows(unquote(rest), unquote(rem), unquote(full), rows) 423 end 424 end 425 426 defp decode_simple() do 427 rest = quote do: rest 428 acc = quote do: acc 429 430 dispatch = decode_simple_dispatch(Postgrex.Extensions.Raw, rest, acc) 431 432 quote do 433 @doc false 434 def decode_simple(binary) do 435 decode_simple(binary, []) 436 end 437 438 defp decode_simple(<<>>, unquote(acc)), do: Enum.reverse(acc) 439 defp decode_simple(<<unquote(rest)::binary>>, unquote(acc)), do: unquote(dispatch) 440 end 441 end 442 443 defp decode_simple_dispatch(extension, rest, acc) do 444 quote do 445 unquote(extension)(unquote(rest), unquote(acc), &decode_simple/2) 446 end 447 end 448 449 defp decode_list(config) do 450 rest = quote do: rest 451 452 dispatch = 453 for {extension, {_, [_ | _], format}} <- config do 454 decode_list_dispatch(extension, format, rest) 455 end 456 457 quote do 458 @doc false 459 def decode_list(<<unquote(rest)::binary>>, type) do 460 case type do 461 unquote(dispatch) 462 end 463 end 464 end 465 end 466 467 defp decode_list_dispatch(extension, :super_binary, rest) do 468 [clause] = 469 quote do 470 {unquote(extension), sub_oids, sub_types} -> 471 unquote(extension)(unquote(rest), sub_oids, sub_types, []) 472 end 473 474 clause 475 end 476 477 defp decode_list_dispatch(extension, _, rest) do 478 [clause] = 479 quote do 480 unquote(extension) -> 481 unquote(extension)(unquote(rest), []) 482 end 483 484 clause 485 end 486 487 defp decode_tuple(config) do 488 rest = quote do: rest 489 oids = quote do: oids 490 n = quote do: n 491 acc = quote do: acc 492 493 dispatch = 494 for {extension, {_, [_ | _], format}} <- config do 495 decode_tuple_dispatch(extension, format, rest, oids, n, acc) 496 end 497 498 quote generated: true do 499 @doc false 500 def decode_tuple(<<rest::binary>>, count, types) when is_integer(count) do 501 decode_tuple(rest, count, types, 0, []) 502 end 503 504 def decode_tuple(<<rest::binary>>, oids, types) do 505 decode_tuple(rest, oids, types, 0, []) 506 end 507 508 defp decode_tuple( 509 <<oid::int32(), unquote(rest)::binary>>, 510 [oid | unquote(oids)], 511 types, 512 unquote(n), 513 unquote(acc) 514 ) do 515 case types do 516 unquote(dispatch) 517 end 518 end 519 520 defp decode_tuple(<<>>, [], [], n, acc) do 521 :erlang.make_tuple(n, @null, acc) 522 end 523 524 defp decode_tuple( 525 <<oid::int32(), unquote(rest)::binary>>, 526 rem, 527 types, 528 unquote(n), 529 unquote(acc) 530 ) 531 when rem > 0 do 532 case Postgrex.Types.fetch(oid, types) do 533 {:ok, {:binary, type}} -> 534 unquote(oids) = rem - 1 535 536 case [type | types] do 537 unquote(dispatch) 538 end 539 540 {:ok, {:text, _}} -> 541 msg = 542 "oid `#{oid}` was bootstrapped in text format and can not " <> 543 "be decoded inside an anonymous record" 544 545 raise RuntimeError, msg 546 547 {:error, %TypeInfo{type: pg_type}, _mod} -> 548 msg = "type `#{pg_type}` can not be handled by the configured extensions" 549 raise RuntimeError, msg 550 551 {:error, nil, _mod} -> 552 msg = "oid `#{oid}` was not bootstrapped and lacks type information" 553 raise RuntimeError, msg 554 end 555 end 556 557 defp decode_tuple(<<>>, 0, _types, n, acc) do 558 :erlang.make_tuple(n, @null, acc) 559 end 560 end 561 end 562 563 defp decode_tuple_dispatch(extension, :super_binary, rest, oids, n, acc) do 564 [clause] = 565 quote do 566 [{unquote(extension), sub_oids, sub_types} | types] -> 567 unquote(extension)( 568 unquote(rest), 569 sub_oids, 570 sub_types, 571 unquote(oids), 572 types, 573 unquote(n) + 1, 574 unquote(acc) 575 ) 576 end 577 578 clause 579 end 580 581 defp decode_tuple_dispatch(extension, _, rest, oids, n, acc) do 582 [clause] = 583 quote do 584 [unquote(extension) | types] -> 585 unquote(extension)(unquote(rest), unquote(oids), types, unquote(n) + 1, unquote(acc)) 586 end 587 588 clause 589 end 590 591 defp decode_type(extension, :super_binary, clause, dispatch, rest, acc, rem, full, rows) do 592 decode_super(extension, clause, dispatch, rest, acc, rem, full, rows) 593 end 594 595 defp decode_type(extension, _, clause, dispatch, rest, acc, rem, full, rows) do 596 decode_extension(extension, clause, dispatch, rest, acc, rem, full, rows) 597 end 598 599 defp decode_null(extension, :super_binary, dispatch, rest, acc, rem, full, rows) do 600 decode_super_null(extension, dispatch, rest, acc, rem, full, rows) 601 end 602 603 defp decode_null(extension, _, dispatch, rest, acc, rem, full, rows) do 604 decode_extension_null(extension, dispatch, rest, acc, rem, full, rows) 605 end 606 607 defp decode_extension(extension, clause, dispatch, rest, acc, rem, full, rows) do 608 case split_extension(clause) do 609 {pattern, guard, body} -> 610 decode_extension(extension, pattern, guard, body, dispatch, rest, acc, rem, full, rows) 611 612 {pattern, body} -> 613 decode_extension(extension, pattern, body, dispatch, rest, acc, rem, full, rows) 614 end 615 end 616 617 defp decode_extension(extension, pattern, guard, body, dispatch, rest, acc, rem, full, rows) do 618 quote do 619 defp unquote(extension)( 620 <<unquote(pattern), unquote(rest)::binary>>, 621 types, 622 acc, 623 unquote(rem), 624 unquote(full), 625 unquote(rows) 626 ) 627 when unquote(guard) do 628 unquote(acc) = [unquote(body) | acc] 629 630 case types do 631 unquote(dispatch) 632 end 633 end 634 635 defp unquote(extension)(<<unquote(pattern), rest::binary>>, acc) 636 when unquote(guard) do 637 unquote(extension)(rest, [unquote(body) | acc]) 638 end 639 640 defp unquote(extension)(<<unquote(pattern), rest::binary>>, acc, callback) 641 when unquote(guard) do 642 unquote(extension)(rest, [unquote(body) | acc], callback) 643 end 644 645 defp unquote(extension)(<<unquote(pattern), rest::binary>>, oids, types, n, acc) 646 when unquote(guard) do 647 decode_tuple(rest, oids, types, n, [{n, unquote(body)} | acc]) 648 end 649 end 650 end 651 652 defp decode_extension(extension, pattern, body, dispatch, rest, acc, rem, full, rows) do 653 quote do 654 defp unquote(extension)( 655 <<unquote(pattern), unquote(rest)::binary>>, 656 types, 657 acc, 658 unquote(rem), 659 unquote(full), 660 unquote(rows) 661 ) do 662 unquote(acc) = [unquote(body) | acc] 663 664 case types do 665 unquote(dispatch) 666 end 667 end 668 669 defp unquote(extension)(<<unquote(pattern), rest::binary>>, acc) do 670 decoded = unquote(body) 671 unquote(extension)(rest, [decoded | acc]) 672 end 673 674 defp unquote(extension)(<<unquote(pattern), rest::binary>>, acc, callback) do 675 decoded = unquote(body) 676 unquote(extension)(rest, [decoded | acc], callback) 677 end 678 679 defp unquote(extension)(<<unquote(pattern), rest::binary>>, oids, types, n, acc) do 680 decode_tuple(rest, oids, types, n, [{n, unquote(body)} | acc]) 681 end 682 end 683 end 684 685 defp decode_extension_null(extension, dispatch, rest, acc, rem, full, rows) do 686 quote do 687 defp unquote(extension)( 688 <<-1::int32(), unquote(rest)::binary>>, 689 types, 690 acc, 691 unquote(rem), 692 unquote(full), 693 unquote(rows) 694 ) do 695 unquote(acc) = [@null | acc] 696 697 case types do 698 unquote(dispatch) 699 end 700 end 701 702 defp unquote(extension)(<<-1::int32(), rest::binary>>, acc) do 703 unquote(extension)(rest, [@null | acc]) 704 end 705 706 defp unquote(extension)(<<>>, acc) do 707 acc 708 end 709 710 defp unquote(extension)(<<-1::int32(), rest::binary>>, acc, callback) do 711 unquote(extension)(rest, [@null | acc], callback) 712 end 713 714 defp unquote(extension)(<<rest::binary-size(0)>>, acc, callback) do 715 callback.(rest, acc) 716 end 717 718 defp unquote(extension)(<<-1::int32(), rest::binary>>, oids, types, n, acc) do 719 decode_tuple(rest, oids, types, n, acc) 720 end 721 end 722 end 723 724 defp split_extension({:->, _, [head, body]}) do 725 case head do 726 [{:when, _, [pattern, guard]}] -> 727 {pattern, guard, body} 728 729 [pattern] -> 730 {pattern, body} 731 end 732 end 733 734 defp decode_super(extension, clause, dispatch, rest, acc, rem, full, rows) do 735 case split_super(clause) do 736 {pattern, oids, types, guard, body} -> 737 decode_super( 738 extension, 739 pattern, 740 oids, 741 types, 742 guard, 743 body, 744 dispatch, 745 rest, 746 acc, 747 rem, 748 full, 749 rows 750 ) 751 752 {pattern, oids, types, body} -> 753 decode_super(extension, pattern, oids, types, body, dispatch, rest, acc, rem, full, rows) 754 end 755 end 756 757 defp decode_super( 758 extension, 759 pattern, 760 sub_oids, 761 sub_types, 762 guard, 763 body, 764 dispatch, 765 rest, 766 acc, 767 rem, 768 full, 769 rows 770 ) do 771 quote do 772 defp unquote(extension)( 773 <<unquote(pattern), unquote(rest)::binary>>, 774 unquote(sub_oids), 775 unquote(sub_types), 776 types, 777 acc, 778 unquote(rem), 779 unquote(full), 780 unquote(rows) 781 ) 782 when unquote(guard) do 783 unquote(acc) = [unquote(body) | acc] 784 785 case types do 786 unquote(dispatch) 787 end 788 end 789 790 defp unquote(extension)( 791 <<unquote(pattern), rest::binary>>, 792 unquote(sub_oids), 793 unquote(sub_types), 794 acc 795 ) 796 when unquote(guard) do 797 acc = [unquote(body) | acc] 798 unquote(extension)(rest, unquote(sub_oids), unquote(sub_types), acc) 799 end 800 801 defp unquote(extension)( 802 <<unquote(pattern), rest::binary>>, 803 unquote(sub_oids), 804 unquote(sub_types), 805 oids, 806 types, 807 n, 808 acc 809 ) 810 when unquote(guard) do 811 decode_tuple(rest, oids, types, n, [{n, unquote(body)} | acc]) 812 end 813 end 814 end 815 816 defp decode_super( 817 extension, 818 pattern, 819 sub_oids, 820 sub_types, 821 body, 822 dispatch, 823 rest, 824 acc, 825 rem, 826 full, 827 rows 828 ) do 829 quote do 830 defp unquote(extension)( 831 <<unquote(pattern), unquote(rest)::binary>>, 832 unquote(sub_oids), 833 unquote(sub_types), 834 types, 835 acc, 836 unquote(rem), 837 unquote(full), 838 unquote(rows) 839 ) do 840 unquote(acc) = [unquote(body) | acc] 841 842 case types do 843 unquote(dispatch) 844 end 845 end 846 847 defp unquote(extension)( 848 <<unquote(pattern), rest::binary>>, 849 unquote(sub_oids), 850 unquote(sub_types), 851 acc 852 ) do 853 acc = [unquote(body) | acc] 854 unquote(extension)(rest, unquote(sub_oids), unquote(sub_types), acc) 855 end 856 857 defp unquote(extension)( 858 <<unquote(pattern), rest::binary>>, 859 unquote(sub_oids), 860 unquote(sub_types), 861 oids, 862 types, 863 n, 864 acc 865 ) do 866 acc = [{n, unquote(body)} | acc] 867 decode_tuple(rest, oids, types, n, acc) 868 end 869 end 870 end 871 872 defp decode_super_null(extension, dispatch, rest, acc, rem, full, rows) do 873 quote do 874 defp unquote(extension)( 875 <<-1::int32(), unquote(rest)::binary>>, 876 _sub_oids, 877 _sub_types, 878 types, 879 acc, 880 unquote(rem), 881 unquote(full), 882 unquote(rows) 883 ) do 884 unquote(acc) = [@null | acc] 885 886 case types do 887 unquote(dispatch) 888 end 889 end 890 891 defp unquote(extension)(<<-1::int32(), rest::binary>>, sub_oids, sub_types, acc) do 892 unquote(extension)(rest, sub_oids, sub_types, [@null | acc]) 893 end 894 895 defp unquote(extension)(<<>>, _sub_oid, _sub_types, acc) do 896 acc 897 end 898 899 defp unquote(extension)( 900 <<-1::int32(), rest::binary>>, 901 _sub_oids, 902 _sub_types, 903 oids, 904 types, 905 n, 906 acc 907 ) do 908 decode_tuple(rest, oids, types, n, acc) 909 end 910 end 911 end 912 913 defp split_super({:->, _, [head, body]}) do 914 case head do 915 [{:when, _, [pattern, sub_oids, sub_types, guard]}] -> 916 {pattern, sub_oids, sub_types, guard, body} 917 918 [pattern, sub_oids, sub_types] -> 919 {pattern, sub_oids, sub_types, body} 920 end 921 end 922 923 defp configure(extensions, opts) do 924 defaults = Postgrex.Utils.default_extensions(opts) 925 Enum.map(extensions ++ defaults, &configure/1) 926 end 927 928 defp configure({extension, opts}) do 929 state = extension.init(opts) 930 matching = extension.matching(state) 931 format = extension.format(state) 932 {extension, {state, matching, format}} 933 end 934 935 defp configure(extension) do 936 configure({extension, []}) 937 end 938 939 defp define_inline(module, config, opts) do 940 quoted = [ 941 directives(config, opts), 942 find(config), 943 encode(config, opts), 944 decode(config, opts) 945 ] 946 947 Module.create(module, quoted, Macro.Env.location(__ENV__)) 948 end 949 end