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
|
# anonymization
|
||||||
my $is_anon = $self->req->param( 'is_anon' ) ? 1 : 0;
|
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
|
# try
|
||||||
eval {
|
eval {
|
||||||
|
|
||||||
@ -54,10 +59,12 @@ sub index {
|
|||||||
eval {
|
eval {
|
||||||
|
|
||||||
# send mail
|
# send mail
|
||||||
$self->send_mail( {
|
$self->send_mail(
|
||||||
|
{
|
||||||
subject => q|Can't create explain from...|,
|
subject => q|Can't create explain from...|,
|
||||||
msg => $plan
|
msg => $plan
|
||||||
} );
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
# leave...
|
# leave...
|
||||||
@ -65,7 +72,7 @@ sub index {
|
|||||||
}
|
}
|
||||||
|
|
||||||
# save to database
|
# 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
|
# redirect to /show/:id
|
||||||
return $self->redirect_to( 'show', id => $id );
|
return $self->redirect_to( 'show', id => $id );
|
||||||
@ -75,14 +82,13 @@ sub show {
|
|||||||
my $self = shift;
|
my $self = shift;
|
||||||
|
|
||||||
# value of "/:id" param
|
# value of "/:id" param
|
||||||
my $id = defined $self->stash->{ id }
|
my $id = defined $self->stash->{ id } ? $self->stash->{ id } : '';
|
||||||
? $self->stash->{ id } : '';
|
|
||||||
|
|
||||||
# missing or invalid
|
# missing or invalid
|
||||||
return $self->redirect_to( 'new-explain' ) unless $id =~ m{\A[a-zA-Z0-9]+\z};
|
return $self->redirect_to( 'new-explain' ) unless $id =~ m{\A[a-zA-Z0-9]+\z};
|
||||||
|
|
||||||
# get plan source from database
|
# get plan source from database
|
||||||
my $plan = $self->database->get_plan( $id );
|
my ( $plan, $title ) = $self->database->get_plan( $id );
|
||||||
|
|
||||||
# not found in database
|
# not found in database
|
||||||
return $self->redirect_to( 'new-explain', status => 404 ) unless $plan;
|
return $self->redirect_to( 'new-explain', status => 404 ) unless $plan;
|
||||||
@ -105,8 +111,9 @@ sub show {
|
|||||||
return $self->redirect_to( 'new-explain' );
|
return $self->redirect_to( 'new-explain' );
|
||||||
}
|
}
|
||||||
|
|
||||||
# put explain to stash
|
# put explain and title to stash
|
||||||
$self->stash->{ explain } = $explain;
|
$self->stash->{ explain } = $explain;
|
||||||
|
$self->stash->{ title } = $title;
|
||||||
|
|
||||||
# render will be called automatically
|
# render will be called automatically
|
||||||
return;
|
return;
|
||||||
@ -138,19 +145,18 @@ sub contact {
|
|||||||
unless Email::Valid->address( $self->req->param( 'email' ) || '' );
|
unless Email::Valid->address( $self->req->param( 'email' ) || '' );
|
||||||
|
|
||||||
# send
|
# send
|
||||||
$self->send_mail( {
|
$self->send_mail(
|
||||||
|
{
|
||||||
msg => sprintf(
|
msg => sprintf(
|
||||||
"\nMessage from: %s <%s>" .
|
"\nMessage from: %s <%s>" . "\nPosted from: %s with %s" . "\n****************************************\n\n" . "%s",
|
||||||
"\nPosted from: %s with %s" .
|
|
||||||
"\n****************************************\n\n" .
|
|
||||||
"%s",
|
|
||||||
$self->req->param( 'name' ) || '',
|
$self->req->param( 'name' ) || '',
|
||||||
$self->req->param( 'email' ),
|
$self->req->param( 'email' ),
|
||||||
$self->tx->remote_address,
|
$self->tx->remote_address,
|
||||||
$self->req->headers->user_agent,
|
$self->req->headers->user_agent,
|
||||||
$self->req->param( 'message' )
|
$self->req->param( 'message' )
|
||||||
)
|
)
|
||||||
} );
|
}
|
||||||
|
);
|
||||||
|
|
||||||
# mail sent message
|
# mail sent message
|
||||||
$self->flash( message => 'Mail sent' );
|
$self->flash( message => 'Mail sent' );
|
||||||
@ -160,6 +166,7 @@ sub contact {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub help {
|
sub help {
|
||||||
|
|
||||||
# direct to template
|
# direct to template
|
||||||
return ( shift )->render;
|
return ( shift )->render;
|
||||||
}
|
}
|
||||||
|
@ -66,13 +66,13 @@ sub register {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sub save_with_random_name {
|
sub save_with_random_name {
|
||||||
my ( $self, $content, $is_public, $is_anon ) = @_;
|
my ( $self, $title, $content, $is_public, $is_anon ) = @_;
|
||||||
|
|
||||||
# create statement handler
|
# create statement handler
|
||||||
my $sth = $self->dbh->prepare( 'SELECT register_plan(?, ?, ?)' );
|
my $sth = $self->dbh->prepare( 'SELECT register_plan(?, ?, ?, ?)' );
|
||||||
|
|
||||||
# execute
|
# execute
|
||||||
$sth->execute( $content, $is_public, $is_anon );
|
$sth->execute( $title, $content, $is_public, $is_anon );
|
||||||
|
|
||||||
# register_plan returns plan id
|
# register_plan returns plan id
|
||||||
my @row = $sth->fetchrow_array;
|
my @row = $sth->fetchrow_array;
|
||||||
@ -90,7 +90,7 @@ sub get_plan {
|
|||||||
my ( $self, $plan_id ) = @_;
|
my ( $self, $plan_id ) = @_;
|
||||||
|
|
||||||
# create statement handler
|
# 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
|
# execute
|
||||||
$sth->execute( $plan_id );
|
$sth->execute( $plan_id );
|
||||||
@ -102,7 +102,7 @@ sub get_plan {
|
|||||||
$sth->finish;
|
$sth->finish;
|
||||||
|
|
||||||
# return plan
|
# return plan
|
||||||
return $row[ 0 ];
|
return @row;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub get_public_list {
|
sub get_public_list {
|
||||||
|
201
sql/create.sql
Executable file → Normal file
201
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 FUNCTION get_random_string(string_length integer) RETURNS text
|
||||||
CREATE TABLE plans (
|
LANGUAGE plpgsql
|
||||||
id TEXT PRIMARY KEY,
|
AS $$
|
||||||
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 $$
|
|
||||||
DECLARE
|
DECLARE
|
||||||
possible_chars TEXT = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
possible_chars TEXT = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
|
||||||
output TEXT = '';
|
output TEXT = '';
|
||||||
@ -34,34 +38,167 @@ DECLARE
|
|||||||
pos INT4;
|
pos INT4;
|
||||||
BEGIN
|
BEGIN
|
||||||
FOR i IN 1..string_length LOOP
|
FOR i IN 1..string_length LOOP
|
||||||
pos := 1 + cast( random( ) * ( length( possible_chars ) - 1 ) AS INT4 );
|
pos := 1 + cast( random() * ( length(possible_chars) - 1) as INT4 );
|
||||||
output := output || substr(possible_chars, pos, 1);
|
output := output || substr(possible_chars, pos, 1);
|
||||||
END LOOP;
|
END LOOP;
|
||||||
RETURN output;
|
RETURN output;
|
||||||
END;
|
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
|
DECLARE
|
||||||
use_hash_length INT4 := 2;
|
use_hash_length int4 := 2;
|
||||||
use_hash TEXT;
|
use_hash text;
|
||||||
BEGIN
|
BEGIN
|
||||||
LOOP
|
LOOP
|
||||||
use_hash := get_random_string(use_hash_length);
|
use_hash := get_random_string(use_hash_length);
|
||||||
|
|
||||||
BEGIN
|
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;
|
RETURN use_hash;
|
||||||
EXCEPTION when unique_violation THEN
|
EXCEPTION WHEN unique_violation THEN
|
||||||
-- do nothing
|
-- do nothing
|
||||||
END;
|
END;
|
||||||
|
|
||||||
use_hash_length := use_hash_length + 1;
|
use_hash_length := use_hash_length + 1;
|
||||||
|
|
||||||
IF use_hash_length >= 30 THEN
|
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 IF;
|
||||||
|
|
||||||
END LOOP;
|
END LOOP;
|
||||||
END;
|
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' %>">
|
<form id="new-explain" method="post" action="<%= url_for 'current' %>">
|
||||||
|
|
||||||
<div class="fe fe-first fe_plan">
|
<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>
|
<label for="plan">Paste your explain/explain analyze here:</label>
|
||||||
<textarea id="plan" name="plan" class="auto-hint" title="For example:
|
<textarea id="plan" name="plan" class="auto-hint" title="For example:
|
||||||
QUERY PLAN
|
QUERY PLAN
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
% layout 'default';
|
% layout 'default';
|
||||||
|
|
||||||
% my $title = stash( 'id' );
|
% my $id = stash( 'id' );
|
||||||
% title $title;
|
% 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)
|
%# 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 =%>">
|
<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' %>">
|
<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>
|
||||||
<td class="i c-<%= $inclusive_point =%><%= $cfg->{ vi } ? '' : ' tight' %>">
|
<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>
|
||||||
<td class="x c-<%= $rows_x_point =%><%= $cfg->{ vx } ? '' : ' tight' %>">
|
<td class="x c-<%= $rows_x_point =%><%= $cfg->{ vx } ? '' : ' tight' %>">
|
||||||
<span>
|
<span>
|
||||||
@ -270,7 +272,7 @@
|
|||||||
|
|
||||||
% end;
|
% end;
|
||||||
|
|
||||||
<h1>Result: <%= $title %></h1>
|
<h1>Result: <%= $full_title %></h1>
|
||||||
|
|
||||||
<div class="explain-form">
|
<div class="explain-form">
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user