Coleccion de cositas para el .psqlrc

--------------------------------------------------
-- 20200115 DAF agrego funcionalidades
-- 20200108 DAF .psqlrc  Version inicial
--------------------------------------------------


-- Para que no muestre el output de los siquientes comandos
\set QUIET ON


-- Prompts
-- Prompt1 / Prompt2 / Prompt3
-- %M : server
-- %m : host name
-- %> : port
-- %n : user
-- %/ : current database
-- %~ : like %/ but ~ for default database
-- %# : '#' if superuser, '>' otherwise
-- %R
-- %x
-- %[...%] : terminal control characters
-- Examples

\set PROMPT1 'u: %n db: %/ %# '
\set PROMPT2 '%# '
\set PROMPT3 ''


\timing on

-- Pone en mayusculas las palabras autocompletadas
\set COMP_KEYWORD_CASE upper

--tipo de lineas, unicode, ascii etc
--\pset linestype ascii

-- Borde de la tabla de resultados
\pset border 0

-- unicode_border_linestyle: border drawing style for unicode style.
-- Values: single, double.
\pset unicode_border_linestyle single

-- unicode_column_linestyle: column drawing style for unicode style.
-- Values: single, double.
\pset unicode_column_linestyle single

-- unicode_header_linestyle: header drawing style for unicode style.
-- Values: single, double.
\pset unicode_header_linestyle single


-- columns: target width for wrapped format
-- Values: number
\pset columns 0

-- expanded: extended display
-- Values: auto, on, off
\x off


-- fieldsep_zero: set field separator to a zero byte.
--Values: no value.
--\pset fieldsep_zero 


-- fieldsep_zero: set field separator to a zero byte.
--Values: no value.
--\pset fieldsep_zero

-- recordsep_zero: set the line separator in unaligned output format to
-- zero byte.
-- Values: no values.
--\pset recordsep_zero

-- tableattr: attributes in the table tag for HTML format.
-- Values: string. Without value, will unset attributes.
--\pset tableattr TODO

-- title: table title for printed tables.
-- Values: string. Without value, title is unset.

-- tuples_only: can also be abreviated with \t
-- Values: on, off. Without value, will toggle.
\pset tuples_only off


-- Para que no pagine
\pset pager off

-- Como va a imprimir los NULOS
\pset null '[null]'

-- Nombre del archivo history
\set HISTFILE ~/scripts/psqlhists/psql_history- :HOST - :PORT - :DBNAME - :USER

-- Cantidad de comandos en el history
\set HISTSIZE 5000

-- Sin duplicados
\set HISTCONTROL ignoredups

-- Nivel de debug
\set VERBOSITY verbose
\errverbose

-- como el @echo off para imprimir algun mensaje
\set ECHO_HIDDEN ON

\set QUIET OFF

\echo '\nCurrent Host Server Date Time : '`date` '\n'

\echo '\t:activity                 :cache_hit              :nspsize                  :tablesize1'
\echo '\t:activity1                :conninfo               :nspsize_pgs              :total_index_size'
\echo '\t:activity2                :dbsize                 :ps                       :unused_indexes'
\echo '\t:activity96               :idletxn                :queries                  :uptime'
\echo '\t:activitytho              :index_size             :seq_scans                :uselesscol'
\echo '\t:                         :index_usage            :settings                 :vacuuminfo'
\echo '\t:autovacs                 :index_usage_adv        :show_slow_queries        :waits'
\echo '\t:backends                 :kill_old_transactions  :spcsize                  :wrapstats'
\echo '\t:bloat                    :locks                  :statrelfilepath          :wrapstats_raw'
\echo '\t:bloat2                   :locks1                 :statrelfilepath_agg      :wrapstats_rels'
\echo '\t:blocking                 :long_running_queries   :statrelspcfilepath_agg   :wrapstats_spc'
\echo '\t:buffer_cache_hit_ratio   :missing_indexes        :tablesize'                

\echo '\n\t:menu -- Help Menu'
\echo '\t\h-- Help with SQL commands'
\echo '\t\?-- Help with psql commands'

\echo '\nDevelopment queries:\n'
\echo '\t:sp-- Current Search Path'
\echo '\t:clear -- Clear screen'
\echo '\t:ll -- List\n'


\set sp 'SHOW search_path;'
\set clear '\\! clear;'
\set ll '\\! ls -lrt'

\set uptime 'select now() - pg_postmaster_start_time() AS uptime;'


\set menu '\\i ~/.psqlrc'



-- buffer cache hit ratio
\set buffer_cache_hit_ratio 'select datname, blks_hit::float/(blks_hit+blks_read) as hit_ratio from pg_stat_database where blks_read+blks_hit <> 0;'
\set cache_hit 'SELECT ''index hit rate'' AS name, (sum(idx_blks_hit)) / sum(idx_blks_hit + idx_blks_read) AS ratio FROM pg_statio_user_indexes UNION ALL SELECT ''cache hit rate'' AS name,       sum(heap_blks_hit) / (sum(heap_blks_hit) + sum(heap_blks_read)) AS ratio FROM pg_statio_user_tables;'

-- kill transactions that have been "idle in transaction" for more than 10 minutes
\set kill_old_transactions 'select count(pg_terminate_backend(pid)) as nb_killed_proc from pg_stat_activity where query = \' in transaction\' and current_timestamp - query_start > \'10 min\';'

-- running queries
\set queries  'select current_timestamp - query_start as runtime,pid,datname,usename,query from pg_stat_activity where query != \'\' order by 1 desc; '



\set autovacs 'WITH q0_0 AS  (SELECT relid,          CASE              WHEN coalesce(last_vacuum, last_analyze, last_autovacuum, last_autoanalyze) IS NULL THEN NULL              WHEN last_vacuum =                     (SELECT MAX(UNNEST)                      FROM                        (SELECT UNNEST(ARRAY[last_vacuum,                                             last_analyze,                                             last_autovacuum,                                             last_autoanalyze]))s0_0) THEN '' v ''              WHEN last_analyze =                     (SELECT MAX(UNNEST)                      FROM                        (SELECT UNNEST(ARRAY[last_vacuum,                                             last_analyze,                                             last_autovacuum,                                             last_autoanalyze]))s1_0) THEN '' z ''              WHEN last_autoanalyze =                     (SELECT MAX(UNNEST)                      FROM                        (SELECT UNNEST(ARRAY[last_vacuum,                                             last_analyze,                                             last_autovacuum,                                             last_autoanalyze]))s2_0) THEN ''az ''              WHEN last_autovacuum =                     (SELECT MAX(UNNEST)                      FROM                        (SELECT UNNEST(ARRAY[last_vacuum,                                             last_analyze,                                             last_autovacuum,                                             last_autoanalyze]))s3_0) THEN ''av ''          END AS last_stats_str,          CASE              WHEN coalesce(last_vacuum, last_analyze, last_autovacuum, last_autoanalyze) IS NULL THEN NULL              WHEN last_vacuum =                     (SELECT MAX(UNNEST)                      FROM                        (SELECT UNNEST(ARRAY[last_vacuum,                                             last_analyze,                                             last_autovacuum,                                             last_autoanalyze]))s0_0) THEN last_vacuum::TIMESTAMP              WHEN last_analyze =                     (SELECT MAX(UNNEST)                      FROM                        (SELECT UNNEST(ARRAY[last_vacuum,                                             last_analyze,                                             last_autovacuum,                                             last_autoanalyze]))s1_0) THEN last_analyze::TIMESTAMP              WHEN last_autoanalyze =                     (SELECT MAX(UNNEST)                      FROM                        (SELECT UNNEST(ARRAY[last_vacuum,                                             last_analyze,                                             last_autovacuum,                                             last_autoanalyze]))s2_0) THEN last_autoanalyze::TIMESTAMP              WHEN last_autovacuum =                     (SELECT MAX(UNNEST)                      FROM                        (SELECT UNNEST(ARRAY[last_vacuum,                                             last_analyze,                                             last_autovacuum,                                             last_autoanalyze]))s3_0) THEN last_autovacuum::TIMESTAMP          END AS last_stats_stamp   FROM pg_stat_user_tables),     q0 AS  (SELECT relid::regclass rel,          n_tup_ins ti,          n_tup_upd + n_tup_del tm,          n_live_tup tliv,          n_dead_tup nded,          n_mod_since_analyze tmod,          last_stats_str||last_stats_stamp AS last_stats,          autoanalyze_count naz,          autovacuum_count nav,          analyze_count nz,          vacuum_count nv   FROM pg_stat_user_tables   JOIN q0_0 USING (relid)   ORDER BY last_stats_stamp DESC nulls LAST,                                        schemaname,                                        relname)SELECT * FROM q0 ;'

\set bloat2 'SELECT tablename AS TABLE_NAME,       ROUND(CASE WHEN otta=0 THEN 0.0 ELSE sml.relpages/otta::numeric END,1) AS table_bloat,       CASE           WHEN relpages < otta THEN ''0''           ELSE pg_size_pretty((bs*(sml.relpages-otta)::bigint)::bigint)       END AS table_waste,       iname AS index_name,       ROUND(CASE WHEN iotta=0             OR ipages=0 THEN 0.0 ELSE ipages/iotta::numeric END,1) AS index_bloat,       CASE           WHEN ipages < iotta THEN ''0''           ELSE pg_size_pretty((bs*(ipages-iotta))::bigint)       END AS index_waste FROM  (SELECT schemaname,          tablename,          cc.reltuples,          cc.relpages,          bs,          CEIL((cc.reltuples*((datahdr+ma- (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)) AS otta,          COALESCE(c2.relname,''?'') AS iname,          COALESCE(c2.reltuples,0) AS ituples,          COALESCE(c2.relpages,0) AS ipages,          COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta   FROM     (SELECT ma,             bs,             schemaname,             tablename,             (datawidth+(hdr+ma-(CASE WHEN hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr,             (maxfracsum*(nullhdr+ma-(CASE WHEN nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2      FROM        (SELECT schemaname,                tablename,                hdr,                ma,                bs,                SUM((1-null_frac)*avg_width) AS datawidth,                MAX(null_frac) AS maxfracsum,                hdr+           (SELECT 1+count(*)/8            FROM pg_stats s2            WHERE null_frac<>0              AND s2.schemaname = s.schemaname              AND s2.tablename = s.tablename) AS nullhdr         FROM pg_stats s,           (SELECT              (SELECT current_setting(''block_size'')::numeric) AS bs,                   CASE WHEN substring(v,12,3) IN (''8.0'',                                                   ''8.1'',                                                   ''8.2'') THEN 27 ELSE 23 END AS hdr,                                                                                 CASE WHEN v ~ ''mingw32'' THEN 8 ELSE 4 END AS ma            FROM              (SELECT version() AS v) AS foo) AS constants         GROUP BY 1,                  2,                  3,                  4,                  5) AS foo) AS rs   JOIN pg_class cc ON cc.relname = rs.tablename   JOIN pg_namespace nn ON cc.relnamespace = nn.oid   AND nn.nspname = rs.schemaname   AND nn.nspname <> ''information_schema''   LEFT JOIN pg_index i ON indrelid = cc.oid   LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid) AS sml ORDER BY CASE             WHEN relpages < otta THEN 0             ELSE bs*(sml.relpages-otta)::bigint         END DESC;'

\set bloat 'SELECT tablename AS TABLE_NAME,       ROUND(CASE WHEN otta=0 THEN 0.0 ELSE sml.relpages/otta::numeric END,1) AS table_bloat,       CASE           WHEN relpages < otta THEN ''0''           ELSE pg_size_pretty((bs*(sml.relpages-otta)::bigint)::bigint)       END AS table_waste,       iname AS index_name,       ROUND(CASE WHEN iotta=0             OR ipages=0 THEN 0.0 ELSE ipages/iotta::numeric END,1) AS index_bloat,       CASE           WHEN ipages < iotta THEN ''0''           ELSE pg_size_pretty((bs*(ipages-iotta))::bigint)       END AS index_waste FROM  (SELECT schemaname,          tablename,          cc.reltuples,          cc.relpages,          bs,          CEIL((cc.reltuples*((datahdr+ma- (CASE WHEN datahdr%ma=0 THEN ma ELSE datahdr%ma END))+nullhdr2+4))/(bs-20::float)) AS otta,          COALESCE(c2.relname,''?'') AS iname,          COALESCE(c2.reltuples,0) AS ituples,          COALESCE(c2.relpages,0) AS ipages,          COALESCE(CEIL((c2.reltuples*(datahdr-12))/(bs-20::float)),0) AS iotta   FROM     (SELECT ma,             bs,             schemaname,             tablename,             (datawidth+(hdr+ma-(CASE WHEN hdr%ma=0 THEN ma ELSE hdr%ma END)))::numeric AS datahdr,             (maxfracsum*(nullhdr+ma-(CASE WHEN nullhdr%ma=0 THEN ma ELSE nullhdr%ma END))) AS nullhdr2      FROM        (SELECT schemaname,                tablename,                hdr,                ma,                bs,                SUM((1-null_frac)*avg_width) AS datawidth,                MAX(null_frac) AS maxfracsum,                hdr+           (SELECT 1+count(*)/8            FROM pg_stats s2            WHERE null_frac<>0              AND s2.schemaname = s.schemaname              AND s2.tablename = s.tablename) AS nullhdr         FROM pg_stats s,           (SELECT              (SELECT current_setting(''block_size'')::numeric) AS bs,                   CASE WHEN substring(v,12,3) IN (''8.0'',                                                   ''8.1'',                                                   ''8.2'') THEN 27 ELSE 23 END AS hdr,                                                                                 CASE WHEN v ~ ''mingw32'' THEN 8 ELSE 4 END AS ma            FROM              (SELECT version() AS v) AS foo) AS constants         GROUP BY 1,                  2,                  3,                  4,                  5) AS foo) AS rs   JOIN pg_class cc ON cc.relname = rs.tablename   JOIN pg_namespace nn ON cc.relnamespace = nn.oid   AND nn.nspname = rs.schemaname   AND nn.nspname <> ''information_schema''   LEFT JOIN pg_index i ON indrelid = cc.oid   LEFT JOIN pg_class c2 ON c2.oid = i.indexrelid) AS sml ORDER BY CASE             WHEN relpages < otta THEN 0             ELSE bs*(sml.relpages-otta)::bigint         END DESC;'

\set blocking 'SELECT bl.pid AS blocked_pid,       ka.query AS blocking_statement,       now() - ka.query_start AS blocking_duration,       kl.pid AS blocking_pid,       a.query AS blocked_statement,       now() - a.query_start AS blocked_duration FROM pg_catalog.pg_locks bl JOIN pg_catalog.pg_stat_activity a ON bl.pid = a.pid JOIN pg_catalog.pg_locks kl JOIN pg_catalog.pg_stat_activity ka ON kl.pid = ka.pid ON bl.transactionid = kl.transactionid AND bl.pid != kl.pid WHERE NOT bl.granted;'



\set idletxn 'SELECT datname,       pid,       (clock_timestamp() - backend_start) AS bk_age,       (clock_timestamp() - state_change) state_age,       (clock_timestamp() - xact_start) xact_age,       usename,       application_name app,       client_addr,       (STATE || CASE                     WHEN waiting THEN ''(w)''                     ELSE ''''                 END) AS STATE,       queryFROM pg_stat_activityWHERE xact_start IS NOT NULL  AND pid <> pg_backend_pid()ORDER BY xact_start;'

\set index_size 'SELECT relname AS name,       pg_size_pretty(sum(relpages*1024)) AS SIZEFROM pg_classWHERE reltype=0GROUP BY relnameORDER BY sum(relpages) DESC;'

\set index_usage_adv 'SELECT *FROM  (SELECT stat.relname AS TABLE,          stai.indexrelname AS INDEX,          CASE stai.idx_scan              WHEN 0 THEN ''Insufficient data''              ELSE (100 * stai.idx_scan / (stat.seq_scan + stai.idx_scan))::text || ''%''          END hit_rate,              CASE stat.idx_scan                  WHEN 0 THEN ''Insufficient data''                  ELSE (100 * stat.idx_scan / (stat.seq_scan + stat.idx_scan))::text || ''%''              END all_index_hit_rate,                  ARRAY     (SELECT pg_get_indexdef(idx.indexrelid, k + 1, TRUE)      FROM generate_subscripts(idx.indkey, 1) AS k      ORDER BY k) AS cols,                  stat.n_live_tup rows_in_table   FROM pg_stat_user_indexes AS stai   JOIN pg_stat_user_tables AS stat ON stai.relid = stat.relid   JOIN pg_index AS idx ON (idx.indexrelid = stai.indexrelid)) AS sub_innerORDER BY rows_in_table DESC,         hit_rate ASC;'

\set index_usage 'SELECT relname,       CASE idx_scan           WHEN 0 THEN ''Insufficient data''           ELSE (100 * idx_scan / (seq_scan + idx_scan))::text       END percent_of_times_index_used,       n_live_tup rows_in_tableFROM pg_stat_user_tables ORDER BY n_live_tup DESC;'

\set locks 'SELECT pg_stat_activity.pid,       pg_class.relname,       pg_locks.transactionid,       pg_locks.granted,       substring(pg_stat_activity.query                 FROM ''([^]*?){1,3}'') AS query_snippet,       age(now(),pg_stat_activity.query_start) AS "age"FROM pg_stat_activity,     pg_locksLEFT OUTER JOIN pg_class ON (pg_locks.relation = pg_class.oid)WHERE pg_stat_activity.query <> ''''  AND pg_locks.pid=pg_stat_activity.pid  AND pg_locks.mode = ''ExclusiveLock''ORDER BY query_start;'


\set locks1  'SELECT bl.pid AS blocked_pid, a.usename AS blocked_user, kl.pid AS blocking_pid, ka.usename AS blocking_user, a.query AS blocked_statement FROM pg_catalog.pg_locks bl JOIN pg_catalog.pg_stat_activity a ON bl.pid = a.pid JOIN pg_catalog.pg_locks kl JOIN pg_catalog.pg_stat_activity ka ON kl.pid = ka.pid ON bl.transactionid = kl.transactionid AND bl.pid != kl.pid WHERE NOT bl.granted;'


\set long_running_queries 'SELECT pid,       now() - pg_stat_activity.query_start AS duration,       query AS queryFROM pg_stat_activityWHERE pg_stat_activity.query <> ''''::text  AND now() - pg_stat_activity.query_start > interval ''5 minutes''ORDER BY now() - pg_stat_activity.query_start DESC;'

\set missing_indexes 'SELECT relname,       seq_scan-idx_scan AS too_much_seq,       CASE           WHEN seq_scan-idx_scan > 0 THEN ''Missing Index?''           ELSE ''OK''       END,       pg_relation_size(relname::regclass) AS rel_size,       seq_scan,       idx_scanFROM pg_stat_all_tablesWHERE schemaname=''public''  AND pg_relation_size(relname::regclass) > 80000ORDER BY too_much_seq DESC;'

\set nspsize_pgs 'SELECT * from (SELECT    nspname,    pg_size_pretty(sum(8192::bigint*nullif(tbl.relpages, 0))) "tables",    pg_size_pretty(sum(8192::bigint*nullif(idx.relpages, 0))) "indexes",    pg_size_pretty(sum(8192::bigint*nullif(tst.relpages, 0))) "toast",    pg_size_pretty(sum(8192::bigint*(        coalesce(tbl.relpages, 0)      + coalesce(idx.relpages, 0)      + coalesce(tst.relpages, 0)))) AS "total",    concat(       count(distinct tbl.oid) FILTER (where tbl.relkind=''r'')::text,       ''/'',       count(distinct tst.oid)::text,       ''/'',       count(distinct idx.oid)::text,       ''/'',       count(distinct tbl.oid) FILTER (where tbl.relkind=''m'')::text    ) AS "#r/t/i/m"FROM    pg_class AS tblJOIN    pg_namespace AS nsp ON (tbl.relnamespace=nsp.oid)LEFT JOIN    pg_class tst ON (tbl.reltoastrelid=tst.oid)LEFT JOIN    pg_index ON (pg_index.indrelid=tbl.oid)LEFT JOIN    pg_class idx ON pg_index.indexrelid=idx.oidWHERE    (tbl.relkind = ''r'' OR tbl.relkind = ''m'')GROUP BY    nspnameORDER BY    sum(coalesce(tbl.relpages, 0)+coalesce(idx.relpages, 0)+coalesce(tst.relpages, 0))DESC) _'

\set nspsize 'SELECT * from (SELECT    nspname,    pg_size_pretty(sum(pg_table_size(pg_class.oid))) "Schema Size",    pg_size_pretty(sum(pg_indexes_size(pg_class.oid))) "Indexes",    count(pg_class.oid) "Tables"FROM pg_classJOIN pg_namespace ON (pg_class.relnamespace=pg_namespace.oid)WHERE relkind = ''r'' or relkind = ''m''GROUP BY nspnameORDER BY sum(pg_total_relation_size(pg_class.oid)) DESC) _'

\set ps 'SELECT pid,       application_name AS SOURCE,       age(now(),query_start) AS running_for,       waiting,       query AS queryFROM pg_stat_activityWHERE query <> ''''  AND STATE <> ''idle''  AND pid <> pg_backend_pid()ORDER BY 3 DESC;'

\set seq_scans 'SELECT relname AS name,       seq_scan AS COUNTFROM pg_stat_user_tables ORDER BY seq_scan DESC;'


-- number of connected backends
\set settings 'select name, setting,unit,context from pg_settings;'

\set show_slow_queries 'SELECT (total_time / 1000 / 60) AS total_minutes,       (total_time/calls) AS average_time,       queryFROM pg_stat_statementsORDER BY 1 DESC LIMIT 100;'

\set spcsize 'SELECT    coalesce(spcname, ''[Default]'') "Tablespace",    pg_size_pretty(sum(pg_relation_size(c.oid)) FILTER (WHERE relkind = ''r'' or relkind = ''m'')) "Data Size",    pg_size_pretty(sum(pg_relation_size(c.oid)) FILTER (WHERE relkind = ''i''                 )) "Index Size",    count(c.oid) "# Tables"FROM pg_class cLEFT JOIN pg_tablespace spc ON (c.reltablespace=spc.oid)WHERE relkind = ''r'' or relkind = ''m'' or relkind = ''i''GROUP BY 1/*ORDER BY sum(pg_total_relation_size(c.oid)) DESC;*/ORDER BY 1;'

\set statrelfilepath_agg 'select * from (select relid,    nsp.nspname,    c.relname,    fpath,numsegs,tot_size,access_bnds,modification_bnds,change_bnds,creation_bnds,isdir from (SELECT c.oid relid,       relpages / segsz.seg_size AS numsegs,       pg_relation_filepath(c.oid) AS fpath,       sum(size) tot_size,       tstzrange(min(fstat.access), max(fstat.access), ''[]'') access_bnds,       tstzrange(min(fstat.modification), max(fstat.modification), ''[]'') modification_bnds,       tstzrange(min(fstat.change), max(fstat.change), ''[]'') change_bnds,       tstzrange(min(fstat.creation), max(fstat.creation), ''[]'') creation_bnds,       fstat.isdirFROM (SELECT setting::bigint seg_sizeFROM pg_settingsWHERE name = ''segment_size'') AS segsz,pg_class c,generate_series(0::bigint, relpages / segsz.seg_size) segnum,concat(pg_relation_filepath(c.oid), coalesce(''.''||nullif(segnum, 0), '''')) _fpath,pg_stat_file(_fpath) fstatwhere relkind=''r'' group by relid, numsegs, fstat.isdir)_JOIN pg_class c on c.oid=relidJOIN pg_namespace nsp ON c.relnamespace=nsp.oid)_'

\set statrelfilepath 'SELECT c.oid relid,       nsp.nspname,       c.relname,       segnum,       fpath,       fstat.size,       fstat.access,       fstat.modification,       fstat.change,       fstat.creation,       fstat.isdirFROM (SELECT setting::bigint seg_sizeFROM pg_settingsWHERE name = ''segment_size'') AS segsz,pg_class cJOIN pg_namespace nsp ON c.relnamespace=nsp.oid,generate_series(0::bigint, relpages / segsz.seg_size) segnum,concat(pg_relation_filepath(c.oid), coalesce(''.''||nullif(segnum, 0), '''')) fpath,pg_stat_file(fpath) fstat'

\set statrelspcfilepath_agg 'SELECTrelid,nspname,relname,spcname,fpath,numsegs,tot_size,access_bnds,modification_bnds,change_bnds,creation_bnds,isdirFROM (SELECT relid,    nsp.nspname,    c.relname,    spc.spcname,    fpath,    numsegs,    tot_size,    access_bnds,    modification_bnds,    change_bnds,    creation_bnds,    isdirFROM (SELECT c.oid relid,       1 + relpages/segsz.seg_size AS numsegs,       pg_relation_filepath(c.oid) AS fpath,       sum(size) tot_size,       tstzrange(min(fstat.access), max(fstat.access), ''[]'') access_bnds,       tstzrange(min(fstat.modification), max(fstat.modification), ''[]'') modification_bnds,       tstzrange(min(fstat.change), max(fstat.change), ''[]'') change_bnds,       tstzrange(min(fstat.creation), max(fstat.creation), ''[]'') creation_bnds,       fstat.isdirFROM (SELECT setting::bigint seg_sizeFROM pg_settingsWHERE name = ''segment_size'') AS segsz,pg_class c,generate_series(0::bigint, relpages / segsz.seg_size) segnum,concat(pg_relation_filepath(c.oid), coalesce(''.''||nullif(segnum, 0), '''')) _fpath,pg_stat_file(_fpath) fstatwhere relkind=''r'' group by relid, numsegs, fstat.isdir)_JOIN pg_class c    ON c.oid=relidJOIN pg_namespace nsp    ON c.relnamespace=nsp.oidJOIN pg_tablespace spc    ON ((c.reltablespace=spc.oid) OR (spc.spcname=''pg_default'' and c.reltablespace=0)))_'

\set total_index_size 'SELECT pg_size_pretty(sum(relpages*1024)) AS SIZEFROM pg_classWHERE reltype=0;'

\set unused_indexes 'SELECT schemaname || ''.'' || relname AS TABLE,       indexrelname AS INDEX,       pg_size_pretty(pg_relation_size(i.indexrelid)) AS index_size,       idx_scan AS index_scansFROM pg_stat_user_indexes uiJOIN pg_index i ON ui.indexrelid = i.indexrelidWHERE NOT indisunique  AND idx_scan < 50  AND pg_relation_size(relid) > 5 * 8192ORDER BY pg_relation_size(i.indexrelid) / nullif(idx_scan, 0) DESC NULLS FIRST,                                                                         pg_relation_size(i.indexrelid) DESC;'


\set vacuuminfo '/*https://gist.githubusercontent.com/skehlet/36aad599171b25826e82/raw/b84501643ec16d05f8b307ad87bac884bc14fd52/gistfile1.sql*/WITH table_opts AS (    SELECT      pg_class.oid, relname, nspname, array_to_string(reloptions, '''') AS relopts    FROM      pg_class INNER JOIN pg_namespace ns ON relnamespace = ns.oid), storage_settings AS (    SELECT      oid, relname, nspname,      CASE        WHEN relopts LIKE ''%autovacuum_vacuum_threshold%''          THEN regexp_replace(relopts, ''.*autovacuum_vacuum_threshold=([0-9.]+).*'', E''\\1'')::integer          ELSE current_setting(''autovacuum_vacuum_threshold'')::integer      END AS autovacuum_vacuum_threshold,      CASE        WHEN relopts LIKE ''%autovacuum_vacuum_scale_factor%''          THEN regexp_replace(relopts, ''.*autovacuum_vacuum_scale_factor=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''autovacuum_vacuum_scale_factor'')::real      END AS autovacuum_vacuum_scale_factor,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_min_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_min_age=([0-9.]+).*'', E''\\1'')::integer          ELSE current_setting(''vacuum_freeze_min_age'')::integer      END AS autovacuum_freeze_min_age,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_table_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_table_age=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''vacuum_freeze_table_age'')::real      END AS autovacuum_freeze_table_age,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_max_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_max_age=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''autovacuum_freeze_max_age'')::real      END AS autovacuum_freeze_max_age    FROM      table_opts)SELECT  storage_settings.nspname AS schema,  storage_settings.relname AS table,  to_char(pg_class.reltuples, ''9G999G999G999'') AS rowcount,  to_char(psut.n_dead_tup, ''9G999G999G999'') AS dead_rowcount,  to_char(autovacuum_vacuum_threshold          + (autovacuum_vacuum_scale_factor::numeric * pg_class.reltuples), ''9G999G999G999'') AS autovacuum_threshold,  CASE    WHEN autovacuum_vacuum_threshold + (autovacuum_vacuum_scale_factor::numeric * pg_class.reltuples) < psut.n_dead_tup      THEN ''yes''  END AS expect_autovacuum,  age(relfrozenxid) as relfrozenxid_age,  autovacuum_freeze_table_age,  CASE    WHEN age(relfrozenxid) > autovacuum_freeze_table_age      THEN ''yes''  END AS next_autovacuum_will_be_a_freeze,  autovacuum_freeze_max_age,  ROUND(100.0 * age(relfrozenxid) / autovacuum_freeze_max_age::numeric, 1) || ''%'' AS "% til forced vacuum freeze"FROM  pg_stat_user_tables psut INNER JOIN pg_class ON psut.relid = pg_class.oid  INNER JOIN storage_settings ON pg_class.oid = storage_settings.oidORDER BY storage_settings.relname;'

\set waits 'SELECT pg_stat_activity.pid,       pg_stat_activity.query,       pg_stat_activity.state,       now() - pg_stat_activity.query_start AS \"totaltime\", pg_stat_activity.backend_start FROM pg_stat_activity WHERE pg_stat_activity.query !~ \'%IDLE%\'::text  AND pg_stat_activity.waiting = TRUE;'

\set waits1 'SELECT pg_stat_activity.pid, pg_stat_activity.query, pg_stat_activity.state, now() - pg_stat_activity.query_start AS \"totaltime\", pg_stat_activity.backend_start FROM pg_stat_activity WHERE pg_stat_activity.query !~ \'%IDLE%\'::text AND pg_stat_activity.waiting = true;'


\set wrapstats_raw '/*https://gist.githubusercontent.com/skehlet/36aad599171b25826e82/raw/b84501643ec16d05f8b307ad87bac884bc14fd52/gistfile1.sql*/select relid, spcid, spcname, nspid, nspname, reltuples, relpages, relsize_pgs, frozenage, iceinfrom (SELECT  storage_settings.oid AS relid,  spc.oid spcid,  spc.spcname,  nsp.oid nspid,  nsp.nspname,  c.reltuples,  c.relpages,  8192::bigint*c.relpages relsize_pgs,  age(relfrozenxid) as frozenage,  autovacuum_freeze_max_age - age(relfrozenxid) AS iceinFROM  pg_stat_user_tables psut  JOIN pg_class c ON psut.relid = c.oid  JOIN (    SELECT      oid, relname, nspname,      CASE        WHEN relopts LIKE ''%autovacuum_vacuum_threshold%''          THEN regexp_replace(relopts, ''.*autovacuum_vacuum_threshold=([0-9.]+).*'', E''\\1'')::integer          ELSE current_setting(''autovacuum_vacuum_threshold'')::integer      END AS autovacuum_vacuum_threshold,      CASE        WHEN relopts LIKE ''%autovacuum_vacuum_scale_factor%''          THEN regexp_replace(relopts, ''.*autovacuum_vacuum_scale_factor=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''autovacuum_vacuum_scale_factor'')::real      END AS autovacuum_vacuum_scale_factor,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_min_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_min_age=([0-9.]+).*'', E''\\1'')::integer          ELSE current_setting(''vacuum_freeze_min_age'')::integer      END AS autovacuum_freeze_min_age,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_table_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_table_age=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''vacuum_freeze_table_age'')::real      END AS autovacuum_freeze_table_age,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_max_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_max_age=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''autovacuum_freeze_max_age'')::real      END AS autovacuum_freeze_max_age    FROM      (    SELECT      pg_class.oid, relname, nspname, array_to_string(reloptions, '''') AS relopts    FROM      pg_class INNER JOIN pg_namespace ns ON relnamespace = ns.oid      )table_opts)storage_settings ON c.oid = storage_settings.oid  JOIN pg_tablespace spc on c.reltablespace=spc.oid or (c.reltablespace=0 and spc.spcname=''pg_default'')  JOIN pg_namespace nsp on c.relnamespace=nsp.oidORDER BY icein)_'

\set wrapstats_rels '/*https://gist.githubusercontent.com/skehlet/36aad599171b25826e82/raw/b84501643ec16d05f8b307ad87bac884bc14fd52/gistfile1.sql*/WITH table_opts AS (    SELECT      pg_class.oid, relname, nspname, array_to_string(reloptions, '''') AS relopts    FROM      pg_class INNER JOIN pg_namespace ns ON relnamespace = ns.oid), storage_settings AS (    SELECT      oid, relname, nspname,      CASE        WHEN relopts LIKE ''%autovacuum_vacuum_threshold%''          THEN regexp_replace(relopts, ''.*autovacuum_vacuum_threshold=([0-9.]+).*'', E''\\1'')::integer          ELSE current_setting(''autovacuum_vacuum_threshold'')::integer      END AS autovacuum_vacuum_threshold,      CASE        WHEN relopts LIKE ''%autovacuum_vacuum_scale_factor%''          THEN regexp_replace(relopts, ''.*autovacuum_vacuum_scale_factor=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''autovacuum_vacuum_scale_factor'')::real      END AS autovacuum_vacuum_scale_factor,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_min_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_min_age=([0-9.]+).*'', E''\\1'')::integer          ELSE current_setting(''vacuum_freeze_min_age'')::integer      END AS autovacuum_freeze_min_age,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_table_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_table_age=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''vacuum_freeze_table_age'')::real      END AS autovacuum_freeze_table_age,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_max_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_max_age=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''autovacuum_freeze_max_age'')::real      END AS autovacuum_freeze_max_age    FROM      table_opts),_ as (SELECT  storage_settings.oid::regclass AS "rel",  to_char(pg_class.reltuples, ''9G999G999G999'') AS "Rows",  to_char(pg_class.relpages, ''9G999G999'') AS "Pages",  pg_size_pretty(pg_table_size(pg_class.oid)) AS "Size",  pg_table_size(pg_class.oid) "size",  age(relfrozenxid) as "icedXID",  autovacuum_freeze_table_age "AV TblIceAge",  CASE    WHEN age(relfrozenxid) > autovacuum_freeze_table_age      THEN ''AV''    WHEN age(relfrozenxid) > current_setting(''vacuum_freeze_table_age'')::integer      THEN ''V''  END AS "Icing",  autovacuum_freeze_max_age "IceMaxAV",  autovacuum_freeze_max_age - age(relfrozenxid) AS "ice_in",  ROUND(100.0 * age(relfrozenxid) / autovacuum_freeze_max_age::numeric, 1) || ''%'' AS "IceAV%"FROM  pg_stat_user_tables psut INNER JOIN pg_class ON psut.relid = pg_class.oid  INNER JOIN storage_settings ON pg_class.oid = storage_settings.oidORDER BY ice_in)select "rel", "Pages", "Size", "icedXID", ice_in, "IceAV%" from _'

\set wrapstats_spc '/*https://gist.githubusercontent.com/skehlet/36aad599171b25826e82/raw/b84501643ec16d05f8b307ad87bac884bc14fd52/gistfile1.sql*/WITH table_opts AS (    SELECT      pg_class.oid, relname, nspname, array_to_string(reloptions, '''') AS relopts    FROM      pg_class INNER JOIN pg_namespace ns ON relnamespace = ns.oid), storage_settings AS (    SELECT      oid, relname, nspname,      CASE        WHEN relopts LIKE ''%autovacuum_vacuum_threshold%''          THEN regexp_replace(relopts, ''.*autovacuum_vacuum_threshold=([0-9.]+).*'', E''\\1'')::integer          ELSE current_setting(''autovacuum_vacuum_threshold'')::integer      END AS autovacuum_vacuum_threshold,      CASE        WHEN relopts LIKE ''%autovacuum_vacuum_scale_factor%''          THEN regexp_replace(relopts, ''.*autovacuum_vacuum_scale_factor=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''autovacuum_vacuum_scale_factor'')::real      END AS autovacuum_vacuum_scale_factor,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_min_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_min_age=([0-9.]+).*'', E''\\1'')::integer          ELSE current_setting(''vacuum_freeze_min_age'')::integer      END AS autovacuum_freeze_min_age,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_table_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_table_age=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''vacuum_freeze_table_age'')::real      END AS autovacuum_freeze_table_age,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_max_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_max_age=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''autovacuum_freeze_max_age'')::real      END AS autovacuum_freeze_max_age    FROM      table_opts),_ as (SELECT  storage_settings.oid::regclass AS "rel",  spc.spcname,  to_char(c.reltuples, ''9G999G999G999'') AS "Rows",  to_char(c.relpages, ''9G999G999'') AS "Pages",  pg_size_pretty(8192::bigint*c.relpages) AS "Size",  8192::bigint*c.relpages "size",  age(relfrozenxid) as "icedXID",  autovacuum_freeze_table_age "AV TblIceAge",  CASE    WHEN age(relfrozenxid) > autovacuum_freeze_table_age      THEN ''AV''    WHEN age(relfrozenxid) > current_setting(''vacuum_freeze_table_age'')::integer      THEN ''V''  END AS "Icing",  autovacuum_freeze_max_age "IceMaxAV",  autovacuum_freeze_max_age - age(relfrozenxid) AS "ice_in",  ROUND(100.0 * age(relfrozenxid) / autovacuum_freeze_max_age::numeric, 1) || ''%'' AS "IceAV%"FROM  pg_stat_user_tables psut  JOIN pg_class c ON psut.relid = c.oid  JOIN storage_settings ON c.oid = storage_settings.oid  JOIN pg_tablespace spc on c.reltablespace=spc.oid or (c.reltablespace=0 and spc.spcname=''pg_default'')  /*LEFT JOIN pg_locks ON c.oid=pg_locks.relation WHERE pg_locks.relation is null*/ORDER BY ice_in)select "rel", spcname, "Pages", "Size", "icedXID", ice_in, "IceAV%" from _'

\set wrapstats '/*https://gist.githubusercontent.com/skehlet/36aad599171b25826e82/raw/b84501643ec16d05f8b307ad87bac884bc14fd52/gistfile1.sql*/WITH table_opts AS (    SELECT      pg_class.oid, relname, nspname, array_to_string(reloptions, '''') AS relopts    FROM      pg_class INNER JOIN pg_namespace ns ON relnamespace = ns.oid), storage_settings AS (    SELECT      oid, relname, nspname,      CASE        WHEN relopts LIKE ''%autovacuum_vacuum_threshold%''          THEN regexp_replace(relopts, ''.*autovacuum_vacuum_threshold=([0-9.]+).*'', E''\\1'')::integer          ELSE current_setting(''autovacuum_vacuum_threshold'')::integer      END AS autovacuum_vacuum_threshold,      CASE        WHEN relopts LIKE ''%autovacuum_vacuum_scale_factor%''          THEN regexp_replace(relopts, ''.*autovacuum_vacuum_scale_factor=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''autovacuum_vacuum_scale_factor'')::real      END AS autovacuum_vacuum_scale_factor,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_min_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_min_age=([0-9.]+).*'', E''\\1'')::integer          ELSE current_setting(''vacuum_freeze_min_age'')::integer      END AS autovacuum_freeze_min_age,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_table_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_table_age=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''vacuum_freeze_table_age'')::real      END AS autovacuum_freeze_table_age,      CASE        WHEN relopts LIKE ''%autovacuum_freeze_max_age%''          THEN regexp_replace(relopts, ''.*autovacuum_freeze_max_age=([0-9.]+).*'', E''\\1'')::real          ELSE current_setting(''autovacuum_freeze_max_age'')::real      END AS autovacuum_freeze_max_age    FROM      table_opts),_ as (SELECT  storage_settings.nspname AS "Schema",  storage_settings.relname AS "Table",  to_char(pg_class.reltuples, ''9G999G999G999'') AS "Rows",  to_char(pg_class.relpages, ''9G999G999'') AS "Pages",  pg_size_pretty(pg_table_size(pg_class.oid)) AS "Size",  age(relfrozenxid) as "icedXID",  autovacuum_freeze_table_age "AV TblIceAge",  CASE    WHEN age(relfrozenxid) > autovacuum_freeze_table_age      THEN ''AV''    WHEN age(relfrozenxid) > current_setting(''vacuum_freeze_table_age'')::integer      THEN ''V''  END AS "Icing",  autovacuum_freeze_max_age "IceMaxAV",  autovacuum_freeze_max_age - age(relfrozenxid) AS "ice_in",  ROUND(100.0 * age(relfrozenxid) / autovacuum_freeze_max_age::numeric, 1) || ''%'' AS "IceAV%"FROM  pg_stat_user_tables psut INNER JOIN pg_class ON psut.relid = pg_class.oid  INNER JOIN storage_settings ON pg_class.oid = storage_settings.oidORDER BY ice_in)select "Schema", "Table", "Pages", "Size", "icedXID", ice_in, "IceAV%" from _'



-- number of connected backends
\set backends 'SELECT datname, numbackends FROM pg_catalog.pg_stat_database;'

\set conninfo 'select usename, count(*) from pg_stat_activity group by usename;'

\set activity 'select datname, pid, usename, application_name,client_addr, client_hostname, client_port, state, left(query,20) query1 from pg_stat_activity;'

\set activity1 'WITH _0 AS (SELECT datname, pid, (clock_timestamp() - backend_start) AS bk_age, (clock_timestamp() - state_change) state_age, (clock_timestamp() - xact_start) xact_age,          (clock_timestamp() - query_start) query_age, usename, application_name app, client_addr, state, left(query,20) query1 FROM pg_stat_activity order by xact_start desc nulls last, query_start desc) SELECT * FROM _0 ;'

\set activity96 'WITH _0 AS (SELECT datname, pid, (clock_timestamp() - backend_start) AS bk_age, (clock_timestamp() - state_change) state_age, (clock_timestamp() - xact_start) xact_age,          (clock_timestamp() - query_start) query_age, usename, application_name app, client_addr, concat(STATE, CASE WHEN waiting THEN ''[WAIT]'' ELSE '''' END) AS STATE, regexp_replace(query, ''[ ]+'', '' '', ''g'') query1   FROM pg_stat_activity order by xact_start desc nulls last, query_start desc)SELECT * FROM _0; '

\set activity2 'WITH _0 AS (SELECT datname, pid, (clock_timestamp() - backend_start) AS bk_age, (clock_timestamp() - state_change) state_age, (clock_timestamp() - xact_start) xact_age,          (clock_timestamp() - query_start) query_age, usename, application_name app, client_addr, state, left(regexp_replace(query, ''[ ]+'', '' '', ''g''),20) query1   FROM pg_stat_activity order by xact_start desc nulls last, query_start desc) SELECT * FROM _0;'

--\set activitytho1 'WITH _0 AS  (SELECT datname, pid, (clock_timestamp() - backend_start) AS bk_age, (clock_timestamp() - state_change) state_age, (clock_timestamp() - xact_start) xact_age,          (clock_timestamp() - query_start) query_age, usename, application_name app, client_addr, state, left(regexp_replace(query, ''[ ]+'', '' '', ''g''),20) query1 FROM pg_stat_activity  WHERE pid <> pg_backend_pid()    AND state <> ''idle''  ORDER BY xact_start DESC NULLS LAST, query_start DESC)SELECT * FROM _0 ;'

\set activitytho 'WITH _0 AS  (SELECT datname, pid, (clock_timestamp() - backend_start) AS bk_age, (clock_timestamp() - state_change) state_age, (clock_timestamp() - xact_start) xact_age,          (clock_timestamp() - query_start) query_age, usename, application_name app, client_addr, state, left(query,20) query1,  FROM pg_stat_activity  WHERE pid <> pg_backend_pid()    AND state <> ''idle''  ORDER BY xact_start DESC NULLS LAST,           query_start DESC)SELECT * FROM _0 ;'



\set dbsize 'SELECT datname, pg_size_pretty(pg_database_size(datname)) db_size FROM pg_database ORDER BY db_size;'

\set tablesize 'SELECT nspname || \'.\' || relname AS \"relation\", pg_size_pretty(pg_relation_size(C.oid)) AS "size" FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace) WHERE nspname NOT IN (\'pg_catalog\', \'information_schema\') ORDER BY pg_relation_size(C.oid) DESC LIMIT 40;'

\set tablesize1 'WITH _0 AS  (SELECT (nspname || \'.\' || relname) AS rel,    pg_size_pretty(pg_relation_size(C.oid)) AS "size"    FROM pg_class C    LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)    WHERE nspname NOT IN (\'pg_catalog\', \'information_schema\')   ORDER BY pg_relation_size(C.oid) DESC)SELECT * from _0 ;'


\set uselesscol 'SELECT nspname, relname, attname, typname, (stanullfrac*100)::int AS null_percent, case when stadistinct >= 0 then stadistinct else abs(stadistinct)*reltuples end AS \"distinct\", case 1 when stakind1 then stavalues1 when stakind2 then stavalues2 end AS \"values\" FROM pg_class c JOIN pg_namespace ns ON (ns.oid=relnamespace) JOIN pg_attribute ON (c.oid=attrelid) JOIN pg_type t ON (t.oid=atttypid) JOIN pg_statistic ON (c.oid=starelid AND staattnum=attnum) WHERE nspname NOT LIKE E\'pg\\\\_%\' AND nspname != \'information_schema\' AND relkind=\'r\' AND NOT attisdropped AND attstattarget != 0 AND reltuples >= 100 AND stadistinct BETWEEN 0 AND 1 ORDER BY nspname, relname, attname;'



Mas info en el gi: https://github.com/DiegoDAF/pgScrips

A principios de mes se subastó el manuscrito de la novela The Sign of Four, de Arthur Conan Doyle, en la que reáparecen el detective Sherlock Holmes y su ayudante, el doctor Watson.
Lá celebre pareja había nacido en la novela anterior de Doyle, Estudio en escarlata (de la que se conserva tan solo una página del manuscrito). A pesar de los reclamos de varios admiradores, Arthur Conan Doyle no quería verse obligado a desarrollar una serie de relatos que tuviera a Holmes y Watson como protagonistas. Sin embargo, cambió de parecer después de una cena realizada a fines de 1889 en un elegante hotel de Londres. Allí, el editor del mensuario literario norteamericano Lippincott`s les pidió, a él y a Oscar Wilde, novelas cortas para editárselas en los Estados Unidos.
Respondiendo a tal pedido, Wilde escribió El retrato de Dorian Gray y Doyle The Sign of Four. La aparición, en 1890, de esta última novela fue el inicio de un éxito comercial de tal magnitud que a Conan Doyle ya no le fue fácil resistirse a narrar nuevas aventuras del detective Sherlock Holmes.
Además de bastante dinero, esas novelas le dieron al escritor escocés una fama de la que abjuró al final de su vida. Conan Doyle creía que el detective había opacado “lo mejor de su obra” y que por eso nunca lograría, como su admirado amigo Oscar Wilde, un lugar destacado en la historia literaria. En esto, le faltó el olfato de su infalible personaje.

CLARIN – jueves 19 de diciembre de 1996

Rational

When you create a user in postgresql, even with only select only permission, your user has a lot more privileges.

Solution

Connect with root user to the desired database you will be giving permissions for:
mydb=# psql -h 10.10.10.10 -U postgres mydb
Now lets create the user:
mydb=# create user readonly with encrypted password 'readonly';
Revoke everything so we can explicitly allow what we need:
mydb=# revoke all on schema public from readonly;

Grant only what you need.

First give connection privilege to the actual database:
mydb=# GRANT CONNECT ON DATABASE mydb TO readonly;

Then grant usage and select:
mydb=# GRANT USAGE,SELECT ON SCHEMA public TO readonly;
mydb=# GRANT SELECT ON ALL TABLES IN SCHEMA public TO readonly;
If you want to grant access to the new tables in the future automatically, you have to alter default:
mydb=# ALTER DEFAULT PRIVILEGES IN SCHEMA public
GRANT SELECT ON TABLES TO readonly;

Fin

Thats all!

Fuente: parask.me/blog/postgresql-readonly-user

– gmapbmap.img = Mapa base, que viene con el equipo.
– gmapprom.img = Mapa precargado de fabrica (EEUU, Canada)
– gmapsupp.img = Mapear V12.4
– gmapprom1.img = Mapear Nautico V2

gmapsupp.img (always the default name from mapsource)
gmapsup1.img (additional on SD card)
gmapprom.img (Garmin main memory)
1 x gmapsupp.img – memoria interna del dispositivo
1 x gmapsupp.img – externa / SD Card
1 x gmapsup2.img – externa / SD Card
1 x gmapsup3.img – externa / SD Card

The ssh “timed out waiting for input: auto-logout” messages is generated by ssh upon reaching a auto-logout after an inactivity time specified by the TMOUT environment variable. If this variable is not set your session will not be auto-logged out due to inactivity. If the environment variable is set, your session will be automatically closed/logged out after the amount of seconds specified by the TMOUT variable.

To see if your auto-logout variable is set and/or see what it is set to issue the following command:
$ echo $TMOUT

Often this value is defined in /etc/profile (globally) or your user’s profile (~/.profile or ~/.bash_profile).

To alter the auto-logout amount, set the TMOUT environment variable accordingly:
* TMOUT=600 #set an auto-logout timeout for 10 minutes
* TMOUT=1200 #set an auto-logout timeout for 20 minutes
* TMOUT= #turn off auto-logout (user session will not auto-logout due to session inactivity)

This value can be set globally (e.g. TMOUT=1200) in the /etc/profile file; however, each user can override the value by setting the TMOUT variable in their personal profile file (~/.profile or ~/.bash_profile). To do this simply set the TMOUT variable as you like in your profile file.

Dont forget to source the file you changed to get the settings to take effect immediately or log out and log back in.

Fuente: adercon.com/ac/node/39

The xrandr program is used to set the size, orientation and/or reflection of the outputs for a screen. Using Xrandr, we can also display the current state of the system screen, change or set the resolution, disable disconnected outputs and enable connected ones. And the good thing is Xrandr comes pre-installed with most Linux distributions, so we don’t have to bother with installing additional tools/apps.

Adjust Monitor Brightness From Command Line In Linux

First, we need to check the current state of system display. To do so, run:

$ xrandr -q

Sample output:

Screen 0: minimum 320 x 200, current 1366 x 768, maximum 8192 x 8192
LVDS-1 connected primary 1366x768+0+0 (normal left inverted right x axis y axis) 344mm x 194mm
1366x768 60.00*+ 40.00 
1280x720 60.00 59.99 59.86 59.74 
1024x768 60.04 60.00 
960x720 60.00 
928x696 60.05 
896x672 60.01 
1024x576 59.95 59.96 59.90 59.82 
960x600 59.93 60.00 
960x540 59.96 59.99 59.63 59.82 
800x600 60.00 60.32 56.25 
840x525 60.01 59.88 
864x486 59.92 59.57 
700x525 59.98 
800x450 59.95 59.82 
640x512 60.02 
700x450 59.96 59.88 
640x480 60.00 59.94 
720x405 59.51 58.99 
684x384 59.88 59.85 
640x400 59.88 59.98 
640x360 59.86 59.83 59.84 59.32 
512x384 60.00 
512x288 60.00 59.92 
480x270 59.63 59.82 
400x300 60.32 56.34 
432x243 59.92 59.57 
320x240 60.05 
360x202 59.51 59.13 
320x180 59.84 59.32 
VGA-1 disconnected (normal left inverted right x axis y axis)
HDMI-1 disconnected (normal left inverted right x axis y axis)
DP-1 disconnected (normal left inverted right x axis y axis)

As you can see, the currently connected display is LVDS-1. This output displays current resolution and screen refresh rate.

If you want to know the only the active display name, use “grep” and “head” commands with “xrandr” as shown below.

$ xrandr -q | grep ' connected' | head -n 1 | cut -d ' ' -f1
LVDS-1

The brightness value must be between 0.0 to 1.0 where 0.0 refers the dimmest (full black) and 1.0 refers the brightest value. For example, to set screen brightness value as 0.7, run:

$ xrandr --output LVDS-1 --brightness 0.7

Replace LVDS-1 with your active display name. Here, 0.7 refers the 70% of the maximum display brightness.

To go back to normal brightness, run:

$ xrandr --output LVDS-1 --brightness 1.0

Don’t use anything above 1.0. It might turn the display into full white and you may not clearly see anything in the screen.

Fuente: https://www.ostechnix.com/how-to-adjust-monitor-brightness-from-command-line-in-linux

MONOLOGO N° 2000 de TATO BORES
DOMINGO 9 DE SETIEMBRE DE 1990 – 21 HORAS 30 MINUTOS.

“Bueno, señores, Monologo 2000! 30 años metiendo libreto debajo de esta peluca! Mire, esta noche en lugar de hacer un monologo con lo que paso esta semana, con la actualidad, esta semana vamos a hacer un monologo recordando lo que paso los ultimos 30 anhos a ver si aprendemos algo, eh?

Señores: cuando alla por 1960 puse la jeta por primera vez delante de los orticones, no existia la television color, no existia Maradona, no existia el Austral – es decir, el Austral tampoco existe ahora pero es otra historia -, no existia el control remoto, no existia el yogur descremado, pero si, si existia Don Alvaro; si señores, si: Don Alvaro, el papá de la nena! Si bien Don Alvaro empezo a curtir gabinete como Ministro de Industria alla por el anho `55 en la “LIBERTADORA”, que no tiene nada que ver con la Copa Libertadores, porque recien con Arturo Frondizi se convirtio en Ministro de Economia. Porque le voy a decir mas: antes de Don Arturo Frondizi no existia el Ministerio de Economia; dicen los memoriosos que para aquellos anhos habia un poco de guita en el tesoro y entonces con un Ministro de Hacienda tipo Serelco, alcanzaba!. Con la mishiadura aparecieron los Ministros de Economia. Lo que no queda muy bien claro es si la mishiadura trajo a los Ministros de Economia o si los Ministros de Economia trajeron la mishiadura! Lo que pasa es que hace 30 anhos que tenemos las dos cosas.

Por aquellos anhos, Don Alvaro Alsogaray se mando la famosa frase “HAY QUE PASAR EL INVIERNO”. Y pasaron y pasaron los inviernos, y las primaveras aparecieron y aparecieron – lo unico que no aparecio fue la guita -; y tambien por aquellos anhos `60 comenzaron lo planteos militares a Don Arturo Frondizi. En realidad el primer planteo fue el 8 de julio de 1958 pero en dos años le enchufaron 30 planteos!; y aqui con Don Alfonsin tuvimos dos planteos con los muchachos de la pomada, calcule lo que habran sido 30 planteos!. La cuestion es que los muchachos, al final, lo rajaron, y cuando el general Poggi estaba ya listo para asumir como presidente aparecio Jose Maria Guido – tambien conocido como “JOSE DONDEMEPONGO” -,pego un Per Saltum, entro a Tribunales, juro como presidente ante la Corte Suprema, se colo por un intersticio en una puerta de la Casa Rosada, se sento en el sillon, y cuando Poggi se dio vuelta le dijo “ACATAA!”

La cuestion es que Don Guido trajo a otro prohombre de la economia: Don Federico Piñedo que dijo que hay que hacer las cosas rapido y se mando en un solo dia una devaluacion del 21% y mando el dolar a la astronomica suma de 99 pesos moneda nacional de curso legal. (Chicos: si ustedes no saben lo que es eso – la moneda nacional de curso legal – preguntenle al abuelo, pero no lo hagan llorar demasiado, por favor!).

La cuestion es que Don Piñedo se las tomo ofendido por las criticas que desperto esa devaluacion y entonces aparecio de vuelta Alvaro II, que viene a ser como “HIGHLANDER II”, “TIBURON II”, “ROCKY II”, una cosa asi.
Como el tema de “HAY QUE PASAR EL INVIERNO” estaba gastado, Don Alvaro invento otra cosa: invento el “EMPRESTITO PATRIOTICO NUEVE DE JULIO” llamado tambien “LOS BONOS DE ALSOGARAY”. Los que se los quedaron, la verdad, se ganaron mucha guita; los que no nos los pudimos quedar, pa’que’ le via’ contar! Es otra historia…

Mientras tanto los militares, que no tenian nada que hacer, se pusieron a jugar a los soldaditos entre ellos: hicieron una raya y dijeron: “COLORADOS DE ESTE LADO, AZULES DE ESTE OTRO LADO, GANA EL QUE TIENE MAS TANQUES”. Nosotros, los civiles, que no teniamos arte ni parte en el asunto, porque unicamente ligabamos una bomba que nos reventara la casa, estabamos tranquilos porque tanto azules como colorados decian que todo lo hacian por el bienestar de la gente y por la salvacion de la patria; de donde se deducia que la salvacion de la patria estaba en manos del que tenia mas tanques, comprende?

La cuestion es que en el anho `63 le toco el turno de vuelta a un presidente constitucional y aparecio Don Arturo Humberto Illia, uno de los pocos Cordobeses nacidos en Pergamino que se conocen. Don Arturo Humberto Illia nombro como Ministro de Economia a Don Eugenio Blasco que muere en el cargo y entonces mi gran amigo Juan Carlos Pugliese asume como Ministro de Economia – empieza, mejor dicho, su carrera como Ministro de Economia suplente en todos los gabinetes radicales -. Pero como las cosas buenas duran poco tiempo, antes de cumplir los tres años los muchachos de la (haciendo el signo de una insignia militar en el hombro izquierdo con los dedos indice y mayor de la mano derecha) viñeta le dan el raje a Don Arturo Humberto Illia y designan, en elecciones limpias, y por u-na-ni-mi-dad – 3 votos – a Don Juan Carlos Ongania. El hecho de que Don Juan Carlos Ongania en la epoca del enfrentamiento entre azules y colorados haya sido azul – y legalista – y despues se convirtio en golpista – y de hecho, colorado – es porque a veces, la gente, des-ti-ñe.

La cuestion es que a Don Arturo lo rajaron porque decian que era muy lento, que era una tortuga. Ahi tuvimos un cacho la culpa todos porque los sindicatos, la C. G. T. le tiraba tortugas en Plaza de Mayo, los medios en contra, los periodistas en contra, los humoristas le haciamos chistes -eramos una manga de boludos que pa’ que’ le via’ contar -; porque el problema no era que Don Illia era lento: el problema es que los que vinieron despues fueron… fueron rapidos, y fuimos derecho pal’ cara… melo, fuimos, pero bah, pero rapido!

Claro, no todo fue negrura en aquellos anhos porque en el `66 hubo avances: porque despues de la “NOCHE DE LOS BASTONES LARGOS” cerraron todas las facultades y entonces todos los investigadores, cientificos, matematicos, laburantes de las neuronas avanzaron: avanzaron hacia la frontera y se las tomaron y no volvieron nunca mas. Despues, aparecio algun premio Nobel que volvio: a saludar a la familia y se las volvio a tomar, total…!

Para 1969 el Ministro de Economia era Adalbert Krieger Vassena que habia mantenido el dolar mas o menos estable; pero de pronto aparecio Don Jose Maria Danigno Pastore y, como el dolar ya estaba a 350 mangos, le arranco dos ceros porque invento el peso ley 18188 – intimamente llamado “EL PESO LEY” – Don Juanca, en aquellos años – Juan Carlos Ongania – pensaba quedarse 20 o 30 anhos, pero aparecio el “CORDOBAZO”, el “ROSARIAZO” y el pais se movio como un “FLANAZO”. O sea que para los finales de 1970 los muchachos (haciendo de nuevo el signo de una insignia militar en el hombro izquierdo con los dedos indice y mayor de la mano derecha) le dieron las gracias por los servicios prestados a Don Juanca I y despues designaron en elecciones limpias y por unanimidad a Roberto Marcelo Levingston.

Roberto Marcelo Levingston es el unico presidente en toda la historia argentina desde 1810 hasta la fecha que cuando lo designaron no lo conocia ni el loro! Vea, en las redacciones, no sabian como se escribia el nombre! No habia una foto de el! Cuando, a la noche, en la sexta aparecio “LEVINGSTON PRESIDENTE” la gente preguntaba “PERO EL PRESIDENTE DE QUE PAIS SERA ESTE BUEN SEÑOR?” Y porque para colmo, cuando lo designaron el estaba en la Junta Interamericana de Defensa en Washington! Asi que aqui estabamos como los indios que se golpean el codo: en bolas, y a los gritos!

Por fin, Don Levingston aparecio y dijo “SOY EL PRESIDENTE” y se sento en el sillon a esperar ordenes. Lo que pasa el problema fue que mientras estaba esperando las ordenes empezo a jugar un jueguito que decia: “PESE A TODO, YO SOY EL PRESIDENTE”. Don Lanusse, que era el inmediato superior, no le gusto nada la cosa, pero roce va roce viene Don Levingston lo destituye a Lanusse, Lanusse escucha eso, caza el tubo y lo destituye a Levingston, y como donde manda Teniente General no manda General de Brigada Levingston volvio rapidamente al anonimato. Cansado ya de hechar presidentes – habia echado dos – Don Lanusse penso: “PARA PENSAR COMO YO, NADIE COMO YO”. Entonces agarro y se nombro presidente sin dejar el cargo de Comandante en Jefe. Astuto el hombre! Y enseguida invento una cosa que se llamo el G. A. N.: “GRAN ACUERDO NACIONAL”. Y lo mando al Coronel Cornicelli a verlo a “PUERTA DE HIERRO” a mi gran amigo Juan Carlos Can… Juan Carlos no (risas), Juan Domingo, Juan Domingo (aplausos), Juan Domingo Cangallo y le dijo que si entraba en el G. A. N. le devolvia todos los sueldos del `55 hasta la fecha. El viejo dijo “LO PRIMERO ES LO PRIMERO”, cazo la mosca, lo dejo al gobierno con el G. A. N. y con las ganas. Y entonces Don Lanusse se chivo y se mando la famosa frase que “EL VIEJO NO VOLVIA PORQUE NO LE DABA EL CUERO”. Pero como el viejo debajo de las arrugas todavia le quedaba un cacho de quiero… de cuero, volvio para mostrarlo en vivo y en directo y formo un frente civico que se llamo “FRE. CI. LI. NA.”. Pero como la Frecilina tenia nombre de antibiotico lo cambiaron por “FRE. JU. LI.”. Escuche, Frecilina, Frejuli, Frejupo, son todos remedios del mismo laboratorio! Vienen en pildoras, en inyectables, en supositorio, uselo como le de las ganas! La cuestion es que en aquellos años ’73 aparecio “LA NUEVA FUERZA”, un partido politico inventado por mi gran amigo Alsogaray que tenia como candidato a presidente a mi gran amigo Julio Chamizo, el que quiere acordarse, que se acuerde! La cuestion es que el 25 de mayo de 1973 asumio el tio, no este, otro tio, el tio, el tio Hector J. Campora, y como el eslogan era “CAMPORA AL GOBIERNO, PERON AL PODER”, los muchachos del bombo rapidamente renunciaron a don Hector.
Renuncio el presidente, renuncio el vicepresidente, renuncio el presidente provisorio del Senado Diaz Vialisi, una cosa ahi, que se yo lo que hicieron. La cuestion es que quedo como candidato a Presidente de la Republica el presidente de la camara de Diputados Raul Lastiri, que casualmente era yerno de Lopez Rega!. La cuestion es que Lastiri -conocido tambien como “JOSE CORBATA” porque tenia un monton y le encantaban – llamo a elecciones y gano por unanimidad la formula “MENEM-MENEM…”, digo, no, la formula “PERON-PERON”. Peron se muere y de estar mal pasamos a estar peor porque viene Isabelita y lo trae a Celestino Rodrigo que se manda el famoso “RODRIGAZO” que nos deja a todos con el tuje pal’ norte! La moral de la historieta es que Don Celestino, que yo sepa cabe destacar, y que yo sepa, fue el unico Ministro de Economia, que se comio canas por cuestion de su gestion como ministro, cosa que no le ha pasado a ningun otro ministro de economia, nunca mas, se han salvado todos, la verdad es que es un misterio, que no se por que! (a su libretista) Como seguia esto? (el libretista le sopla, y Tato sigue).
Ah!, si.

Despues de Celestino Rodrigo, despues de Celestino Rodrigo aparecio Tony Cafiero, si, si, si, Tony Cafiero, el del “SI”, el del “SI LO HUBIERA SABIDO NO LLAMABA A PLESBICITO”! Y despues de el aparecio Mondelli – que Isabel decia “NO ME LO TOQUEN AL GORDITO” -.

Cuando se murio Peron – es una acotacion que le voy a hacer yo – estaba laburando en este canal, me llamaron para decirme “VAMOS A PARAR UN POCO CON LOS PROGRAMAS HUMORISTICOS, HAY QUE HACER DUELO”, y yo pense que estaba bien para que lo suspendan un par de semanas (silencio durante algunos segundos, y luego risas)… La verdad es que no lo suspendieron un par de semanas, lo suspendieron un par de años! Porque despues vinieron los muchachos del `76 de vuelta y la siguieron… Porque en aquel entonces eran largos los duelos, comprende?! Y asi llegamos, a la epoca del proceso, de los Ministros de Economia, era Jose Alfredo Martinez de Hoz, y el proceso lo voy a pasar por alto porque, la verdad que, no, mejor no recordarlo, cierto?

Por eso hice un Per Saltum y apareci en la democracia, en 1983, con Alfonsin, Grinspun, Sourrouille, el Austral, el desagio, Juan Carlos Pugliese II, el bolonki, y Jesus Rodriguez casi como Jesus termina crucificado. Mientras en estos tiempos la hiperinflacion y los empresarios le apretaban el gañote a Don Raul Alfonsin, aparecio Carlos Saul I, primer presidente electo que decia que tenia el equipo formado, listo para salir a la cancha y ganar por goleada! Don Raul, que queria quedarse 6 años, ni un dia antes, ni un dia despues, no le quedo mas remedio que tirar la esponja y de paso le tiro el gobierno por la cabeza a la patilla mas gorda de America, Carlos Saul I.

Y aqui estamos señor. 30 años. 30 años bancandose 16 presidentes y 37 Ministros de Economia que se la pasaron diciendo “ESTA ES LA CRISIS MAS GRANDE QUE ESTA SUFRIENDO EL PAIS”, “HAY QUE REDUCIR EL GASTO PUBLICO”, “HAY QUE LABURAR MAS”, “HAY QUE INVERTIR EN EL ISPA”. Mientras tanto, quiere que le diga una cosa?, mire, este peso moneda nacional (sosteniendo el billete de un m$n en la mano, con otros billetes –un $ley 18188, un $ argentino, un Austral– sobre la mesa) le arrancaron dos ceros por este otro peso ley 18188; a este le arrancaron cuatro ceros por este otro peso argentino, y como si esto fuera poco le sacaron tres ceros mas por este peso… por este Austral. O sea que extirparon, le extirparon nueve ceros a este pesito de aca delante. Y como este Austral equivale a mil millones de pesos moneda nacional, y como en aquel entonces se compraba con 83 $mn un dolar, este Austral equivale a DOCE MILLONES DE DOLARES… (risas, mezcladas con silencio, lagrimas e ironia), lo cual parece un chiste, si no fuera una joda grande como una casa… Y yo todavia (aplausos), yo todavia tengo confianza, tengo confianza, por eso le digo a los politicos y a los funcionarios – no a todos los politicos ni a todos los funcionarios porque hay que preservar las instituciones – algunos politicos y algunos funcionarios que estan ahi viendome, si siguen haciendo las cosas que estan haciendo yo voy a tratar de estar aca todo el tiempo posible para seguir jodiendo! Y para cuidarlos tambien… Y para preservarlos de la maquina de cortar boludos; porque si pusieramos la maquina de cortar boludos dentro de la maquina del tunel del tiempo, y se pusiera a cortar boludos historicos con retroactividad… otra hubiera sido la historieta hoy! Historieta que como pais, no creo que nos merezcamos – esto lo dice mi libretista Santiago Varela… yo… no estoy tan seguro! Un cacho de culpa tenemos tambien…! -. Por eso les digo, mis queridos chichipios, seguir laburando, vermouth con papas fritas, y… (aplaudiendo dos veces, levantandose y terminando el monologo como todos los domingos) GOOD SHOW!!!”

ANIVERSARIO
A 95 años del retiro de Sherlock Holmes

Su creador lo había. “matado” en 1891 · Pero tuvo que revivirlo a pedido del público · En 1904, finalmente, hizo que Holmes se recluyera en una granja
El doctor Watson invitó a Sherlock Holmes a su casamiento y después dejó de ver a su amigo; bastante tiempo más tarde se reencontraron en la casa de huéspedes del 221b de Baker Street, en Londres, y ya no se separaron. Según consta en las aventuras publicadas por el escritor Arthur Conan Doyle, en esa perisión vivieron los dos personajes y allí resolvieron gran parte de los enigmas policiales, hasta que el detective se retiró de la actividad, hace exactamente 95 años.
“Sherlock Holmes es posiblemente el único personaje de ficción que se ha convertido en una persona con residencia fija”, apuntó Guillermo Cabrera Infante en El libro de las ciudades.
Conan Doyle inventó un domicilio literario y, aunque el 221b de Baker Street nunca estuvo registrado en la nomenclatura londinense, esa dirección existe.
Durante muchos años la sede del Abbey National Bank ocupó la numeración 215 a 229 de la calle y allï llegaban decenas de cartas semanales, dirigidas al detective, que una abnegada secretaria contestaba.
“El señor Holmes le agradece su carta; en la actualidad está retirado en Sussex, dedicado a Ia apicultura”, informaba con amabilidad. En 1904, el personaje se refugió en una granja donde comenzó a producir una miel que, aparentemente; servía para alargar la vida.
Desde el 27 de marzo de 1990, en la casa, de estilo victoriano, funciona el Museo Sherlock Holmes.
En base a las descripciones de los relatos, recrea minuciosamente la pensión de la señora Hudson. Todo está allí coxno lo dejaron el détective y su compañero en la ficción. Una escalera de 17 éscalones une el hall con el primer piso; donde está el despacho que la dupla utilizó durante casi 25 años y al lado, la habitación de Holmes.
En la segunda planta está el dormitorio de Watson, donde ahora los visitantes dejan sus tarjetas personales: hay datos de policías, detectives privados y especialistas en criminología.
Entre los muebles antiguos pueden verse fotografías, libros, periódicos, objetos rescatadas de las aventuras y hasta una medalla que el gobierno francés le entregó al detective en agradecimiento por los servicios prestados.
Por supuesto, están el gorro, la lupa, la pipa y el sillón: elementos básicos para descifrar las aventuras, a fuerza de razonamientos lógicos y poder de observación.
Holmes y Watson protagonizaron cincuenta y seis cuentos y cuatro novelas. Policiales puros, que nada tienen que ver con las historias duras que el género incorporó después.
El antecedente literario del detective es Dupin -el personaje ideado por Edgar Allan Poe- y su continuador es el Padre Brown, de Gilbert Keith Chesterton.
En las historias de Conan Doyle prima el orden; toda causa tiene su efecto y los crímenes siempre se resuelven. Si se sabe discernir entre los indicios reales y los falsos, se llega a la verdad.
Agobiado ya de su personaje, el escritor lo hizo morir en 1891, en unos saltos alemanes cercanos a la ciudad de Meiningen. Los lectores protestaron y hasta la madre del propio autor quedó consternada. La presión fue tal que Conan Doyle tuvo que revivir a Sherlock Holmes, y “retirarlo” a una granja más de diez años dèspués.

CLARIN – Lunes 2 de agosto de 1999

Conan Doyle, el inventor de un detective sagaz e inmutable

El creador de Sherlock Holmes murio hace 70 años. Su profesion de medico la cambio por la de escritor

Sir Arthur Conan Doyle recibió ese título, el de sir, luego de haber participado en la guerra anglo-boer (1899-1902) que enfrentó a los blancos sudafricanos con la corona, y de haber apoyado con su pluma la posición de Inglaterra. No es el único dato que lo define comó un hombre de lòs buenos viejos tiempos. Como un personaje del imperio.
Nacido en Edimburgo, Escocia, en 1858, Conan Doyle estudió Mediciria. Durante sus cursos còmo practicante, lo impresionó vivamente uno de sus profesòres, quien despuntaba un curioso hobby: deducir, à partir de datos que a la mayor parte de los mortales no le resultaban relevantes la procedencia de los heridos de un hospital militar.
Cuando, en 1887 publicá la primera avénturá de Sherlock (Estudio en escarlata), el personaje es presentado esgrimiendo las mismas dotes de su antiguo profesor en una situación sin duda muy similar a las que él, Conan Doyle, debe haber presenciando.

El prlmer encuentro

Durante el primer encuentro del entonces joven detective con el doctor Watson -quien se convertirá en su infatigable ayudante y admirador-, el investigador dispara: “Qué noticiàs trae de Afganistán?”
Un conjunto de datos le sirven para asombrar à Watson con ese aparente don adivinatorió: ha visto que el hombre parece estar reponiéndose de una herida puesto que se sostiene el brazo de un modo especial; es médico, puesto que como tal acaban de presentárselo, y médico militar, ya que tiene porte marcial: ergo, fue herido en combate. Afganistán no era la única contienda en que estaba a énvuelto el imperio, pero era la única que se libraba en un lugar cálido; como Watson estaba qúemado por el sol, sin duda había sido herido allí.
Cinco minutos despues Sherlock y Watson simpatizan. Acuerdan compartir un departamento,-ya que uno es un éstudiante diletante y el otro un veterano sin mucho dinero, y nace un número mágico en una calle real de Londres: 221b de Baker Street. Mágico porque se ha convertido en el museo palpable de un personaje de ficción, y hacia él peregrinan miles de actuales fans de un detective que nunca existio.
Después del éxito de Estudio en escarlata, Doyle se rétira de la Medicina y; eumpliendo con la promesa de Watsón a Sherlock (“Yo escribiré sus hazañas”), se dedica a inventar una tras otra històrias de mágicas resoluciones de su imaginario compañero de aventuras (porque Watson parece ser el papel de Arthur Conan Doyle en la historia).
Los relatos de Sherlock Holmes se suceden, desde El signo de los cuatro (1890), pasando por Las aventuras de Sherlock Holmes (1892) y El sabueso de Baskerville (1902) hasta Su último saludo en el escenario (1917).
Harto, Doyle trató de deshacerse de su detective decretando su muerte a manos de Moriarty, su principal rival -antecedente de los archienemigos del cómic-, pero debió sacarlo vivo del fondo de un barranco ante el clamor del público. Tal vez no terminaba de entender lo que el público entendía: Holmes era un emblema de la vieja Inglaterra, la que se había terminado con el fin del reinado de Victoria.
Holmes encarnaba no sólo la flema británica, sino también la previsibilidad: por enigmático y sórdido que se presentara el caso, Holmes lo resolvería. Cualquiera, como Watson, podía sentirse cómodo junto a él, seguro. Holmes era un Hércules analítico, no un Quijote: Su escudero nunca experimentaría el desasasiego de Sancho Panza. El crimen se convertía en un puzzle en sus manos. La cachiporra, la esgrima, el revólver, eran otros tantos argumentos intelectuales para él.
El detective que hacía quedar en ridículo a Scotland Yard trasmitía una sensación de vida inmutable. Había nacido en los años que en Jack el Destripador asolaba el barrio de Whitechapel. Jack derrotó de verdad a la policía británica; Holmes era su sustituto.
Tal vez, cuando se sumía en su catatonía acompañada de droga, el detective percibía el abismo con el que lidiaba en realidad. Sigmund Freud asumiría a la vez sus armas analíticas y su abismo. Pues el tipo de lógica que Holmes utilizaba estaba relacionada con algunos escritos de Charles S. Pierce, conocidos hacia 1878 que Doyle debió leer.
No era Hohnes un “deductivo”; su razonamiento era de otro tipo. Según Pierce “no hay sino tres clases elementales de razonamiento. La primera, que yo llamo abduccióri (…) consiste en examinar una masa de hechos y en permitir que estos hechos sugieran una teoría. De este modo ganamos nuevas ideas; pero el razonamiento no tiene fuerza. La segunda clase dle razonamiento es la deducción o razonamiento necesario. Sólo es aplicable a un estado ideal de cosas (…) tercer modo dé razonamiento es la índucción o investigación experimental”.
Los estados de cosas que Holmes investigaba no se presentaban ni de lejos en condiciones ideales. De manera que procedía a la abducción (examinar la masa de hechos) para dar un salto hacia la inducción o lógica experimental, que.deslumbraba a Watson. En ella había más intuición que pura matemática (véase Crítica…).
Doyle dejó a Holmes en el camino en 1917 y vivió hasta el 7 de julio de 1930. El personaje no podía habitar mucho más en el siglo veinte a menos que se decidiese a ampliar su campo de visión El relato negro norteamericano tomó la posta. El crimen tendría desde entonces un escenario más creíble: las inasibles ciudades del nuevo mundo donde el énigma es sucio, básicamente vulgar y profundamente arraigado en el funcionamiento social.

Clarin – Viernes 7 de julio de 2000