jakajancar / pgc4d

A full-featured PostgreSQL Client for Deno
MIT License
21 stars 3 forks source link

Query remains pending when constraint violated #8

Closed MichaelTheriot closed 3 years ago

MichaelTheriot commented 3 years ago

Version: PostgreSQL 13.0, compiled by Visual C++ build 1914, 64-bit

The promise for conn.query never rejects or resolves when a constraint is violated. (same for prepared statements)

E.g.:

await conn.query('DROP TABLE IF EXISTS users');
await conn.query(`CREATE TABLE users (id BIGINT PRIMARY KEY, name VARCHAR(32) NOT NULL)`);

await conn.query("INSERT INTO users (id, name) VALUES (0, 'John')");
console.log('added John');

await conn.query("INSERT INTO users (id, name) VALUES (1, 'Bob')");
console.log('added Bob');

await conn.query("INSERT INTO users (id, name) VALUES (1, 'Jake')"); // violates primary key
console.log('added Jake'); // this never prints

Output:

added John
added Bob

DB:

# select * from users;
 id | name
----+------
  0 | John
  1 | Bob
(2 rows)

I just noticed the date of this library and the date of PostgreSQL 13.0; will try on a lower version.

MichaelTheriot commented 3 years ago

Seeing the same behavior on 12.4 and 11.9.

DB parameters...

allow_system_table_mods             | off
application_name                    | psql
archive_command                     | (disabled)
archive_mode                        | off
archive_timeout                     | 0
array_nulls                         | on
authentication_timeout              | 1min
autovacuum                          | on
autovacuum_analyze_scale_factor     | 0.1
autovacuum_analyze_threshold        | 50
autovacuum_freeze_max_age           | 200000000
autovacuum_max_workers              | 3
autovacuum_multixact_freeze_max_age | 400000000
autovacuum_naptime                  | 1min
autovacuum_vacuum_cost_delay        | 20ms
autovacuum_vacuum_cost_limit        | -1
autovacuum_vacuum_scale_factor      | 0.2
autovacuum_vacuum_threshold         | 50
autovacuum_work_mem                 | -1
backend_flush_after                 | 0
backslash_quote                     | safe_encoding
bgwriter_delay                      | 200ms
bgwriter_flush_after                | 0
bgwriter_lru_maxpages               | 100
bgwriter_lru_multiplier             | 2
block_size                          | 8192
bonjour                             | off
bonjour_name                        |
bytea_output                        | hex
check_function_bodies               | on
checkpoint_completion_target        | 0.5
checkpoint_flush_after              | 0
checkpoint_timeout                  | 5min
checkpoint_warning                  | 30s
client_encoding                     | UTF8
client_min_messages                 | notice
cluster_name                        |
commit_delay                        | 0
commit_siblings                     | 5
constraint_exclusion                | partition
cpu_index_tuple_cost                | 0.005
cpu_operator_cost                   | 0.0025
cpu_tuple_cost                      | 0.01
cursor_tuple_fraction               | 0.1
data_checksums                      | off
data_directory_mode                 | 0700
data_sync_retry                     | off
DateStyle                           | ISO, MDY
db_user_namespace                   | off
deadlock_timeout                    | 1s
debug_assertions                    | off
debug_pretty_print                  | on
debug_print_parse                   | off
debug_print_plan                    | off
debug_print_rewritten               | off
default_statistics_target           | 100
default_tablespace                  |
default_text_search_config          | pg_catalog.english
default_transaction_deferrable      | off
default_transaction_isolation       | read committed
default_transaction_read_only       | off
default_with_oids                   | off
dynamic_library_path                | $libdir
dynamic_shared_memory_type          | windows
effective_cache_size                | 4GB
effective_io_concurrency            | 0
enable_bitmapscan                   | on
enable_gathermerge                  | on
enable_hashagg                      | on
enable_hashjoin                     | on
enable_indexonlyscan                | on
enable_indexscan                    | on
enable_material                     | on
enable_mergejoin                    | on
enable_nestloop                     | on
enable_parallel_append              | on
enable_parallel_hash                | on
enable_partition_pruning            | on
enable_partitionwise_aggregate      | off
enable_partitionwise_join           | off
enable_seqscan                      | on
enable_sort                         | on
enable_tidscan                      | on
escape_string_warning               | on
event_source                        | PostgreSQL
exit_on_error                       | off
external_pid_file                   |
extra_float_digits                  | 0
force_parallel_mode                 | off
from_collapse_limit                 | 8
fsync                               | on
full_page_writes                    | on
geqo                                | on
geqo_effort                         | 5
geqo_generations                    | 0
geqo_pool_size                      | 0
geqo_seed                           | 0
geqo_selection_bias                 | 2
geqo_threshold                      | 12
gin_fuzzy_search_limit              | 0
gin_pending_list_limit              | 4MB
hot_standby                         | on
hot_standby_feedback                | off
huge_pages                          | try
idle_in_transaction_session_timeout | 0
ignore_checksum_failure             | off
ignore_system_indexes               | off
integer_datetimes                   | on
IntervalStyle                       | postgres
jit                                 | off
jit_above_cost                      | 100000
jit_debugging_support               | off
jit_dump_bitcode                    | off
jit_expressions                     | on
jit_inline_above_cost               | 500000
jit_optimize_above_cost             | 500000
jit_profiling_support               | off
jit_provider                        | llvmjit
jit_tuple_deforming                 | on
join_collapse_limit                 | 8
krb_caseins_users                   | off
krb_server_keyfile                  |
lc_collate                          | English_United States.1252
lc_ctype                            | English_United States.1252
lc_messages                         | English_United States.1252
lc_monetary                         | English_United States.1252
lc_numeric                          | English_United States.1252
lc_time                             | English_United States.1252
listen_addresses                    | localhost
lo_compat_privileges                | off
local_preload_libraries             |
lock_timeout                        | 0
log_autovacuum_min_duration         | -1
log_checkpoints                     | off
log_connections                     | off
log_destination                     | stderr
log_directory                       | log
log_disconnections                  | off
log_duration                        | off
log_error_verbosity                 | default
log_executor_stats                  | off
log_file_mode                       | 0640
log_filename                        | postgresql-%Y-%m-%d_%H%M%S.log
log_hostname                        | off
log_line_prefix                     | %m [%p]
log_lock_waits                      | off
log_min_duration_statement          | -1
log_min_error_statement             | error
log_min_messages                    | warning
log_parser_stats                    | off
log_planner_stats                   | off
log_replication_commands            | off
log_rotation_age                    | 1d
log_rotation_size                   | 10MB
log_statement                       | none
log_statement_stats                 | off
log_temp_files                      | -1
log_timezone                        | US/Central
log_truncate_on_rotation            | off
logging_collector                   | off
maintenance_work_mem                | 64MB
max_connections                     | 100
max_files_per_process               | 1000
max_function_args                   | 100
max_identifier_length               | 63
max_index_keys                      | 32
max_locks_per_transaction           | 64
max_logical_replication_workers     | 4
max_parallel_maintenance_workers    | 2
max_parallel_workers                | 8
max_parallel_workers_per_gather     | 2
max_pred_locks_per_page             | 2
max_pred_locks_per_relation         | -2
max_pred_locks_per_transaction      | 64
max_prepared_transactions           | 0
max_replication_slots               | 10
max_stack_depth                     | 2MB
max_standby_archive_delay           | 30s
max_standby_streaming_delay         | 30s
max_sync_workers_per_subscription   | 2
max_wal_senders                     | 10
max_wal_size                        | 1GB
max_worker_processes                | 8
min_parallel_index_scan_size        | 512kB
min_parallel_table_scan_size        | 8MB
min_wal_size                        | 80MB
old_snapshot_threshold              | -1
operator_precedence_warning         | off
parallel_leader_participation       | on
parallel_setup_cost                 | 1000
parallel_tuple_cost                 | 0.1
password_encryption                 | md5
port                                | 5432
post_auth_delay                     | 0
pre_auth_delay                      | 0
quote_all_identifiers               | off
random_page_cost                    | 4
restart_after_crash                 | on
row_security                        | on
search_path                         | "$user", public
segment_size                        | 1GB
seq_page_cost                       | 1
server_encoding                     | UTF8
server_version                      | 11.9
server_version_num                  | 110009
session_preload_libraries           |
session_replication_role            | origin
shared_buffers                      | 128MB
shared_preload_libraries            |
ssl                                 | off
ssl_ca_file                         |
ssl_cert_file                       | server.crt
ssl_ciphers                         | HIGH:MEDIUM:+3DES:!aNULL
ssl_crl_file                        |
ssl_dh_params_file                  |
ssl_ecdh_curve                      | prime256v1
ssl_key_file                        | server.key
ssl_passphrase_command              |
ssl_passphrase_command_supports_reload | off
ssl_prefer_server_ciphers           | on
standard_conforming_strings         | on
statement_timeout                   | 0
stats_temp_directory                | pg_stat_tmp
superuser_reserved_connections      | 3
synchronize_seqscans                | on
synchronous_commit                  | on
synchronous_standby_names           |
syslog_facility                     | none
syslog_ident                        | postgres
syslog_sequence_numbers             | on
syslog_split_messages               | on
tcp_keepalives_count                | 0
tcp_keepalives_idle                 | -1
tcp_keepalives_interval             | -1
temp_buffers                        | 8MB
temp_file_limit                     | -1
temp_tablespaces                    |
TimeZone                            | US/Central
timezone_abbreviations              | Default
trace_notify                        | off
trace_recovery_messages             | log
trace_sort                          | off
track_activities                    | on
track_activity_query_size           | 1kB
track_commit_timestamp              | off
track_counts                        | on
track_functions                     | none
track_io_timing                     | off
transaction_deferrable              | off
transaction_isolation               | read committed
transaction_read_only               | off
transform_null_equals               | off
unix_socket_directories             |
unix_socket_group                   |
unix_socket_permissions             | 0777
update_process_title                | off
vacuum_cleanup_index_scale_factor   | 0.1
vacuum_cost_delay                   | 0
vacuum_cost_limit                   | 200
vacuum_cost_page_dirty              | 20
vacuum_cost_page_hit                | 1
vacuum_cost_page_miss               | 10
vacuum_defer_cleanup_age            | 0
vacuum_freeze_min_age               | 50000000
vacuum_freeze_table_age             | 150000000
vacuum_multixact_freeze_min_age     | 5000000
vacuum_multixact_freeze_table_age   | 150000000
wal_block_size                      | 8192
wal_buffers                         | 4MB
wal_compression                     | off
wal_consistency_checking            |
wal_keep_segments                   | 0
wal_level                           | replica
wal_log_hints                       | off
wal_receiver_status_interval        | 10s
wal_receiver_timeout                | 1min
wal_retrieve_retry_interval         | 5s
wal_segment_size                    | 16MB
wal_sender_timeout                  | 1min
wal_sync_method                     | open_datasync
wal_writer_delay                    | 200ms
wal_writer_flush_after              | 1MB
work_mem                            | 4MB
xmlbinary                           | base64
xmloption                           | content
zero_damaged_pages                  | off
MichaelTheriot commented 3 years ago

I traced down the issue to this line:

https://github.com/jakajancar/pgc4d/blob/90232ceef7a5f697e8c95e94368cc8c41c26b8ff/src/prepared_statement.ts#L86

The error is correctly thrown in the try block, but in the finally block a new read is performed regardless if an error occurred. Expectedly, the request stalls waiting for 'CommandComplete' and the error does not bubble up.

jakajancar commented 3 years ago

Thank you Michael!