You've already forked explain.depesz.com
mirror of
https://gitlab.com/depesz/explain.depesz.com.git
synced 2025-07-05 00:58:52 +02:00
Added title for plan
Nathan Thom requested ability to add title to plan. It wasn't very complicated, so it's added :)
This commit is contained in:
@ -26,6 +26,11 @@ sub index {
|
||||
# anonymization
|
||||
my $is_anon = $self->req->param( 'is_anon' ) ? 1 : 0;
|
||||
|
||||
# plan title
|
||||
my $title = $self->req->param( 'title' );
|
||||
$title = '' unless defined $title;
|
||||
$title = '' if 'Optional title' eq $title;
|
||||
|
||||
# try
|
||||
eval {
|
||||
|
||||
@ -54,10 +59,12 @@ sub index {
|
||||
eval {
|
||||
|
||||
# send mail
|
||||
$self->send_mail( {
|
||||
$self->send_mail(
|
||||
{
|
||||
subject => q|Can't create explain from...|,
|
||||
msg => $plan
|
||||
} );
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
# leave...
|
||||
@ -65,7 +72,7 @@ sub index {
|
||||
}
|
||||
|
||||
# save to database
|
||||
my $id = $self->database->save_with_random_name( $plan, $is_public, $is_anon, );
|
||||
my $id = $self->database->save_with_random_name( $title, $plan, $is_public, $is_anon, );
|
||||
|
||||
# redirect to /show/:id
|
||||
return $self->redirect_to( 'show', id => $id );
|
||||
@ -75,14 +82,13 @@ sub show {
|
||||
my $self = shift;
|
||||
|
||||
# value of "/:id" param
|
||||
my $id = defined $self->stash->{ id }
|
||||
? $self->stash->{ id } : '';
|
||||
my $id = defined $self->stash->{ id } ? $self->stash->{ id } : '';
|
||||
|
||||
# missing or invalid
|
||||
return $self->redirect_to( 'new-explain' ) unless $id =~ m{\A[a-zA-Z0-9]+\z};
|
||||
|
||||
# get plan source from database
|
||||
my $plan = $self->database->get_plan( $id );
|
||||
my ( $plan, $title ) = $self->database->get_plan( $id );
|
||||
|
||||
# not found in database
|
||||
return $self->redirect_to( 'new-explain', status => 404 ) unless $plan;
|
||||
@ -105,8 +111,9 @@ sub show {
|
||||
return $self->redirect_to( 'new-explain' );
|
||||
}
|
||||
|
||||
# put explain to stash
|
||||
# put explain and title to stash
|
||||
$self->stash->{ explain } = $explain;
|
||||
$self->stash->{ title } = $title;
|
||||
|
||||
# render will be called automatically
|
||||
return;
|
||||
@ -138,19 +145,18 @@ sub contact {
|
||||
unless Email::Valid->address( $self->req->param( 'email' ) || '' );
|
||||
|
||||
# send
|
||||
$self->send_mail( {
|
||||
$self->send_mail(
|
||||
{
|
||||
msg => sprintf(
|
||||
"\nMessage from: %s <%s>" .
|
||||
"\nPosted from: %s with %s" .
|
||||
"\n****************************************\n\n" .
|
||||
"%s",
|
||||
"\nMessage from: %s <%s>" . "\nPosted from: %s with %s" . "\n****************************************\n\n" . "%s",
|
||||
$self->req->param( 'name' ) || '',
|
||||
$self->req->param( 'email' ),
|
||||
$self->tx->remote_address,
|
||||
$self->req->headers->user_agent,
|
||||
$self->req->param( 'message' )
|
||||
)
|
||||
} );
|
||||
}
|
||||
);
|
||||
|
||||
# mail sent message
|
||||
$self->flash( message => 'Mail sent' );
|
||||
@ -160,6 +166,7 @@ sub contact {
|
||||
}
|
||||
|
||||
sub help {
|
||||
|
||||
# direct to template
|
||||
return ( shift )->render;
|
||||
}
|
||||
|
@ -66,13 +66,13 @@ sub register {
|
||||
}
|
||||
|
||||
sub save_with_random_name {
|
||||
my ( $self, $content, $is_public, $is_anon ) = @_;
|
||||
my ( $self, $title, $content, $is_public, $is_anon ) = @_;
|
||||
|
||||
# create statement handler
|
||||
my $sth = $self->dbh->prepare( 'SELECT register_plan(?, ?, ?)' );
|
||||
my $sth = $self->dbh->prepare( 'SELECT register_plan(?, ?, ?, ?)' );
|
||||
|
||||
# execute
|
||||
$sth->execute( $content, $is_public, $is_anon );
|
||||
$sth->execute( $title, $content, $is_public, $is_anon );
|
||||
|
||||
# register_plan returns plan id
|
||||
my @row = $sth->fetchrow_array;
|
||||
@ -90,7 +90,7 @@ sub get_plan {
|
||||
my ( $self, $plan_id ) = @_;
|
||||
|
||||
# create statement handler
|
||||
my $sth = $self->dbh->prepare( 'SELECT plan FROM plans WHERE id = ?' );
|
||||
my $sth = $self->dbh->prepare( 'SELECT plan, title FROM plans WHERE id = ?' );
|
||||
|
||||
# execute
|
||||
$sth->execute( $plan_id );
|
||||
@ -102,7 +102,7 @@ sub get_plan {
|
||||
$sth->finish;
|
||||
|
||||
# return plan
|
||||
return $row[ 0 ];
|
||||
return @row;
|
||||
}
|
||||
|
||||
sub get_public_list {
|
||||
|
205
sql/create.sql
Executable file → Normal file
205
sql/create.sql
Executable file → Normal file
@ -1,32 +1,36 @@
|
||||
\connect template1 postgres
|
||||
--
|
||||
-- PostgreSQL database dump
|
||||
--
|
||||
|
||||
\set ON_ERROR_STOP OFF
|
||||
SET statement_timeout = 0;
|
||||
SET client_encoding = 'UTF8';
|
||||
SET standard_conforming_strings = on;
|
||||
SET check_function_bodies = false;
|
||||
SET client_min_messages = warning;
|
||||
|
||||
DROP DATABASE "explain";
|
||||
--
|
||||
-- Name: plpgsql; Type: EXTENSION; Schema: -; Owner: -
|
||||
--
|
||||
|
||||
DROP USER "explain";
|
||||
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
|
||||
|
||||
\set ON_ERROR_STOP ON
|
||||
|
||||
CREATE USER "explain" WITH password 'explain';
|
||||
--
|
||||
-- Name: EXTENSION plpgsql; Type: COMMENT; Schema: -; Owner: -
|
||||
--
|
||||
|
||||
CREATE DATABASE "explain" WITH encoding 'utf8' owner "explain";
|
||||
COMMENT ON EXTENSION plpgsql IS 'PL/pgSQL procedural language';
|
||||
|
||||
\connect "explain" postgres
|
||||
|
||||
CREATE procedural LANGUAGE plpgsql;
|
||||
SET search_path = public, pg_catalog;
|
||||
|
||||
\connect "explain" "explain"
|
||||
--
|
||||
-- Name: get_random_string(integer); Type: FUNCTION; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
-- plan
|
||||
CREATE TABLE plans (
|
||||
id TEXT PRIMARY KEY,
|
||||
plan TEXT NOT NULL,
|
||||
entered_on timestamptz NOT NULL DEFAULT now( ),
|
||||
is_public bool NOT NULL DEFAULT 'true'
|
||||
);
|
||||
|
||||
CREATE OR REPLACE FUNCTION get_random_string( string_length INT4 ) RETURNS TEXT AS $$
|
||||
CREATE FUNCTION get_random_string(string_length integer) RETURNS text
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
possible_chars TEXT = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||
output TEXT = '';
|
||||
@ -34,34 +38,167 @@ DECLARE
|
||||
pos INT4;
|
||||
BEGIN
|
||||
FOR i IN 1..string_length LOOP
|
||||
pos := 1 + cast( random( ) * ( length( possible_chars ) - 1 ) AS INT4 );
|
||||
output := output || substr( possible_chars, pos, 1 );
|
||||
pos := 1 + cast( random() * ( length(possible_chars) - 1) as INT4 );
|
||||
output := output || substr(possible_chars, pos, 1);
|
||||
END LOOP;
|
||||
RETURN output;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
$$;
|
||||
|
||||
CREATE OR REPLACE FUNCTION register_plan( in_plan TEXT, in_is_public BOOL ) RETURNS TEXT AS $$
|
||||
|
||||
--
|
||||
-- Name: register_plan(text, boolean); Type: FUNCTION; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE FUNCTION register_plan(in_plan text, in_is_public boolean) RETURNS text
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
use_hash_length INT4 := 2;
|
||||
use_hash TEXT;
|
||||
use_hash_length int4 := 2;
|
||||
use_hash text;
|
||||
BEGIN
|
||||
LOOP
|
||||
use_hash := get_random_string( use_hash_length );
|
||||
|
||||
use_hash := get_random_string(use_hash_length);
|
||||
BEGIN
|
||||
INSERT INTO plans ( id, plan, is_public, entered_on ) VALUES ( use_hash, in_plan, in_is_public, now( ) );
|
||||
INSERT INTO plans (id, plan, is_public, entered_on) values (use_hash, in_plan, in_is_public, now());
|
||||
RETURN use_hash;
|
||||
EXCEPTION when unique_violation THEN
|
||||
EXCEPTION WHEN unique_violation THEN
|
||||
-- do nothing
|
||||
END;
|
||||
|
||||
use_hash_length := use_hash_length + 1;
|
||||
|
||||
IF use_hash_length >= 30 THEN
|
||||
raise EXCEPTION 'Random string of length == 30 requested. Something is wrong.';
|
||||
raise exception 'Random string of length == 30 requested. something''s wrong.';
|
||||
END IF;
|
||||
|
||||
END LOOP;
|
||||
END;
|
||||
$$ LANGUAGE plpgsql;
|
||||
$$;
|
||||
|
||||
|
||||
--
|
||||
-- Name: register_plan(text, boolean, boolean); Type: FUNCTION; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE FUNCTION register_plan(in_plan text, in_is_public boolean, in_is_anonymized boolean) RETURNS text
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
use_hash_length int4 := 2;
|
||||
use_hash text;
|
||||
BEGIN
|
||||
LOOP
|
||||
use_hash := get_random_string(use_hash_length);
|
||||
BEGIN
|
||||
INSERT INTO plans (id, plan, is_public, entered_on, is_anonymized) values (use_hash, in_plan, in_is_public, now(), in_is_anonymized);
|
||||
RETURN use_hash;
|
||||
EXCEPTION WHEN unique_violation THEN
|
||||
-- do nothing
|
||||
END;
|
||||
use_hash_length := use_hash_length + 1;
|
||||
IF use_hash_length >= 30 THEN
|
||||
raise exception 'Random string of length == 30 requested. something''s wrong.';
|
||||
END IF;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
|
||||
--
|
||||
-- Name: register_plan(text, text, boolean, boolean); Type: FUNCTION; Schema: public; Owner: -
|
||||
--
|
||||
|
||||
CREATE FUNCTION register_plan(in_title text, in_plan text, in_is_public boolean, in_is_anonymized boolean) RETURNS text
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
DECLARE
|
||||
use_hash_length int4 := 2;
|
||||
use_hash text;
|
||||
BEGIN
|
||||
LOOP
|
||||
use_hash := get_random_string(use_hash_length);
|
||||
BEGIN
|
||||
INSERT INTO plans (id, title, plan, is_public, entered_on, is_anonymized) values (use_hash, in_title, in_plan, in_is_public, now(), in_is_anonymized);
|
||||
RETURN use_hash;
|
||||
EXCEPTION WHEN unique_violation THEN
|
||||
-- do nothing
|
||||
END;
|
||||
use_hash_length := use_hash_length + 1;
|
||||
IF use_hash_length >= 30 THEN
|
||||
raise exception 'Random string of length == 30 requested. something''s wrong.';
|
||||
END IF;
|
||||
END LOOP;
|
||||
END;
|
||||
$$;
|
||||
|
||||
|
||||
SET default_tablespace = '';
|
||||
|
||||
SET default_with_oids = false;
|
||||
|
||||
--
|
||||
-- Name: another; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
||||
--
|
||||
|
||||
CREATE TABLE another (
|
||||
i integer
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: plans; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
||||
--
|
||||
|
||||
CREATE TABLE plans (
|
||||
id text NOT NULL,
|
||||
plan text NOT NULL,
|
||||
entered_on timestamp with time zone DEFAULT now() NOT NULL,
|
||||
is_public boolean DEFAULT true NOT NULL,
|
||||
is_anonymized boolean DEFAULT false NOT NULL,
|
||||
title text
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: z; Type: TABLE; Schema: public; Owner: -; Tablespace:
|
||||
--
|
||||
|
||||
CREATE TABLE z (
|
||||
i integer NOT NULL,
|
||||
j integer NOT NULL
|
||||
);
|
||||
|
||||
|
||||
--
|
||||
-- Name: plans_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY plans
|
||||
ADD CONSTRAINT plans_pkey PRIMARY KEY (id);
|
||||
|
||||
|
||||
--
|
||||
-- Name: z_i_key; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY z
|
||||
ADD CONSTRAINT z_i_key UNIQUE (i);
|
||||
|
||||
|
||||
--
|
||||
-- Name: z_pkey; Type: CONSTRAINT; Schema: public; Owner: -; Tablespace:
|
||||
--
|
||||
|
||||
ALTER TABLE ONLY z
|
||||
ADD CONSTRAINT z_pkey PRIMARY KEY (j, i);
|
||||
|
||||
|
||||
--
|
||||
-- Name: r; Type: INDEX; Schema: public; Owner: -; Tablespace:
|
||||
--
|
||||
|
||||
CREATE UNIQUE INDEX r ON z USING btree (j);
|
||||
|
||||
|
||||
--
|
||||
-- PostgreSQL database dump complete
|
||||
--
|
||||
|
||||
|
@ -15,6 +15,8 @@
|
||||
<form id="new-explain" method="post" action="<%= url_for 'current' %>">
|
||||
|
||||
<div class="fe fe-first fe_plan">
|
||||
<label for="title">Optional title for plan:</label>
|
||||
<input id="title" name="title" class="auto-hint" title="Optional title"/>
|
||||
<label for="plan">Paste your explain/explain analyze here:</label>
|
||||
<textarea id="plan" name="plan" class="auto-hint" title="For example:
|
||||
QUERY PLAN
|
||||
|
@ -1,7 +1,9 @@
|
||||
% layout 'default';
|
||||
|
||||
% my $title = stash( 'id' );
|
||||
% title $title;
|
||||
% my $id = stash( 'id' );
|
||||
% my $title = stash( 'title' );
|
||||
% my $full_title = $title ? "$id : $title" : $id;
|
||||
% title $full_title;
|
||||
|
||||
|
||||
%# c = e|i|x|m (colorize = exclusive|inclusive|rows-x|mixed)
|
||||
@ -122,10 +124,10 @@
|
||||
|
||||
<tr class="n <%= $row_class %>" data-node_id="<%= $node_id =%>" data-node_parent="<%= $parent =%>" data-level="<%= $level =%>" data-e="<%= $exclusive_point =%>" data-i="<%= $inclusive_point =%>" data-x="<%= $rows_x_point =%>">
|
||||
<td class="e c-<%= $exclusive_point =%><%= $cfg->{ ve } ? '' : ' tight' %>">
|
||||
<span><%= sprintf '%.3f', $node->total_exclusive_time =%></span>
|
||||
<span><%= sprintf '%.3f', defined $node->total_exclusive_time ? $node->total_exclusive_time : 0 =%></span>
|
||||
</td>
|
||||
<td class="i c-<%= $inclusive_point =%><%= $cfg->{ vi } ? '' : ' tight' %>">
|
||||
<span><%= sprintf '%.3f', $node->total_inclusive_time =%></span>
|
||||
<span><%= sprintf '%.3f', defined $node->total_inclusive_time ? $node->total_inclusive_time : 0 =%></span>
|
||||
</td>
|
||||
<td class="x c-<%= $rows_x_point =%><%= $cfg->{ vx } ? '' : ' tight' %>">
|
||||
<span>
|
||||
@ -270,7 +272,7 @@
|
||||
|
||||
% end;
|
||||
|
||||
<h1>Result: <%= $title %></h1>
|
||||
<h1>Result: <%= $full_title %></h1>
|
||||
|
||||
<div class="explain-form">
|
||||
|
||||
|
Reference in New Issue
Block a user