enode/enode-lisp/enode-oracle.el

783 lines
28 KiB
EmacsLisp
Executable file

;; Copyright 2013 Éibhear Ó hAnluain
;; This file is part of ENODE.
;;
;; ENODE is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;;
;; ENODE is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;;
;; You should have received a copy of the GNU General Public License
;; along with ENODE. If not, see <http://www.gnu.org/licenses/>.
(defun enode-oracle-connect (conn-user conn-pass conn-connection conn-prompt)
"A function to connect to an oracle database."
;; Create a temporary buffer and go to it.
(with-temp-buffer
;; Set it to be an SQL commands buffer.
(sql-mode)
;; Put in the connection and sqlprompt modification commands, and
;; set the serverout on.
(insert
(format "\nconnect %s/%s@%s\nset serverout on\nset sqlprompt \"%s> \"\n"
conn-user
conn-pass
conn-connection
conn-prompt))
;; Send the temp buffer to the *SQL* process buffer.
(sql-send-region (point-min) (point-max))
)
)
(defun enode-oracle-disconnect ()
"A function to close an oracle database connection."
(with-temp-buffer
(sql-mode)
(insert (format "\ndisconnect\n"))
(sql-send-region (point-min) (point-max))
(enode-oracle-sqlplus-set-prompt "NOP")
)
)
(defun enode-oracle-start-sql-engine ()
"A function to set up the SQL engine for connecting to an Oracle database.
Currently, only SQL*Plus is supported."
(call-interactively 'sql-oracle)
;; Set the prompt regexps properly
(save-excursion
(set-buffer "*SQL*")
(setq comint-prompt-regexp "^[0-9A-Za-z]\\{3\\}> ")
(setq sql-prompt-regexp "^[0-9A-Za-z]\\{3\\}> ")
;; (enode-oracle-sqlplus-set-timing "on")
)
)
(defun enode-oracle-stop-sql-engine ()
"A function to close the engine connecting to the oracle database.
Currently, only SQL*Plus is supported."
;; Kludge to get around the fact that redirecting output from exit
;; doesn't really work.
(comint-send-string (get-buffer-process sql-buffer) (format "exit\n"))
(sleep-for 3)
;; (with-temp-buffer
;; (enode-oracle-run-sql-command "exit"
;; (current-buffer)
;; sql-buffer
;; t)
;; )
)
(defun enode-oracle-list-users (user-list-buffer)
"A function to list the users in an Oracle database."
(let ((user-list-command
(format "select username from all_users order by username;"))
)
;; Run the SQL command.
(enode-oracle-run-sql-command user-list-command
user-list-buffer
sql-buffer)
)
)
(defun enode-oracle-desc (object-name desc-buffer)
"A function to run the SQL DESCRIBE command for an object and to present
the output."
(let ((desc-command (format "desc %s" object-name)))
(enode-oracle-run-sql-command desc-command
desc-buffer
sql-buffer)
)
)
(defun enode-oracle-list-objects (object-list-buffer dbuser
&optional object-type
invalid-flag
filter-string)
"A function to get up a list of objects in an oracle database."
(let ((object-list-command
(format "%s%s%s;"
"select object_name, object_type, status "
(format "from %s " (if dbuser "all_objects" "user_objects"))
(let (have-where
where-clause)
(if dbuser
(if have-where
(setq where-clause
(concat where-clause
" "
(format "and owner = '%s' " dbuser)
)
)
(setq where-clause
(format "where owner = '%s' " dbuser))
(setq have-where t)
)
)
(if object-type
(if have-where
(setq where-clause
(concat where-clause
" "
(format "and object_type = '%s' "
object-type)
)
)
(setq where-clause
(format "where object_type = '%s' "
object-type))
(setq have-where t)
)
)
(if invalid-flag
(if have-where
(setq where-clause
(concat where-clause
" and status = 'INVALID' "
)
)
(setq where-clause
"where status = 'INVALID' ")
(setq have-where t)
)
)
(if filter-string
(if have-where
(setq where-clause
(concat where-clause
" and object_name like '%"
filter-string
"%' "
)
)
(setq where-clause
(concat "where object_name like '%"
filter-string
"%' ")
)
(setq have-where t)
)
)
where-clause
)
)
)
)
(enode-oracle-run-sql-command object-list-command
object-list-buffer
sql-buffer)
)
)
(defun enode-oracle-list-object-types (object-type-list-buffer
&optional dbuser)
"A function to show the list of object types in an oracle database broken
down by user. If DBUSER is non-nil, list only for that user."
(let ((object-type-list-command
(format "%s%s%s%s%s;"
"select owner, object_type, count(*) "
"from all_objects "
(if dbuser (format "where owner = '%s' " (upcase dbuser)) "")
"group by owner, object_type "
"order by owner, object_type "
))
)
;; Run the SQL command.
(enode-oracle-run-sql-command object-type-list-command
object-type-list-buffer
sql-buffer)
)
)
(defun enode-oracle-run-sql-command (sql-command output-buffer sql-buffer
&optional asynchronous)
"A function to run an SQL command in a synchronous manner. If ASYNCHRONOUS is non-nil, it's run, you guessed it, asynchronously."
;; Run it as though it's from where we're calling it.
(save-excursion
;; Run the command, not echoing the output.
(comint-redirect-send-command-to-process sql-command
output-buffer
sql-buffer
nil)
;; If we don't want to pretend it's synchronous, don't
(if (not asynchronous)
(enode-wait-for-command)
)
)
)
(defun enode-oracle-pls-code-max-length (pls-name pls-type &optional pls-owner)
"A function to return the length of the longest line in a block of
stored PL/SQL code."
;; Do all this in a temporary buffer
(with-temp-buffer
;; Get the buffer name
(let ((my-buffer (current-buffer))
;; Determine the code to run
(plsql-code-line-length-command
(format "%s%s%s%s%s;"
"select max ( length ( text ) ) "
(format "from %s " (if pls-owner "all_source"
"user_source"))
(format "where name = '%s' " (upcase pls-name))
(format "and type = '%s' " (upcase pls-type))
(if pls-owner (format "and owner = '%s' "
(upcase pls-owner))
""))))
;; Run the command synchronously
(enode-oracle-run-sql-command plsql-code-line-length-command
my-buffer
sql-buffer)
;; Go to the buffer
(set-buffer my-buffer)
;; Go to the end
(goto-char (point-max))
;; Look back for the returned value
(re-search-backward "^[ ]+\\([0-9]+\\)[ ]*$")
;; and return it.
(match-string 1)
)
)
)
(defun enode-oracle-get-pls-code (pls-name pls-type &optional pls-owner)
"A function to present a block of PL/SQL code. Really should be called from
a wrapper. PLS-NAME is the name of the PL/SQL block, PLS-TYPE is its type
function, package, etc. and PLS-OWNER is the block's owner. If
PLS-OWNER is NIL, assume the current user."
;; Get the length of the longest line of the code block
(let ((block-line-length
(enode-oracle-pls-code-max-length pls-name pls-type pls-owner))
;; Determine the current SQL*Plus state
(current-sqlplus-state (enode-oracle-sqlplus-get-state))
;; Get a buffer for the code.
(code-buffer (enode-oracle-plsql-code-buffer pls-name pls-owner))
)
;; Set the SQL*Plus state to something that's suitable for this
;; '(LINESIZE PAGESIZE TIMING HEADING FEEDBACK LONG TRIMOUT TRIMSPOOL
;; LONGCHUNKSIZE TERMOUT)
(enode-oracle-sqlplus-set-state (list block-line-length 0 nil "off"
"off" nil)
)
;; Create the SQL code to get the PL/SQL code.
(let ((plsql-code-command
(format "%s%s%s%s%s%s;"
"select text "
(format "from %s " (if pls-owner "all_source"
"user_source"))
(format "where name = '%s' " (upcase pls-name))
(format "and type = '%s' " (upcase pls-type))
(if pls-owner (format "and owner = '%s' "
(upcase pls-owner))
"")
"order by line")))
;; Run the command.
(enode-oracle-run-sql-command plsql-code-command code-buffer sql-buffer)
)
;; Restore the state
(enode-oracle-sqlplus-set-state current-sqlplus-state)
(save-excursion
;; Go to the buffer with the code.
(set-buffer code-buffer)
;; It's PL/SQL code, set the mode.
(pls-mode)
)
(display-buffer code-buffer)
)
)
(defun enode-oracle-timing-on ()
"Turn on timing reports for SQL*Plus commands"
(interactive)
(enode-oracle-sqlplus-set-timing "on")
)
(defun enode-oracle-get-pls-package-code (proc-name &optional proc-owner)
"A function to return the code of a PL/SQL package spec."
(interactive (list (read-from-minibuffer "Package Name: ")))
(enode-oracle-get-pls-code proc-name "package" proc-owner))
(defun enode-oracle-get-pls-package-body-code (proc-name &optional proc-owner)
"A function to return the code of a PL/SQL package body."
(interactive (list (read-from-minibuffer "Package Name: ")))
(enode-oracle-get-pls-code proc-name "package body" proc-owner))
(defun enode-oracle-get-pls-procedure-code (proc-name &optional proc-owner)
"A function to return the code of a PL/SQL procedure."
(interactive (list (read-from-minibuffer "Procedure Name: ")))
(enode-oracle-get-pls-code proc-name "procedure" proc-owner))
(defun enode-oracle-get-pls-function-code (func-name &optional func-owner)
"A function to return the code of a PL/SQL function."
(interactive (list (read-from-minibuffer "Function Name: ")))
(enode-oracle-get-pls-code func-name "function" func-owner))
(defun enode-oracle-sqlplus-get-state ()
"A function to determine the current state of the SQL*Plus interface. It
returns a list in the following format '(LINESIZE PAGESIZE TIMING HEADING FEEDBACK LONG TRIMOUT TRIMSPOOL LONGCHUNKSIZE TERMOUT)."
;; Get the settings.
(let ((current-linesize (enode-oracle-sqlplus-get-linesize))
(current-pagesize (enode-oracle-sqlplus-get-pagesize))
(current-timing (enode-oracle-sqlplus-get-timing))
(current-heading (enode-oracle-sqlplus-get-heading))
(current-feedback (enode-oracle-sqlplus-get-feedback))
(current-long (enode-oracle-sqlplus-get-long))
(current-trimout (enode-oracle-sqlplus-get-trimout))
(current-trimspool (enode-oracle-sqlplus-get-trimspool))
(current-longchunksize (enode-oracle-sqlplus-get-longchunksize))
(current-termout (enode-oracle-sqlplus-get-termout))
)
;; Return the settings as a list.
(list current-linesize current-pagesize current-timing current-heading
current-feedback current-long current-trimout current-trimspool
current-longchunksize current-termout)
)
)
(defun enode-oracle-sqlplus-set-state (sqlplus-state)
"A function to put the current SQL*Plus interface into a certain statd. It
takes a list in the following format '(LINESIZE PAGESIZE TIMING HEADING FEEDBACK LONG TRIMOUT TRIMSPOOL LONGCHUNKSIZE TERMOUT).
If any of this is NIL, it's not touched"
;; Determine the settings
(let ((new-linesize (nth 0 sqlplus-state))
(new-pagesize (nth 1 sqlplus-state))
(new-timing (nth 2 sqlplus-state))
(new-heading (nth 3 sqlplus-state))
(new-feedback (nth 4 sqlplus-state))
(new-long (nth 5 sqlplus-state))
(new-trimout (nth 6 sqlplus-state))
(new-trimspool (nth 7 sqlplus-state))
(new-longchunksize (nth 8 sqlplus-state))
(new-termout (nth 9 sqlplus-state))
)
;; For each of the settings that are specified in the parameter,
;; set it.
(if new-linesize (enode-oracle-sqlplus-set-linesize new-linesize))
(if new-pagesize (enode-oracle-sqlplus-set-pagesize new-pagesize))
(if new-timing (enode-oracle-sqlplus-set-timing new-timing))
(if new-heading (enode-oracle-sqlplus-set-heading new-heading))
(if new-feedback (enode-oracle-sqlplus-set-feedback new-feedback))
(if new-long (enode-oracle-sqlplus-set-long new-long))
(if new-trimout (enode-oracle-sqlplus-set-trimout new-trimout))
(if new-trimspool (enode-oracle-sqlplus-set-trimspool new-trimspool))
(if new-longchunksize
(enode-oracle-sqlplus-set-longchunksize new-longchunksize))
(if new-termout (enode-oracle-sqlplus-set-termout new-termout))
)
)
(defun enode-oracle-plsql-code-buffer
(&optional pls-block-name pls-block-owner)
"A function to return a buffer to contain the code of a PL/SQL object. The
name of the buffer encorporates the name of the block if not nil"
(enode-code-buffer "plsql" pls-block-name pls-block-owner)
)
(defun enode-oracle-view-code-buffer
(&optional view-name view-owner)
"A function to return a buffer to contain the code of a view. The
name of the buffer encorporates the name of the block if not nil"
(enode-code-buffer "view" view-name view-owner)
)
(defun enode-oracle-view-length (view-name &optional view-owner)
"A function to return the length of the code making up the definition of
a view."
;; Do all this in a temporary buffer
(with-temp-buffer
;; What buffer?
(let ((my-buffer (current-buffer))
;; Create the SQL command to determine the value
(view-code-length-command
(format "%s%s%s%s;"
"select text_length "
(format "from %s " (if view-owner "all_views"
"user_views"))
(format "where view_name = '%s' " (upcase view-name))
(if view-owner (format "and owner = '%s' "
(upcase view-owner))
""))))
;; Run the command.
(enode-oracle-run-sql-command view-code-length-command
my-buffer
sql-buffer)
;; Go to the output buffer
(set-buffer my-buffer)
;; Go to the end.
(goto-char (point-max))
;; Look for the output
(re-search-backward "^[ ]+\\([0-9]+\\)[ ]*$")
;; Return it
(match-string 1)
)
)
)
(defun enode-oracle-get-view-code (view-name &optional view-owner)
"A function to present the code that makes up a view."
(interactive (list (read-from-minibuffer "View name: ")))
;; Get the current SQL*Plus state
(let ((current-sqlplus-state (enode-oracle-sqlplus-get-state))
;; The buffer to send the code to
(code-buffer (enode-oracle-view-code-buffer view-name view-owner))
)
;; Set the SQL*Plus state to something that is suitable.
;; '(LINESIZE PAGESIZE TIMING HEADING FEEDBACK LONG TRIMOUT TRIMSPOOL
;; LONGCHUNKSIZE TERMOUT)
(enode-oracle-sqlplus-set-state (list 2499 0 "off" "off" "off" 5242880 "on"
"on" 2499 "off"))
;; Create the command to get the code.
(let ((view-command
;; select dbms_metadate.get_ddl ( 'VIEW', '<<VIEW_NAME>>' )
;; from dual
(format "%s%s%s;"
"select dbms_metadata.get_ddl ( 'VIEW', '"
(upcase view-name)
"' ) from dual"
)))
;; Run the command.
(enode-oracle-run-sql-command view-command code-buffer sql-buffer)
)
;; Restore the SQL*Plus state.
(enode-oracle-sqlplus-set-state current-sqlplus-state)
(save-excursion
;; Go to the buffer
(set-buffer code-buffer)
;; It's SQL code. Set the mode.
(sql-mode)
)
(display-buffer code-buffer)
)
)
;;;; Change this to use enode-oracle-run-sql-command
(defun enode-oracle-sqlplus-get-param (sql-setting-command sql-setting-regexp)
"A function to get an SQL*Plus setting. It simply runs SQL-SETTING-COMMAND
and looks in the output for the first parenthesized expression in
SQL-SETTING-REGEXP."
;; We don't want to disturb anything, now do we?
(save-excursion
;; Get an empty output buffer
(let ((output-buffer (enode-temp-output-buffer)))
;; Send the command that was passed to get the setting.
(comint-redirect-send-command-to-process
sql-setting-command output-buffer sql-buffer nil t)
;; Go to the output buffer
(set-buffer output-buffer)
;; Wait a short period for the command to complete
(enode-wait-for-command)
;; Go to the last position
(goto-char (point-max))
;; Search backwards for the passed regular expression
(search-backward-regexp sql-setting-regexp nil t)
;; Return the first parenthesised expression from a matched string.
(match-string 1)
)
)
)
(defun enode-oracle-get-sql-prompt ()
"A function to get the setting of the SQL*Plus prompt"
(format "%s"
(enode-oracle-sqlplus-get-param
"show sqlprompt" "sqlprompt \"\\([^\"]*\\)\"$")
)
)
(defun enode-oracle-sqlplus-set-prompt (value)
"A function to set the 'sqlprompt' SQL*Plus parameter to VALUE."
(enode-oracle-sqlplus-set-param "sqlprompt" (concat "\"" value "> \""))
)
(defun enode-oracle-sqlplus-get-linesize ()
"A function to get the 'linesize' SQL*Plus setting"
(format "%s"
(enode-oracle-sqlplus-get-param
"show linesize" "linesize \\([0-9]+\\)$")
)
)
(defun enode-oracle-sqlplus-set-linesize (value)
"A function to set the 'linesize' SQL*Plus parameter to VALUE."
(enode-oracle-sqlplus-set-param "linesize" value)
)
(defun enode-oracle-sqlplus-get-long ()
"A function to get the 'long' SQL*Plus setting"
(format "%s"
(enode-oracle-sqlplus-get-param
"show long" "long \\([0-9]+\\)$")
)
)
(defun enode-oracle-sqlplus-set-long (value)
"A function to set the 'long' SQL*Plus parameter to VALUE."
(enode-oracle-sqlplus-set-param "long" value)
)
(defun enode-oracle-sqlplus-get-longchunksize ()
"A function to get the 'longchunksize' SQL*Plus setting"
(format "%s"
(enode-oracle-sqlplus-get-param
"show longchunksize" "longchunksize \\([0-9]+\\)$")
)
)
(defun enode-oracle-sqlplus-set-longchunksize (value)
"A function to set the 'longchunksize' SQL*Plus parameter to VALUE."
(enode-oracle-sqlplus-set-param "longchunksize" value)
)
(defun enode-oracle-sqlplus-get-pagesize ()
"A function to get the 'pagesize' SQL*Plus setting"
(format "%s"
(enode-oracle-sqlplus-get-param
"show pagesize" "^pagesize \\([0-9]+\\)$")
)
)
(defun enode-oracle-sqlplus-set-pagesize (value)
"A function to set the 'pagesize' SQL*Plus parameter to VALUE."
(enode-oracle-sqlplus-set-param "pagesize" value)
)
(defun enode-oracle-sqlplus-get-heading ()
"A function to get the 'heading' SQL*Plus setting"
(format "%s"
(enode-oracle-sqlplus-get-param
"show heading" "^heading \\(O[NF]+\\)$")
)
)
(defun enode-oracle-sqlplus-set-heading (value)
"A function to set the 'heading' SQL*Plus parameter to VALUE."
(enode-oracle-sqlplus-set-param "heading" value)
)
(defun enode-oracle-sqlplus-get-timing ()
"A function to get the 'timing' SQL*Plus setting"
(format "%s"
(enode-oracle-sqlplus-get-param
"show timing" "^timing \\(O[NF]+\\)$")
)
)
(defun enode-oracle-sqlplus-set-timing (value)
"A function to set the 'timing' SQL*Plus parameter to VALUE."
(enode-oracle-sqlplus-set-param "timing" value)
)
(defun enode-oracle-sqlplus-get-termout ()
"A function to get the 'termout' SQL*Plus setting"
(format "%s"
(enode-oracle-sqlplus-get-param
"show termout" "^termout \\(O[NF]+\\)$")
)
)
(defun enode-oracle-sqlplus-set-termout (value)
"A function to set the 'termout' SQL*Plus parameter to VALUE."
(enode-oracle-sqlplus-set-param "termout" value)
)
(defun enode-oracle-sqlplus-get-trimout ()
"A function to get the 'trimout' SQL*Plus setting"
(format "%s"
(enode-oracle-sqlplus-get-param
"show trimout" "^trimout \\(O[NF]+\\)$")
)
)
(defun enode-oracle-sqlplus-set-trimout (value)
"A function to set the 'trimout' SQL*Plus parameter to VALUE."
(enode-oracle-sqlplus-set-param "trimout" value)
)
(defun enode-oracle-sqlplus-get-trimspool ()
"A function to get the 'trimspool' SQL*Plus setting"
(format "%s"
(enode-oracle-sqlplus-get-param
"show trimspool" "^trimspool \\(O[NF]+\\)$")
)
)
(defun enode-oracle-sqlplus-set-trimspool (value)
"A function to set the 'trimspool' SQL*Plus parameter to VALUE."
(enode-oracle-sqlplus-set-param "trimspool" value)
)
(defun enode-oracle-sqlplus-get-feedback ()
"A function to get the 'feedback' SQL*Plus setting"
(format "%s"
(enode-oracle-sqlplus-get-param
"show feedback" "^FEEDBACK \\(O[NF]+\\).*$")
)
)
(defun enode-oracle-sqlplus-set-feedback (value)
"A function to set the 'feedback' SQL*Plus parameter to VALUE."
(enode-oracle-sqlplus-set-param "feedback" value)
)
;; This is useful for main ENODE environment.
;;;; Is this necessary if we user with-temp-buffer()?
(defun enode-temp-output-buffer ()
"A function to return the temporary output buffer for redirected SQL
commands. If the buffer already exists, it empties it first.
Call this function directly if you don't care about the output. Set a variable
to this function's return value if you want to process it once the command
has completed."
;; Get the buffer
(let ((the-buffer (get-buffer-create " *enode-comint-sql-output*")))
;; Empty it.
(enode-clean-buffer the-buffer)
;; Return it
the-buffer
)
)
;; This is useful for main ENODE environment.
;;;; Is this necessary if we user with-temp-buffer()?
(defun enode-stage-buffer ()
"A function to provide a buffer for staging commands out of."
(let ((the-buffer (get-buffer-create " *enode-stage-buffer*")))
;; Empty it
(enode-clean-buffer the-buffer)
;; Return it
the-buffer
)
)
;;;; Change this to use enode-oracle-run-sql-command
(defun enode-oracle-sqlplus-set-param (param value)
"A function to set an sqlplus parameter, PARAM, to VALUE."
(comint-redirect-send-command-to-process
(format "set %s %s\n" param value)
(enode-temp-output-buffer)
(get-buffer-process sql-buffer)
nil
t)
(enode-wait-for-command)
)
(defun enode-oracle-get-table-constraints (owner table)
"A function to return a list of tables belonging to OWNER"
(let ((the-command
(format
"select constraint_name from all_constraints where table_name = '%s' and owner = '%s';"
table
owner
)
)
)
(comint-redirect-results-list-from-process
(get-buffer-process sql-buffer)
the-command
"^\\([A-Z0-9_]+\\)$"
1)
)
)
(defun enode-oracle-get-table-indexes (owner table)
"A function to return a list of indexes on TABLE belonging to OWNER"
(let ((the-command
(format
"select index_name from all_indexes where table_name = '%s' and owner = '%s';"
table
owner
)
)
)
(comint-redirect-results-list-from-process
(get-buffer-process sql-buffer)
the-command
"^\\([A-Z0-9_]+\\)$"
1)
)
)
(defun enode-oracle-get-triggers (owner table)
"A function to return a list of indexes on TABLE belonging to OWNER"
(let ((the-command
(format
"select trigger_name from all_triggers where table_name = '%s' and owner = '%s';"
table
owner
)
)
)
(comint-redirect-results-list-from-process
(get-buffer-process sql-buffer)
the-command
"^\\([A-Z0-9_]+\\)$"
1)
)
)
(defun enode-oracle-get-constraint-columns (owner constraint)
"A function to return as a list the names of columns in a constraint
ordered by the position"
(let ((the-command
(format
"select table_name || '.' || column_name from all_cons_columns where constraint_name = '%s' and owner = '%s' order by position;"
constraint
owner
)
)
)
(comint-redirect-results-list-from-process
(get-buffer-process sql-buffer)
the-command
"^\\([\.A-Z0-9_]+\\)$"
1)
)
)
(defun enode-oracle-get-java-source (owner java-source)
"A function to return the source of a stored java program."
(let ((the-command
(format
"select text from all_source where name = '%s' and owner = '%s' and type = 'JAVA SOURCE' order by line;"
java-source
owner
)
)
)
(comint-redirect-send-command-to-process
the-command
(get-buffer-create "*tester*")
(get-buffer-process sql-buffer)
nil)
)
)
(defun enode-oracle-commit (&optional rollback)
"A function to commit changes to an oracle database"
(let ((output-buffer (enode-temp-output-buffer))
response-msg
)
(comint-redirect-send-command-to-process
(if rollback (format "rollback;\n") (format "commit;\n"))
output-buffer
(get-buffer-process sql-buffer)
nil
t)
(enode-wait-for-command)
(save-excursion
(set-buffer output-buffer)
(goto-char (point-min))
(forward-line)
(setq response-msg
(buffer-substring (point) (save-excursion (end-of-line) (point))))
)
(message "%s" response-msg)
)
)
(provide 'enode-oracle)