Browse Source

Merge pull request #66 from RJ/errcodes

add #error.codename field
David N. Welton 10 years ago
parent
commit
0b4eb1de01
7 changed files with 278 additions and 9 deletions
  1. 4 1
      Makefile
  2. 19 0
      generate_errcodes_src.sh
  3. 1 0
      include/epgsql.hrl
  4. 1 1
      src/epgsql.app.src
  5. 239 0
      src/epgsql_errcodes.erl
  6. 4 1
      src/epgsql_wire.erl
  7. 10 6
      test/epgsql_tests.erl

+ 4 - 1
Makefile

@@ -3,12 +3,15 @@ LASTVERSION = $(shell git rev-parse HEAD )
 
 all: compile
 
-compile:
+compile: src/epgsql_errcodes.erl
 	@$(REBAR) compile
 
 clean:
 	@$(REBAR) clean
 
+src/epgsql_errcodes.erl:
+	./generate_errcodes_src.sh > src/epgsql_errcodes.erl
+
 # The INSERT is used to make sure the schema_version matches the tests
 # being run.
 create_testdbs:

+ 19 - 0
generate_errcodes_src.sh

@@ -0,0 +1,19 @@
+#!/usr/bin/env bash -e
+#
+# Used to generate epgsql_errcodes.erl
+#
+ERRFILE="https://raw.github.com/postgres/postgres/master/src/backend/utils/errcodes.txt"
+echo "%% DO NOT EDIT - AUTOGENERATED ON $(date)"
+echo "-module(epgsql_errcodes)."
+echo "-export([to_name/1])."
+echo
+wget -qO- "$ERRFILE" | awk '
+NF == 4 && \
+$1 ~ /[^\s]{5}/ && \
+$2 ~ /[EWS]/ \
+{
+    printf("to_name(<<\"%s\">>) -> %s;\n", $1, $4)
+}
+END {
+    print "to_name(_) -> undefined."
+}'

+ 1 - 0
include/epgsql.hrl

@@ -17,6 +17,7 @@
 -record(error, {
     severity :: fatal | error | atom(), %TODO: concretize
     code :: binary(),
+    codename :: atom(),
     message :: binary(),
     extra :: [{detail, binary()} | {hint, binary()} | {position, binary()}]
 }).

+ 1 - 1
src/epgsql.app.src

@@ -1,6 +1,6 @@
 {application, epgsql,
  [{description, "PostgreSQL Client"},
-  {vsn, "3.1.0"},
+  {vsn, "3.2.0"},
   {modules, []},
   {registered, []},
   {applications, [kernel,

+ 239 - 0
src/epgsql_errcodes.erl

@@ -0,0 +1,239 @@
+%% DO NOT EDIT - AUTOGENERATED ON Mon  1 Jun 2015 14:42:37 BST
+-module(epgsql_errcodes).
+-export([to_name/1]).
+
+to_name(<<"00000">>) -> successful_completion;
+to_name(<<"01000">>) -> warning;
+to_name(<<"0100C">>) -> dynamic_result_sets_returned;
+to_name(<<"01008">>) -> implicit_zero_bit_padding;
+to_name(<<"01003">>) -> null_value_eliminated_in_set_function;
+to_name(<<"01007">>) -> privilege_not_granted;
+to_name(<<"01006">>) -> privilege_not_revoked;
+to_name(<<"01004">>) -> string_data_right_truncation;
+to_name(<<"01P01">>) -> deprecated_feature;
+to_name(<<"02000">>) -> no_data;
+to_name(<<"02001">>) -> no_additional_dynamic_result_sets_returned;
+to_name(<<"03000">>) -> sql_statement_not_yet_complete;
+to_name(<<"08000">>) -> connection_exception;
+to_name(<<"08003">>) -> connection_does_not_exist;
+to_name(<<"08006">>) -> connection_failure;
+to_name(<<"08001">>) -> sqlclient_unable_to_establish_sqlconnection;
+to_name(<<"08004">>) -> sqlserver_rejected_establishment_of_sqlconnection;
+to_name(<<"08007">>) -> transaction_resolution_unknown;
+to_name(<<"08P01">>) -> protocol_violation;
+to_name(<<"09000">>) -> triggered_action_exception;
+to_name(<<"0A000">>) -> feature_not_supported;
+to_name(<<"0B000">>) -> invalid_transaction_initiation;
+to_name(<<"0F000">>) -> locator_exception;
+to_name(<<"0F001">>) -> invalid_locator_specification;
+to_name(<<"0L000">>) -> invalid_grantor;
+to_name(<<"0LP01">>) -> invalid_grant_operation;
+to_name(<<"0P000">>) -> invalid_role_specification;
+to_name(<<"0Z000">>) -> diagnostics_exception;
+to_name(<<"0Z002">>) -> stacked_diagnostics_accessed_without_active_handler;
+to_name(<<"20000">>) -> case_not_found;
+to_name(<<"21000">>) -> cardinality_violation;
+to_name(<<"22000">>) -> data_exception;
+to_name(<<"2202E">>) -> array_subscript_error;
+to_name(<<"22021">>) -> character_not_in_repertoire;
+to_name(<<"22008">>) -> datetime_field_overflow;
+to_name(<<"22012">>) -> division_by_zero;
+to_name(<<"22005">>) -> error_in_assignment;
+to_name(<<"2200B">>) -> escape_character_conflict;
+to_name(<<"22022">>) -> indicator_overflow;
+to_name(<<"22015">>) -> interval_field_overflow;
+to_name(<<"2201E">>) -> invalid_argument_for_logarithm;
+to_name(<<"22014">>) -> invalid_argument_for_ntile_function;
+to_name(<<"22016">>) -> invalid_argument_for_nth_value_function;
+to_name(<<"2201F">>) -> invalid_argument_for_power_function;
+to_name(<<"2201G">>) -> invalid_argument_for_width_bucket_function;
+to_name(<<"22018">>) -> invalid_character_value_for_cast;
+to_name(<<"22007">>) -> invalid_datetime_format;
+to_name(<<"22019">>) -> invalid_escape_character;
+to_name(<<"2200D">>) -> invalid_escape_octet;
+to_name(<<"22025">>) -> invalid_escape_sequence;
+to_name(<<"22P06">>) -> nonstandard_use_of_escape_character;
+to_name(<<"22010">>) -> invalid_indicator_parameter_value;
+to_name(<<"22023">>) -> invalid_parameter_value;
+to_name(<<"2201B">>) -> invalid_regular_expression;
+to_name(<<"2201W">>) -> invalid_row_count_in_limit_clause;
+to_name(<<"2201X">>) -> invalid_row_count_in_result_offset_clause;
+to_name(<<"22009">>) -> invalid_time_zone_displacement_value;
+to_name(<<"2200C">>) -> invalid_use_of_escape_character;
+to_name(<<"2200G">>) -> most_specific_type_mismatch;
+to_name(<<"22004">>) -> null_value_not_allowed;
+to_name(<<"22002">>) -> null_value_no_indicator_parameter;
+to_name(<<"22003">>) -> numeric_value_out_of_range;
+to_name(<<"22026">>) -> string_data_length_mismatch;
+to_name(<<"22001">>) -> string_data_right_truncation;
+to_name(<<"22011">>) -> substring_error;
+to_name(<<"22027">>) -> trim_error;
+to_name(<<"22024">>) -> unterminated_c_string;
+to_name(<<"2200F">>) -> zero_length_character_string;
+to_name(<<"22P01">>) -> floating_point_exception;
+to_name(<<"22P02">>) -> invalid_text_representation;
+to_name(<<"22P03">>) -> invalid_binary_representation;
+to_name(<<"22P04">>) -> bad_copy_file_format;
+to_name(<<"22P05">>) -> untranslatable_character;
+to_name(<<"2200L">>) -> not_an_xml_document;
+to_name(<<"2200M">>) -> invalid_xml_document;
+to_name(<<"2200N">>) -> invalid_xml_content;
+to_name(<<"2200S">>) -> invalid_xml_comment;
+to_name(<<"2200T">>) -> invalid_xml_processing_instruction;
+to_name(<<"23000">>) -> integrity_constraint_violation;
+to_name(<<"23001">>) -> restrict_violation;
+to_name(<<"23502">>) -> not_null_violation;
+to_name(<<"23503">>) -> foreign_key_violation;
+to_name(<<"23505">>) -> unique_violation;
+to_name(<<"23514">>) -> check_violation;
+to_name(<<"23P01">>) -> exclusion_violation;
+to_name(<<"24000">>) -> invalid_cursor_state;
+to_name(<<"25000">>) -> invalid_transaction_state;
+to_name(<<"25001">>) -> active_sql_transaction;
+to_name(<<"25002">>) -> branch_transaction_already_active;
+to_name(<<"25008">>) -> held_cursor_requires_same_isolation_level;
+to_name(<<"25003">>) -> inappropriate_access_mode_for_branch_transaction;
+to_name(<<"25004">>) -> inappropriate_isolation_level_for_branch_transaction;
+to_name(<<"25005">>) -> no_active_sql_transaction_for_branch_transaction;
+to_name(<<"25006">>) -> read_only_sql_transaction;
+to_name(<<"25007">>) -> schema_and_data_statement_mixing_not_supported;
+to_name(<<"25P01">>) -> no_active_sql_transaction;
+to_name(<<"25P02">>) -> in_failed_sql_transaction;
+to_name(<<"26000">>) -> invalid_sql_statement_name;
+to_name(<<"27000">>) -> triggered_data_change_violation;
+to_name(<<"28000">>) -> invalid_authorization_specification;
+to_name(<<"28P01">>) -> invalid_password;
+to_name(<<"2B000">>) -> dependent_privilege_descriptors_still_exist;
+to_name(<<"2BP01">>) -> dependent_objects_still_exist;
+to_name(<<"2D000">>) -> invalid_transaction_termination;
+to_name(<<"2F000">>) -> sql_routine_exception;
+to_name(<<"2F005">>) -> function_executed_no_return_statement;
+to_name(<<"2F002">>) -> modifying_sql_data_not_permitted;
+to_name(<<"2F003">>) -> prohibited_sql_statement_attempted;
+to_name(<<"2F004">>) -> reading_sql_data_not_permitted;
+to_name(<<"34000">>) -> invalid_cursor_name;
+to_name(<<"38000">>) -> external_routine_exception;
+to_name(<<"38001">>) -> containing_sql_not_permitted;
+to_name(<<"38002">>) -> modifying_sql_data_not_permitted;
+to_name(<<"38003">>) -> prohibited_sql_statement_attempted;
+to_name(<<"38004">>) -> reading_sql_data_not_permitted;
+to_name(<<"39000">>) -> external_routine_invocation_exception;
+to_name(<<"39001">>) -> invalid_sqlstate_returned;
+to_name(<<"39004">>) -> null_value_not_allowed;
+to_name(<<"39P01">>) -> trigger_protocol_violated;
+to_name(<<"39P02">>) -> srf_protocol_violated;
+to_name(<<"39P03">>) -> event_trigger_protocol_violated;
+to_name(<<"3B000">>) -> savepoint_exception;
+to_name(<<"3B001">>) -> invalid_savepoint_specification;
+to_name(<<"3D000">>) -> invalid_catalog_name;
+to_name(<<"3F000">>) -> invalid_schema_name;
+to_name(<<"40000">>) -> transaction_rollback;
+to_name(<<"40002">>) -> transaction_integrity_constraint_violation;
+to_name(<<"40001">>) -> serialization_failure;
+to_name(<<"40003">>) -> statement_completion_unknown;
+to_name(<<"40P01">>) -> deadlock_detected;
+to_name(<<"42000">>) -> syntax_error_or_access_rule_violation;
+to_name(<<"42601">>) -> syntax_error;
+to_name(<<"42501">>) -> insufficient_privilege;
+to_name(<<"42846">>) -> cannot_coerce;
+to_name(<<"42803">>) -> grouping_error;
+to_name(<<"42P20">>) -> windowing_error;
+to_name(<<"42P19">>) -> invalid_recursion;
+to_name(<<"42830">>) -> invalid_foreign_key;
+to_name(<<"42602">>) -> invalid_name;
+to_name(<<"42622">>) -> name_too_long;
+to_name(<<"42939">>) -> reserved_name;
+to_name(<<"42804">>) -> datatype_mismatch;
+to_name(<<"42P18">>) -> indeterminate_datatype;
+to_name(<<"42P21">>) -> collation_mismatch;
+to_name(<<"42P22">>) -> indeterminate_collation;
+to_name(<<"42809">>) -> wrong_object_type;
+to_name(<<"42703">>) -> undefined_column;
+to_name(<<"42883">>) -> undefined_function;
+to_name(<<"42P01">>) -> undefined_table;
+to_name(<<"42P02">>) -> undefined_parameter;
+to_name(<<"42704">>) -> undefined_object;
+to_name(<<"42701">>) -> duplicate_column;
+to_name(<<"42P03">>) -> duplicate_cursor;
+to_name(<<"42P04">>) -> duplicate_database;
+to_name(<<"42723">>) -> duplicate_function;
+to_name(<<"42P05">>) -> duplicate_prepared_statement;
+to_name(<<"42P06">>) -> duplicate_schema;
+to_name(<<"42P07">>) -> duplicate_table;
+to_name(<<"42712">>) -> duplicate_alias;
+to_name(<<"42710">>) -> duplicate_object;
+to_name(<<"42702">>) -> ambiguous_column;
+to_name(<<"42725">>) -> ambiguous_function;
+to_name(<<"42P08">>) -> ambiguous_parameter;
+to_name(<<"42P09">>) -> ambiguous_alias;
+to_name(<<"42P10">>) -> invalid_column_reference;
+to_name(<<"42611">>) -> invalid_column_definition;
+to_name(<<"42P11">>) -> invalid_cursor_definition;
+to_name(<<"42P12">>) -> invalid_database_definition;
+to_name(<<"42P13">>) -> invalid_function_definition;
+to_name(<<"42P14">>) -> invalid_prepared_statement_definition;
+to_name(<<"42P15">>) -> invalid_schema_definition;
+to_name(<<"42P16">>) -> invalid_table_definition;
+to_name(<<"42P17">>) -> invalid_object_definition;
+to_name(<<"44000">>) -> with_check_option_violation;
+to_name(<<"53000">>) -> insufficient_resources;
+to_name(<<"53100">>) -> disk_full;
+to_name(<<"53200">>) -> out_of_memory;
+to_name(<<"53300">>) -> too_many_connections;
+to_name(<<"53400">>) -> configuration_limit_exceeded;
+to_name(<<"54000">>) -> program_limit_exceeded;
+to_name(<<"54001">>) -> statement_too_complex;
+to_name(<<"54011">>) -> too_many_columns;
+to_name(<<"54023">>) -> too_many_arguments;
+to_name(<<"55000">>) -> object_not_in_prerequisite_state;
+to_name(<<"55006">>) -> object_in_use;
+to_name(<<"55P02">>) -> cant_change_runtime_param;
+to_name(<<"55P03">>) -> lock_not_available;
+to_name(<<"57000">>) -> operator_intervention;
+to_name(<<"57014">>) -> query_canceled;
+to_name(<<"57P01">>) -> admin_shutdown;
+to_name(<<"57P02">>) -> crash_shutdown;
+to_name(<<"57P03">>) -> cannot_connect_now;
+to_name(<<"57P04">>) -> database_dropped;
+to_name(<<"58000">>) -> system_error;
+to_name(<<"58030">>) -> io_error;
+to_name(<<"58P01">>) -> undefined_file;
+to_name(<<"58P02">>) -> duplicate_file;
+to_name(<<"F0000">>) -> config_file_error;
+to_name(<<"F0001">>) -> lock_file_exists;
+to_name(<<"HV000">>) -> fdw_error;
+to_name(<<"HV005">>) -> fdw_column_name_not_found;
+to_name(<<"HV002">>) -> fdw_dynamic_parameter_value_needed;
+to_name(<<"HV010">>) -> fdw_function_sequence_error;
+to_name(<<"HV021">>) -> fdw_inconsistent_descriptor_information;
+to_name(<<"HV024">>) -> fdw_invalid_attribute_value;
+to_name(<<"HV007">>) -> fdw_invalid_column_name;
+to_name(<<"HV008">>) -> fdw_invalid_column_number;
+to_name(<<"HV004">>) -> fdw_invalid_data_type;
+to_name(<<"HV006">>) -> fdw_invalid_data_type_descriptors;
+to_name(<<"HV091">>) -> fdw_invalid_descriptor_field_identifier;
+to_name(<<"HV00B">>) -> fdw_invalid_handle;
+to_name(<<"HV00C">>) -> fdw_invalid_option_index;
+to_name(<<"HV00D">>) -> fdw_invalid_option_name;
+to_name(<<"HV090">>) -> fdw_invalid_string_length_or_buffer_length;
+to_name(<<"HV00A">>) -> fdw_invalid_string_format;
+to_name(<<"HV009">>) -> fdw_invalid_use_of_null_pointer;
+to_name(<<"HV014">>) -> fdw_too_many_handles;
+to_name(<<"HV001">>) -> fdw_out_of_memory;
+to_name(<<"HV00P">>) -> fdw_no_schemas;
+to_name(<<"HV00J">>) -> fdw_option_name_not_found;
+to_name(<<"HV00K">>) -> fdw_reply_handle;
+to_name(<<"HV00Q">>) -> fdw_schema_not_found;
+to_name(<<"HV00R">>) -> fdw_table_not_found;
+to_name(<<"HV00L">>) -> fdw_unable_to_create_execution;
+to_name(<<"HV00M">>) -> fdw_unable_to_create_reply;
+to_name(<<"HV00N">>) -> fdw_unable_to_establish_connection;
+to_name(<<"P0000">>) -> plpgsql_error;
+to_name(<<"P0001">>) -> raise_exception;
+to_name(<<"P0002">>) -> no_data_found;
+to_name(<<"P0003">>) -> too_many_rows;
+to_name(<<"P0004">>) -> assert_failure;
+to_name(<<"XX000">>) -> internal_error;
+to_name(<<"XX001">>) -> data_corrupted;
+to_name(<<"XX002">>) -> index_corrupted;
+to_name(_) -> undefined.

+ 4 - 1
src/epgsql_wire.erl

@@ -59,9 +59,12 @@ decode_fields(<<Type:8, Rest/binary>>, Acc) ->
 %% TODO add fields from http://www.postgresql.org/docs/9.0/interactive/protocol-error-fields.html
 decode_error(Bin) ->
     Fields = decode_fields(Bin),
+    ErrCode = proplists:get_value($C, Fields),
+    ErrName = epgsql_errcodes:to_name(ErrCode),
     Error = #error{
       severity = lower_atom(proplists:get_value($S, Fields)),
-      code     = proplists:get_value($C, Fields),
+      code     = ErrCode,
+      codename = ErrName,
       message  = proplists:get_value($M, Fields),
       extra    = decode_error_extra(Fields)},
     Error.

+ 10 - 6
test/epgsql_tests.erl

@@ -21,9 +21,13 @@
 -define(UUID3,
         <<198,188,155,66,149,151,17,227,138,98,112,24,139,130,16,73>>).
 
--define(TIMEOUT_ERROR,
-        {error,{error,error,<<"57014">>,
-                <<"canceling statement due to statement timeout">>,[]}}).
+-define(TIMEOUT_ERROR, {error, #error{
+        severity = error,
+        code = <<"57014">>,
+        codename = query_canceled,
+        message = <<"canceling statement due to statement timeout">>,
+        extra = []
+        }}).
 
 %% From uuid.erl in http://gitorious.org/avtobiff/erlang-uuid
 uuid_to_string(<<U0:32, U1:16, U2:16, U3:16, U4:48>>) ->
@@ -288,7 +292,7 @@ parse_and_close_test(Module) ->
       fun(C) ->
               Parse = fun() -> Module:parse(C, "test", "select * from test_table1", []) end,
               {ok, S} = Parse(),
-              {error, #error{code = <<"42P05">>}} = Parse(),
+              {error, #error{code = <<"42P05">>, codename = duplicate_prepared_statement}} = Parse(),
               Module:close(C, S),
               {ok, S} = Parse(),
               ok = Module:sync(C)
@@ -333,7 +337,7 @@ bind_and_close_test(Module) ->
       fun(C) ->
               {ok, S} = Module:parse(C, "select * from test_table1"),
               ok = Module:bind(C, S, "one", []),
-              {error, #error{code = <<"42P03">>}} = Module:bind(C, S, "one", []),
+              {error, #error{code = <<"42P03">>, codename = duplicate_cursor}} = Module:bind(C, S, "one", []),
               ok = Module:close(C, portal, "one"),
               ok = Module:bind(C, S, "one", []),
               ok = Module:sync(C)
@@ -345,7 +349,7 @@ execute_error_test(Module) ->
       fun(C) ->
           {ok, S} = Module:parse(C, "insert into test_table1 (id, value) values ($1, $2)"),
           ok = Module:bind(C, S, [1, <<"foo">>]),
-          {error, #error{code = <<"23505">>}} = Module:execute(C, S, 0),
+          {error, #error{code = <<"23505">>, codename = unique_violation}} = Module:execute(C, S, 0),
           {error, sync_required} = Module:bind(C, S, [3, <<"quux">>]),
           ok = Module:sync(C),
           ok = Module:bind(C, S, [3, <<"quux">>]),