Received: from malur.postgresql.org ([217.196.149.56]) by arkaria.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hnO6S-0005yy-Di for pgsql-hackers@arkaria.postgresql.org; Tue, 16 Jul 2019 14:06:48 +0000 Received: from localhost ([127.0.0.1] helo=malur.postgresql.org) by malur.postgresql.org with esmtp (Exim 4.89) (envelope-from ) id 1hnO6R-0005M0-A2 for pgsql-hackers@arkaria.postgresql.org; Tue, 16 Jul 2019 14:06:47 +0000 Received: from magus.postgresql.org ([2a02:c0:301:0:ffff::29]) by malur.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hnO6Q-0005Lt-Oe for pgsql-hackers@lists.postgresql.org; Tue, 16 Jul 2019 14:06:47 +0000 Received: from mail-io1-xd30.google.com ([2607:f8b0:4864:20::d30]) by magus.postgresql.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.89) (envelope-from ) id 1hnO6M-0003Ny-LS for pgsql-hackers@postgresql.org; Tue, 16 Jul 2019 14:06:46 +0000 Received: by mail-io1-xd30.google.com with SMTP id s7so40005011iob.11 for ; Tue, 16 Jul 2019 07:06:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=telsasoft-com.20150623.gappssmtp.com; s=20150623; h=date:from:to:cc:subject:message-id:references:mime-version :content-disposition:in-reply-to:user-agent; bh=vaecVBPJpO8OnKtOjRPdJMGqEWEIPAmVvAKrqU+cMq8=; b=y1YTNUEPhDg1VMBjhdbccrkj5LGxDrcPgtjiCoW0soaw7WEBe45ZiviWYUWtuEd99Y uxFw/D3fABqIHVaVcuTGT7jCDlNTRBlHWYIae+pSUvZlya3rjch1C9nkE9PyH5g9fzwO rXwfKrmAvjcmn1N/9fCgVlLnYAROdg18cPO/7fMUCvP7+MOJrvC9wv6L20Mwl2zn5S42 kOg/z+xtrK1BY0hL6fzl88nDYoMtIj9g36BDG21DpeWF9fDhryjXJAi/vgBMPhoQ2ozb TMYhjniq525rwEmF5Y1am9WlYUpBhBSiHuJXzoy7Idj/z4BSzepxMY0g8lsKaeq7NRMq sA0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to:user-agent; bh=vaecVBPJpO8OnKtOjRPdJMGqEWEIPAmVvAKrqU+cMq8=; b=Yh8AoXNC0rz6JlbAdZTgPE4jMITji+95bnRpNYowEaNpHdBYju1DR/lyJmbjkh4tL3 qqkwkFlId3+SdpVl60L6hWgPrItBGOEsttpX/PS9s1XK/kBnHUoQ0vuZy9HaT6vU9RWl 0u4aDziCpZ7ns3XLWxfRGfQhu+jv7HgEu6J+rcV4ACXXH8WL5H1y73ISmYSrms1mk3Le 01X0yCd8ShfeehNhbpR0xc7j1O2rkZlYxUJAAnEzvZGhiJXMZMxDb37YioqTCOgLiOtw bYz+O7ciymzxAmh6cwu8UlVipzslPf6R9+cVs+uu3LVxrxiwKvOKuonA5ulWiEsiUEgf g/Hw== X-Gm-Message-State: APjAAAWXhKS998+icnSzantilVKVSopz+jwENX85S15aheLybuSAzUZ8 M3Z7Lx7DPokTq4vK/z4zotM= X-Google-Smtp-Source: APXvYqzKoMlYFJ5tlwRPJyfmYtaXG1/PGldgPpLm3AhUAzBlIjJ9i4AUUHDtQQds8ZYxoTdMwlILiQ== X-Received: by 2002:a02:9991:: with SMTP id a17mr8109627jal.1.1563285999434; Tue, 16 Jul 2019 07:06:39 -0700 (PDT) Received: from pryzbyj (charmander.telsasoft.com. [50.244.222.1]) by smtp.gmail.com with ESMTPSA id i3sm17659821ion.9.2019.07.16.07.06.38 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Jul 2019 07:06:38 -0700 (PDT) Received: by pryzbyj (Postfix, from userid 1000) id 518448008C2; Tue, 16 Jul 2019 09:06:36 -0500 (CDT) Date: Tue, 16 Jul 2019 09:06:36 -0500 From: Justin Pryzby To: Fabien COELHO Cc: Rafia Sabih , PostgreSQL-development Subject: Re: make \d pg_toast.foo show its indices ; and, \d toast show its main table ; and \d relkind=I show its partitions Message-ID: <20190716140636.GA11917@telsasoft.com> References: <20190422154902.GH14223@telsasoft.com> <20190503142721.GC3925@telsasoft.com> <20190506162251.GN3925@telsasoft.com> <20190623142546.GE16019@telsasoft.com> <20190627230201.GA9401@telsasoft.com> <20190716050124.GG22387@telsasoft.com> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="Qxx1br4bt0+wmkIi" Content-Disposition: inline In-Reply-To: <20190716050124.GG22387@telsasoft.com> User-Agent: Mutt/1.5.24 (2015-08-30) List-Id: List-Help: List-Subscribe: List-Post: List-Owner: List-Archive: Precedence: bulk --Qxx1br4bt0+wmkIi Content-Type: text/plain; charset=us-ascii Content-Disposition: inline I realized that the test added to show-childs patch was listing partitioned tables not indices..fixed. --Qxx1br4bt0+wmkIi Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v5-0001-print-table-associated-with-given-TOAST-table.patch" From 237f0bb2a048aa71726eff2580d01404ae3a98b4 Mon Sep 17 00:00:00 2001 From: Justin Pryzby Date: Tue, 30 Apr 2019 19:05:53 -0500 Subject: [PATCH v5] print table associated with given TOAST table --- src/bin/psql/describe.c | 28 ++++++++++++++++++++++++++++ src/test/regress/expected/psql.out | 10 ++++++++++ src/test/regress/sql/psql.sql | 3 +++ 3 files changed, 41 insertions(+) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 3ee9c82..13ed2e1 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -2153,6 +2153,34 @@ describeOneTableDetails(const char *schemaname, } } + /* print table associated with given TOAST table */ + if (tableinfo.relkind == RELKIND_TOASTVALUE) + { + PGresult *result = NULL; + printfPQExpBuffer(&buf, + "SELECT c.relnamespace::pg_catalog.regnamespace, c.relname FROM pg_catalog.pg_class c WHERE reltoastrelid = '%s'", + oid); + result = PSQLexec(buf.data); + if (!result) + { + goto error_return; + } + else if (PQntuples(result) != 1) + { + PQclear(result); + goto error_return; + } + else + { + char *schemaname = PQgetvalue(result, 0, 0); + char *relname = PQgetvalue(result, 0, 1); + appendPQExpBuffer(&tmpbuf, _("For table: \"%s.%s\""), + schemaname, relname); + printTableAddFooter(&cont, tmpbuf.data); + PQclear(result); + } + } + if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE) { /* Get the partition key information */ diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 9021c80..5c8e439 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -4748,3 +4748,13 @@ drop schema testpart; set search_path to default; set role to default; drop role regress_partitioning_role; +-- slash dee on toast table: +\d pg_toast.pg_toast_2619 +TOAST table "pg_toast.pg_toast_2619" + Column | Type +------------+--------- + chunk_id | oid + chunk_seq | integer + chunk_data | bytea +For table: "pg_catalog.pg_statistic" + diff --git a/src/test/regress/sql/psql.sql b/src/test/regress/sql/psql.sql index cefe41b..b4a232d 100644 --- a/src/test/regress/sql/psql.sql +++ b/src/test/regress/sql/psql.sql @@ -1131,3 +1131,6 @@ set search_path to default; set role to default; drop role regress_partitioning_role; + +-- slash dee on toast table: +\d pg_toast.pg_toast_2619 -- 2.7.4 --Qxx1br4bt0+wmkIi Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v5-0002-make-d-pg_toast.foo-show-its-indices.patch" From 38928b346dc2cc264bb2a7581f1214f14b1bb89a Mon Sep 17 00:00:00 2001 From: Justin Pryzby Date: Fri, 3 May 2019 09:24:51 -0500 Subject: [PATCH v5] make \d pg_toast.foo show its indices --- src/bin/psql/describe.c | 1 + src/test/regress/expected/psql.out | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 13ed2e1..86a7610 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -2303,6 +2303,7 @@ describeOneTableDetails(const char *schemaname, else if (tableinfo.relkind == RELKIND_RELATION || tableinfo.relkind == RELKIND_MATVIEW || tableinfo.relkind == RELKIND_FOREIGN_TABLE || + tableinfo.relkind == RELKIND_TOASTVALUE || tableinfo.relkind == RELKIND_PARTITIONED_TABLE) { /* Footer information about a table */ diff --git a/src/test/regress/expected/psql.out b/src/test/regress/expected/psql.out index 5c8e439..d53dbb0 100644 --- a/src/test/regress/expected/psql.out +++ b/src/test/regress/expected/psql.out @@ -4757,4 +4757,6 @@ TOAST table "pg_toast.pg_toast_2619" chunk_seq | integer chunk_data | bytea For table: "pg_catalog.pg_statistic" +Indexes: + "pg_toast_2619_index" PRIMARY KEY, btree (chunk_id, chunk_seq) -- 2.7.4 --Qxx1br4bt0+wmkIi Content-Type: text/x-diff; charset=us-ascii Content-Disposition: attachment; filename="v6-0003-show-childs-of-partitioned-indices.patch" From ae748eda1460e6da37a6c5a1e1168a5c7c18639b Mon Sep 17 00:00:00 2001 From: Justin Pryzby Date: Wed, 19 Jun 2019 15:41:25 -0500 Subject: [PATCH v6] show childs of partitioned indices --- src/bin/psql/describe.c | 57 ++++++++++++++----------------- src/test/regress/input/tablespace.source | 1 + src/test/regress/output/tablespace.source | 31 +++++++++++++++++ 3 files changed, 57 insertions(+), 32 deletions(-) diff --git a/src/bin/psql/describe.c b/src/bin/psql/describe.c index 86a7610..6d136ba 100644 --- a/src/bin/psql/describe.c +++ b/src/bin/psql/describe.c @@ -3069,6 +3069,7 @@ describeOneTableDetails(const char *schemaname, if (tableinfo.relkind == RELKIND_RELATION || tableinfo.relkind == RELKIND_MATVIEW || tableinfo.relkind == RELKIND_FOREIGN_TABLE || + tableinfo.relkind == RELKIND_PARTITIONED_INDEX || tableinfo.relkind == RELKIND_PARTITIONED_TABLE) { PGresult *result; @@ -3120,6 +3121,7 @@ describeOneTableDetails(const char *schemaname, " FROM pg_catalog.pg_class c, pg_catalog.pg_inherits i" " WHERE c.oid=i.inhparent AND i.inhrelid = '%s'" " AND c.relkind != " CppAsString2(RELKIND_PARTITIONED_TABLE) + " AND c.relkind != " CppAsString2(RELKIND_PARTITIONED_INDEX) " ORDER BY inhseqno;", oid); result = PSQLexec(buf.data); @@ -3184,7 +3186,8 @@ describeOneTableDetails(const char *schemaname, * Otherwise, we will not print "Partitions" section for a partitioned * table without any partitions. */ - if (tableinfo.relkind == RELKIND_PARTITIONED_TABLE && tuples == 0) + if (tuples == 0 && (tableinfo.relkind == RELKIND_PARTITIONED_TABLE || + tableinfo.relkind == RELKIND_PARTITIONED_INDEX)) { printfPQExpBuffer(&buf, _("Number of partitions: %d"), tuples); printTableAddFooter(&cont, buf.data); @@ -3194,7 +3197,7 @@ describeOneTableDetails(const char *schemaname, /* print the number of child tables, if any */ if (tuples > 0) { - if (tableinfo.relkind != RELKIND_PARTITIONED_TABLE) + if (tableinfo.relkind != RELKIND_PARTITIONED_TABLE && tableinfo.relkind != RELKIND_PARTITIONED_INDEX) printfPQExpBuffer(&buf, _("Number of child tables: %d (Use \\d+ to list them.)"), tuples); else printfPQExpBuffer(&buf, _("Number of partitions: %d (Use \\d+ to list them.)"), tuples); @@ -3204,39 +3207,33 @@ describeOneTableDetails(const char *schemaname, else { /* display the list of child tables */ - const char *ct = (tableinfo.relkind != RELKIND_PARTITIONED_TABLE) ? + const char *ct = (tableinfo.relkind != RELKIND_PARTITIONED_TABLE && tableinfo.relkind != RELKIND_PARTITIONED_INDEX) ? _("Child tables") : _("Partitions"); int ctw = pg_wcswidth(ct, strlen(ct), pset.encoding); for (i = 0; i < tuples; i++) { - if (tableinfo.relkind != RELKIND_PARTITIONED_TABLE) - { - if (i == 0) - printfPQExpBuffer(&buf, "%s: %s", - ct, PQgetvalue(result, i, 0)); - else - printfPQExpBuffer(&buf, "%*s %s", - ctw, "", PQgetvalue(result, i, 0)); + char *ptn_expr = tableinfo.relkind == RELKIND_PARTITIONED_TABLE ? PQgetvalue(result, i, 1) : ""; + char *partitioned_note; + switch (*PQgetvalue(result, i, 2)) { + case RELKIND_PARTITIONED_INDEX: + case RELKIND_PARTITIONED_TABLE: + partitioned_note = ", PARTITIONED"; + break; + default: + partitioned_note = ""; } - else - { - char *partitioned_note; - - if (*PQgetvalue(result, i, 2) == RELKIND_PARTITIONED_TABLE) - partitioned_note = ", PARTITIONED"; - else - partitioned_note = ""; - if (i == 0) - printfPQExpBuffer(&buf, "%s: %s %s%s", - ct, PQgetvalue(result, i, 0), PQgetvalue(result, i, 1), - partitioned_note); - else - printfPQExpBuffer(&buf, "%*s %s %s%s", - ctw, "", PQgetvalue(result, i, 0), PQgetvalue(result, i, 1), - partitioned_note); - } + if (i == 0) + printfPQExpBuffer(&buf, "%s: %s%s%s%s", + ct, PQgetvalue(result, i, 0), + tableinfo.relkind == RELKIND_PARTITIONED_TABLE ? " " : "", ptn_expr, + partitioned_note); + else + printfPQExpBuffer(&buf, "%*s %s%s%s%s", + ctw, "", PQgetvalue(result, i, 0), + tableinfo.relkind == RELKIND_PARTITIONED_TABLE ? " " : "", ptn_expr, + partitioned_note); if (i < tuples - 1) appendPQExpBufferChar(&buf, ','); @@ -3279,10 +3276,6 @@ describeOneTableDetails(const char *schemaname, if (verbose && tableinfo.relkind != RELKIND_MATVIEW && tableinfo.hasoids) printTableAddFooter(&cont, _("Has OIDs: yes")); - /* Tablespace info */ - add_tablespace_footer(&cont, tableinfo.relkind, tableinfo.tablespace, - true); - /* Access method info */ if (verbose && tableinfo.relam != NULL && !pset.hide_tableam) { diff --git a/src/test/regress/input/tablespace.source b/src/test/regress/input/tablespace.source index 8f012fc..7875292 100644 --- a/src/test/regress/input/tablespace.source +++ b/src/test/regress/input/tablespace.source @@ -86,6 +86,7 @@ CREATE TABLE testschema.part2 PARTITION OF testschema.part FOR VALUES IN (2); SELECT relname, spcname FROM pg_catalog.pg_tablespace t, pg_catalog.pg_class c where c.reltablespace = t.oid AND c.relname LIKE 'part%_idx'; \d testschema.part_a_idx +\d+ testschema.part_a_idx -- partitioned rels cannot specify the default tablespace. These fail: CREATE TABLE testschema.dflt (a int PRIMARY KEY) PARTITION BY LIST (a) TABLESPACE pg_default; diff --git a/src/test/regress/output/tablespace.source b/src/test/regress/output/tablespace.source index 2ea68ca..d4771b7 100644 --- a/src/test/regress/output/tablespace.source +++ b/src/test/regress/output/tablespace.source @@ -129,6 +129,17 @@ Partitioned index "testschema.part_a_idx" a | integer | yes | a btree, for table "testschema.part" Tablespace: "regress_tblspace" +Number of partitions: 2 (Use \d+ to list them.) + +\d+ testschema.part_a_idx + Partitioned index "testschema.part_a_idx" + Column | Type | Key? | Definition | Storage | Stats target +--------+---------+------+------------+---------+-------------- + a | integer | yes | a | plain | +btree, for table "testschema.part" +Tablespace: "regress_tblspace" +Partitions: testschema.part1_a_idx, + testschema.part2_a_idx -- partitioned rels cannot specify the default tablespace. These fail: CREATE TABLE testschema.dflt (a int PRIMARY KEY) PARTITION BY LIST (a) TABLESPACE pg_default; @@ -344,6 +355,7 @@ Partitioned index "testschema.test_index1" --------+--------+------+------------ val | bigint | yes | val btree, for table "testschema.test_default_tab_p" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index2 Partitioned index "testschema.test_index2" @@ -352,6 +364,7 @@ Partitioned index "testschema.test_index2" val | bigint | yes | val btree, for table "testschema.test_default_tab_p" Tablespace: "regress_tblspace" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index3 Partitioned index "testschema.test_index3" @@ -359,6 +372,7 @@ Partitioned index "testschema.test_index3" --------+--------+------+------------ id | bigint | yes | id primary key, btree, for table "testschema.test_default_tab_p" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index4 Partitioned index "testschema.test_index4" @@ -367,6 +381,7 @@ Partitioned index "testschema.test_index4" id | bigint | yes | id unique, btree, for table "testschema.test_default_tab_p" Tablespace: "regress_tblspace" +Number of partitions: 1 (Use \d+ to list them.) -- use a custom tablespace for default_tablespace SET default_tablespace TO regress_tblspace; @@ -378,6 +393,7 @@ Partitioned index "testschema.test_index1" --------+--------+------+------------ val | bigint | yes | val btree, for table "testschema.test_default_tab_p" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index2 Partitioned index "testschema.test_index2" @@ -386,6 +402,7 @@ Partitioned index "testschema.test_index2" val | bigint | yes | val btree, for table "testschema.test_default_tab_p" Tablespace: "regress_tblspace" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index3 Partitioned index "testschema.test_index3" @@ -393,6 +410,7 @@ Partitioned index "testschema.test_index3" --------+--------+------+------------ id | bigint | yes | id primary key, btree, for table "testschema.test_default_tab_p" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index4 Partitioned index "testschema.test_index4" @@ -401,6 +419,7 @@ Partitioned index "testschema.test_index4" id | bigint | yes | id unique, btree, for table "testschema.test_default_tab_p" Tablespace: "regress_tblspace" +Number of partitions: 1 (Use \d+ to list them.) SELECT * FROM testschema.test_default_tab_p; id | val @@ -416,6 +435,7 @@ Partitioned index "testschema.test_index1" --------+---------+------+------------ val | integer | yes | val btree, for table "testschema.test_default_tab_p" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index2 Partitioned index "testschema.test_index2" @@ -424,6 +444,7 @@ Partitioned index "testschema.test_index2" val | integer | yes | val btree, for table "testschema.test_default_tab_p" Tablespace: "regress_tblspace" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index3 Partitioned index "testschema.test_index3" @@ -431,6 +452,7 @@ Partitioned index "testschema.test_index3" --------+--------+------+------------ id | bigint | yes | id primary key, btree, for table "testschema.test_default_tab_p" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index4 Partitioned index "testschema.test_index4" @@ -439,6 +461,7 @@ Partitioned index "testschema.test_index4" id | bigint | yes | id unique, btree, for table "testschema.test_default_tab_p" Tablespace: "regress_tblspace" +Number of partitions: 1 (Use \d+ to list them.) SELECT * FROM testschema.test_default_tab_p; id | val @@ -456,6 +479,7 @@ Partitioned index "testschema.test_index1" --------+---------+------+------------ val | integer | yes | val btree, for table "testschema.test_default_tab_p" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index2 Partitioned index "testschema.test_index2" @@ -464,6 +488,7 @@ Partitioned index "testschema.test_index2" val | integer | yes | val btree, for table "testschema.test_default_tab_p" Tablespace: "regress_tblspace" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index3 Partitioned index "testschema.test_index3" @@ -471,6 +496,7 @@ Partitioned index "testschema.test_index3" --------+--------+------+------------ id | bigint | yes | id primary key, btree, for table "testschema.test_default_tab_p" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index4 Partitioned index "testschema.test_index4" @@ -479,6 +505,7 @@ Partitioned index "testschema.test_index4" id | bigint | yes | id unique, btree, for table "testschema.test_default_tab_p" Tablespace: "regress_tblspace" +Number of partitions: 1 (Use \d+ to list them.) -- tablespace should not change even if there is an index rewrite ALTER TABLE testschema.test_default_tab_p ALTER val TYPE bigint; @@ -488,6 +515,7 @@ Partitioned index "testschema.test_index1" --------+--------+------+------------ val | bigint | yes | val btree, for table "testschema.test_default_tab_p" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index2 Partitioned index "testschema.test_index2" @@ -496,6 +524,7 @@ Partitioned index "testschema.test_index2" val | bigint | yes | val btree, for table "testschema.test_default_tab_p" Tablespace: "regress_tblspace" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index3 Partitioned index "testschema.test_index3" @@ -503,6 +532,7 @@ Partitioned index "testschema.test_index3" --------+--------+------+------------ id | bigint | yes | id primary key, btree, for table "testschema.test_default_tab_p" +Number of partitions: 1 (Use \d+ to list them.) \d testschema.test_index4 Partitioned index "testschema.test_index4" @@ -511,6 +541,7 @@ Partitioned index "testschema.test_index4" id | bigint | yes | id unique, btree, for table "testschema.test_default_tab_p" Tablespace: "regress_tblspace" +Number of partitions: 1 (Use \d+ to list them.) DROP TABLE testschema.test_default_tab_p; -- check that default_tablespace affects index additions in ALTER TABLE -- 2.7.4 --Qxx1br4bt0+wmkIi--