Some more files:
+ contrib/pls-mode.el: pls-mode for emacs. Used for building PL/SQL files. + docs/oracle-lisp-functions.txt: Another document file + For creating explain plans.
This commit is contained in:
parent
af1b40838a
commit
f33add7663
3 changed files with 4504 additions and 0 deletions
4249
contrib/pls-mode.el
Normal file
4249
contrib/pls-mode.el
Normal file
File diff suppressed because it is too large
Load diff
71
docs/oracle-lisp-functions.txt
Normal file
71
docs/oracle-lisp-functions.txt
Normal file
|
@ -0,0 +1,71 @@
|
|||
- get-explain-plan-for-region
|
||||
+ determine enode-stage-buffer
|
||||
~ create a buffer called " *enode-stage-buffer*"
|
||||
~ empty it
|
||||
+ go to that buffer
|
||||
+ add the SQL text to plan
|
||||
+ get-explain-plan
|
||||
~ set the progress message
|
||||
~ Determine the get-statement-id
|
||||
* Return a string of the format ENODE_YYYYMMDD_HH24MMSS
|
||||
~ prepare the plan with enode-prepare-explain-plan
|
||||
* Determine the full explain plan command with
|
||||
get-sql-explain-plan-command
|
||||
$ return the string starting with "explain plan..." and finishing
|
||||
with get-sql-command-to-explain
|
||||
> return the SQL command to explain with blank lines and ';'
|
||||
characters removed.
|
||||
* Send the explain plan command to the SQL buffer and redirect output
|
||||
$ to a buffer determined by enode-temp-output-buffer
|
||||
$ create a buffer named " *enode-comint-sql-output*"
|
||||
$ empty it
|
||||
* wait for command to complete with enode-oracle-wait-for-command
|
||||
~ enode-output-explain-plan
|
||||
* Get the line size
|
||||
$ run "show linesize" through enode-oracle-get-sqlplus-param
|
||||
* Get the page size
|
||||
$ run "show pagesize" through enode-oracle-get-sqlplus-param
|
||||
* get the explain plan output command from
|
||||
get-explain-plan-output-command
|
||||
$ return the SQL command to output an explain plan.
|
||||
* get the SQL buffer
|
||||
* clean output buffer
|
||||
* prepare the sql buffer with prepare-sql-buffer-for-command
|
||||
$ set the SQL parameters heading(off), linesize(1024) and
|
||||
pagesize(0) with enode-oracle-set-sqlplus-param
|
||||
> send the "set" command to the SQL buffer redirecting any output
|
||||
* send the command, redirecting the output
|
||||
* wait for command to complete with enode-oracle-wait-for-command
|
||||
* Set the SQL buffer back to it's standard output presentation with
|
||||
reset-sql-buffer-after-command
|
||||
$ Sets the heading(on), pagesize(original_val) and
|
||||
linesize(original_val) SQL*Plus parameters.
|
||||
~ enode-oracle-remove-prompt-from-plan-output
|
||||
* Get the prompt from enode-oracle-get-sql-prompt
|
||||
$ Return the sqlprompt parameter through
|
||||
enode-oracle-get-sqlplus-param
|
||||
* replace every instance of the prompt with "" in the buffer.
|
||||
~ present the buffer with the plan
|
||||
|
||||
|
||||
- Present the PL/SQL code
|
||||
+ Determine a buffer to take the code.
|
||||
~ enode-pls-code-buffer
|
||||
+ Determine SQL buffer settings
|
||||
~ line size
|
||||
~ page size
|
||||
+ Query the longest line in the PL/SQL block sending the output to the
|
||||
prepared buffer
|
||||
~ enode-oracle-plsql-max-line-length
|
||||
+ Prepare the SQL buffer for the output
|
||||
~ set heading off
|
||||
~ set linesize to the longest line
|
||||
~ set pagesize 0
|
||||
+ Send the select statement to the SQL buffer sending output to the
|
||||
prepared buffer
|
||||
~ comint...
|
||||
+ Reset the SQL buffer.
|
||||
~ set heading on
|
||||
~ set linesize to original value
|
||||
~ set pagesize to original value
|
||||
+ Present the buffer with the PL/SQL code
|
184
enode-lisp/planner.el
Executable file
184
enode-lisp/planner.el
Executable file
|
@ -0,0 +1,184 @@
|
|||
;; (load-file "enode-experiments.el")
|
||||
|
||||
;; The customisation group. Will in the ENODE group.
|
||||
(defgroup enode-planner nil
|
||||
"A group for customising the ENODE-PLANNER functionality."
|
||||
:group 'ENODE
|
||||
:version "21.2"
|
||||
)
|
||||
|
||||
;; What table the execution plan should be made from
|
||||
(defcustom enode-planner-plan-table "PLAN_TABLE"
|
||||
"The table that the will be used for generating an execution plan for
|
||||
queries. Defaults to PLAN_TABLE, but can, of course, be anything else."
|
||||
:type 'string
|
||||
:group 'enode-planner
|
||||
:version "21.2"
|
||||
)
|
||||
|
||||
(defun enode-oracle-remove-prompt-from-plan-output (plan-buffer)
|
||||
"A function to clean the explain plan output of the sqlprompt string"
|
||||
(let ((sql-prompt (enode-oracle-get-sql-prompt)))
|
||||
(save-excursion
|
||||
(set-buffer plan-buffer)
|
||||
(goto-char (point-min))
|
||||
(while (search-forward sql-prompt nil t)
|
||||
(replace-match "" nil nil)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun enode-plan-buffer ()
|
||||
"A function to return the buffer assigned for the explain plan output"
|
||||
(get-buffer-create "*enode-explain-plan*"))
|
||||
|
||||
(defun get-statement-id ()
|
||||
"A function to generate a unique statement id for the explain plan"
|
||||
(format "ENODE_%s_%s"
|
||||
(format-time-string "%Y%m%d")
|
||||
(format-time-string "%H%M%S"))
|
||||
)
|
||||
|
||||
(defun prepare-sql-buffer-for-command ()
|
||||
"A function to prepare the SQLi buffer for an outputting command. It sets
|
||||
properties of the SQL*Plus process to value that make an explain plan output
|
||||
somewhat pretty."
|
||||
(enode-oracle-sqlplus-set-param "heading" "off")
|
||||
(enode-oracle-sqlplus-set-param "linesize" "1024")
|
||||
(enode-oracle-sqlplus-set-param "pagesize" "0")
|
||||
)
|
||||
|
||||
(defun reset-sql-buffer-after-command (page-size line-size)
|
||||
"A function to return the SQL*Plus process' setting to 'original' values. As
|
||||
well as setting PAGE-SIZE and LINE-SIZE, it also turns 'heading'
|
||||
on and 'sqlnumber' on."
|
||||
(enode-oracle-sqlplus-set-param "heading" "on")
|
||||
(enode-oracle-sqlplus-set-param "pagesize" page-size)
|
||||
(enode-oracle-sqlplus-set-param "linesize" line-size)
|
||||
)
|
||||
|
||||
(defun get-sql-explain-plan-command (enode-plan-statement-id)
|
||||
"A function to return the 'explain plan...' statement. It sets the
|
||||
statement_id to ENODE-PLAN-STATEMENT-ID. It also includes the sql command from
|
||||
the current buffer -- i.e. the command you want to analyse."
|
||||
(format
|
||||
"explain plan\nset statement_id = '%s'\ninto %s\nfor\n%s;"
|
||||
enode-plan-statement-id
|
||||
enode-planner-plan-table
|
||||
(get-sql-command-to-explain)
|
||||
)
|
||||
)
|
||||
|
||||
(defun get-sql-command-to-explain ()
|
||||
"A function to return as a string the SQL command in the current buffer.
|
||||
It assumes there is only one command. It replaces empty lines with a space and
|
||||
the ';' character with nothing."
|
||||
(replace-regexp-in-string "^[$\n]" " "
|
||||
(replace-regexp-in-string ";" "" (buffer-string)))
|
||||
)
|
||||
|
||||
(defun get-explain-plan-output-command (enode-plan-statement-id)
|
||||
"A function to return the command to generate the nice explain plan output.
|
||||
It uses ENODE-PLAN-STATEMENT-ID to determine which explain plan we want to
|
||||
look at."
|
||||
(format "SELECT LPAD ( ' ', LEVEL - 1 ) || decode ( position, null, '', position || '-' ) || operation || decode ( options, null, '', ' ' || options ) || decode ( object_name, null, '', ' ' || object_name ) || decode ( optimizer, null, '', ' Optimiser=''' || optimizer || '''' ) || decode ( cost, null, '', ' Cost=' || cost ) || decode ( cardinality, null, '', ' Cardinality=' || cardinality ) FROM %s START WITH id = 0 AND statement_id = '%s' CONNECT BY PRIOR id = parent_id AND statement_id = '%s';"
|
||||
enode-planner-plan-table
|
||||
enode-plan-statement-id
|
||||
enode-plan-statement-id)
|
||||
)
|
||||
|
||||
;;;; Change this to use enode-oracle-run-sql-command
|
||||
(defun enode-prepare-explain-plan (enode-plan-statement-id)
|
||||
"A function to prepare an explain plan. That is, it takes the SQL command
|
||||
in the current buffer and generates an explain plan in the PLAN_TABLE in it,
|
||||
using ENODE-PLAN-STATEMENT-ID as the statement_id value."
|
||||
(save-excursion
|
||||
;; Get the full explain plan command and the SQLi buffer to run it in.
|
||||
(let ((enode-sql-command
|
||||
(get-sql-explain-plan-command enode-plan-statement-id))
|
||||
(enode-sql-buffer sql-buffer)
|
||||
)
|
||||
;; Run the command.
|
||||
(comint-redirect-send-command-to-process
|
||||
enode-sql-command
|
||||
(enode-temp-output-buffer)
|
||||
enode-sql-buffer
|
||||
nil
|
||||
t
|
||||
)
|
||||
;; Allow the command to complete.
|
||||
(enode-wait-for-command)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
;;;; Change this to use enode-oracle-run-sql-command
|
||||
(defun enode-output-explain-plan (enode-plan-statement-id)
|
||||
"A function to display an explain plan that is already in the PLAN_TABLE. It
|
||||
identifies the plan with ENODE-PLAN-STATEMENT-ID."
|
||||
(save-excursion
|
||||
;; Get the linesize and pagesize values the command to run
|
||||
;; to generate the output and the SQLi buffer in which to run it.
|
||||
(let ((enode-line-size (enode-oracle-sqlplus-get-linesize))
|
||||
(enode-page-size (enode-oracle-sqlplus-get-pagesize))
|
||||
(enode-plan-output-command
|
||||
(get-explain-plan-output-command enode-plan-statement-id))
|
||||
(enode-sql-buffer sql-buffer)
|
||||
)
|
||||
;; Empty the explain plan output buffer.
|
||||
(enode-clean-buffer (enode-plan-buffer))
|
||||
;; Tell SQL*Plus we want pretty output for this command.
|
||||
(prepare-sql-buffer-for-command)
|
||||
;; Run the command.
|
||||
(comint-redirect-send-command-to-process
|
||||
enode-plan-output-command
|
||||
(enode-plan-buffer)
|
||||
enode-sql-buffer
|
||||
nil
|
||||
t)
|
||||
;; Allow the command to complete.
|
||||
(enode-wait-for-command)
|
||||
;; We're done with the nice output. Return SQL*Plus to it regular ugly
|
||||
;; stuff.
|
||||
(reset-sql-buffer-after-command
|
||||
enode-page-size enode-line-size)
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
(defun get-explain-plan (&optional present-plan-command-output-p)
|
||||
"A function to display an explain plan for an SQL command in the current
|
||||
buffer."
|
||||
;; We want to call this as a command
|
||||
(interactive "P")
|
||||
;; For feedback purposes
|
||||
(setq enode-oracle-progress-message ".")
|
||||
;; Generate a statement_id value for this plan.
|
||||
(let ((plan-statement-id (get-statement-id)))
|
||||
;; Generate the plan in the PLAN_TABLE
|
||||
(enode-prepare-explain-plan plan-statement-id)
|
||||
(if present-plan-command-output-p
|
||||
(save-excursion
|
||||
(display-buffer (get-buffer " *enode-comint-sql-output*"))
|
||||
(read-from-minibuffer "Hit return to continue...")))
|
||||
;; Send a nice representation of the plan to the plan buffer.
|
||||
(enode-output-explain-plan plan-statement-id)
|
||||
;; Clean up the buffer
|
||||
(enode-oracle-remove-prompt-from-plan-output (enode-plan-buffer))
|
||||
;; Show us the plan in another window.
|
||||
(pop-to-buffer (enode-plan-buffer))
|
||||
)
|
||||
)
|
||||
|
||||
(defun get-explain-plan-for-region (beg end &optional present-plan-command-output-p)
|
||||
"A function to take an SQL statement from the region and to
|
||||
get an explain plan for it."
|
||||
(interactive "r\nP")
|
||||
(let ((plan-command-buffer (enode-stage-buffer))
|
||||
(plan-command (buffer-substring beg end)))
|
||||
(set-buffer plan-command-buffer)
|
||||
(insert plan-command)
|
||||
(get-explain-plan present-plan-command-output-p)
|
||||
)
|
||||
)
|
Loading…
Reference in a new issue