Logo Search packages:      
Sourcecode: monodevelop version File versions  Download package

SqlQueryView.cs

//
// SqlQueryView.cs
//
// Authors:
//   Christian Hergert <chris@mosaix.net>
//   Daniel Morgan <danielmorgan@verizon.net>
//
// Copyright (C) 2005 Christian Hergert
// Copyright (C) 2005 Daniel Morgan
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

using System;
using System.Data;

using Gtk;
using GtkSourceView;

using Mono.Data.Sql;

using MonoDevelop.Core;
using MonoDevelop.Components;
using MonoDevelop.Ide.Gui;

namespace MonoQuery
{
      public class SqlQueryView : AbstractViewContent
      {
            protected Frame control;
            protected SourceView sourceView;
            protected ComboBox providers;
            
            protected ListStore model;
            
            protected EventHandler changedHandler;
            
            protected MonoQueryService service;

            private int executeMode = 0;
            private int offset = 0;
            
            public SqlQueryView () : base ()
            {
                  control = new Frame ();
                  control.Show ();
                  
                  VBox vbox = new VBox ();
                  vbox.Show ();
                  
                  Tooltips tips = new Tooltips ();
                  
                  Toolbar toolbar = new Toolbar ();
                  vbox.PackStart    (toolbar, false, true, 0);
                  toolbar.Show ();
                  
                  Image image = new Image ();
                  image.Pixbuf = Gdk.Pixbuf.LoadFromResource ("MonoQuery.Execute");
                  image.Show ();
                  
                  Button execute = new Button (image);
                  execute.Clicked += new EventHandler (OnExecute);
                  execute.Relief = ReliefStyle.None;
                  tips.SetTip (execute, "Execute", "");
                  toolbar.Add (execute);
                  execute.Show ();
                  
                  image = new Image ();
                  image.Pixbuf = Gdk.Pixbuf.LoadFromResource ("MonoQuery.RunFromCursor");
                  image.Show ();
                  
                  Button run = new Button (image);
                  run.Clicked += new EventHandler (OnRunFromCursor);
                  run.Relief = ReliefStyle.None;
                  tips.SetTip (run, "Run from cursor", "");
                  toolbar.Add (run);
                  run.Show ();
                  
                  image = new Image ();
                  image.Pixbuf = Gdk.Pixbuf.LoadFromResource ("MonoQuery.Explain");
                  image.Show ();
                  
                  Button explain = new Button (image);
                  explain.Clicked += new EventHandler (OnExplain);
                  explain.Relief = ReliefStyle.None;
                  tips.SetTip (explain, "Explain query", "");
                  toolbar.Add (explain);
                  explain.Show ();
                  
                  image = new Image ();
                  image.Pixbuf = Gdk.Pixbuf.LoadFromResource ("MonoQuery.Stop");
                  image.Show ();
                  
                  Button stop = new Button (image);
                  stop.Clicked += new EventHandler (OnStop);
                  stop.Relief = ReliefStyle.None;
                  stop.Sensitive = false;
                  tips.SetTip (stop, "Stop", "");
                  toolbar.Add (stop);
                  stop.Show ();

                  VSeparator sep = new VSeparator ();
                  toolbar.Add (sep);
                  sep.Show ();
                  
                  model = new ListStore (typeof (string), typeof (DbProviderBase));
                  
                  providers = new ComboBox ();
                  providers.Model = model;
                  CellRendererText ctext = new CellRendererText ();
                  providers.PackStart (ctext, true);
                  providers.AddAttribute (ctext, "text", 0);
                  toolbar.Add (providers);
                  providers.Show ();
                  
                  SourceLanguagesManager lm = new SourceLanguagesManager ();
                  SourceLanguage lang = lm.GetLanguageFromMimeType ("text/x-sql");
                  SourceBuffer buf = new SourceBuffer (lang);
                  buf.Highlight = true;
                  sourceView = new SourceView (buf);
                  sourceView.ShowLineNumbers = true;
                  sourceView.Show ();
                  
                  ScrolledWindow scroller = new ScrolledWindow ();
                  scroller.Add (sourceView);
                  scroller.Show ();
                  vbox.PackStart (scroller, true, true, 0);
                  
                  control.Add (vbox);
                  
                  service = (MonoQueryService)
                        ServiceManager.GetService (typeof (MonoQueryService));
                  changedHandler
                         = (EventHandler) MonoDevelop.Core.Gui.Services.DispatchService.GuiDispatch (
                              new EventHandler (OnProvidersChanged));
                  service.Providers.Changed += changedHandler;
                  
                  foreach (DbProviderBase p in service.Providers) {
                        model.AppendValues (p.Name, p);
                  }
            }
            
            public string Text {
                  get {
                        return sourceView.Buffer.Text;
                  }
                  set {
                        sourceView.Buffer.Text = value;
                  }
            }
            
            public override Gtk.Widget Control {
                  get {
                        return control;
                  }
            }
            
            public override string UntitledName {
                  get {
                        return "SQL Query";
                  }
            }
            
            public override void Dispose ()
            {
                  service.Providers.Changed -= changedHandler;
            }
            
            public override void Load (string filename)
            {
            }
            
            public DbProviderBase Connection {
                  set {
                        int i = 0;
                        foreach (object[] row in model) {
                              if (row[1] == value)
                                    providers.Active = i;
                              i++;
                        }
                  }
                  get {
                        TreeIter iter;
                        providers.GetActiveIter (out iter);
                        return (DbProviderBase) model.GetValue (iter, 1);
                  }
            }

            void OnExecute (object sender, EventArgs args)
            {
                  TextBuffer buf = (TextBuffer) sourceView.Buffer;
                  TextIter iter = buf.StartIter;
                  TextIter end_iter = buf.EndIter;
                  string query = String.Empty;

                  if (buf.GetSelectionBounds (out iter, out end_iter) == true) {
                        query = buf.GetText (iter, end_iter, false);
                        executeMode = 2; // as-is
                  } else {
                        query = GetSqlStatementAtCursor (buf, out iter);
                        executeMode = 0; // one single statement at cursor
                  }

                  if (query.Trim ().Length > 0) {
                        IdeApp.Workbench.StatusBar.BeginProgress (
                              GettextCatalog.GetString("Executing sql query on")
                              + String.Format (" {0}", Connection.Name));
                        IdeApp.Workbench.StatusBar.SetProgressFraction (0.1);

                        IdeApp.Workbench.StatusBar.SetMessage (
                              GettextCatalog.GetString ("Query sent, waiting for response."));
                        IdeApp.Workbench.StatusBar.SetProgressFraction (0.5);

                        SQLCallback callback = (SQLCallback)
                              MonoDevelop.Core.Gui.Services.DispatchService.GuiDispatch (
                              new SQLCallback (OnExecuteReturn));

                        buf.MoveMark (buf.InsertMark, iter);
                        buf.MoveMark (buf.SelectionBound, iter);
                  
                        offset = 0;
                        Connection.ExecuteSQL (query, callback);
                  }
            }
            
            void OnRunFromCursor (object sender, EventArgs args)
            {
                  TextBuffer buf = (TextBuffer) sourceView.Buffer;
                  TextIter iter = buf.StartIter;
                  TextIter end_iter = buf.EndIter;
                  string query = String.Empty;

                  if (buf.GetSelectionBounds (out iter, out end_iter) == true) {
                        query = buf.GetText (iter, end_iter, false);
                        executeMode = 2; // as-is
                  } else {
                        query = GetSqlStatementAtCursor (buf, out iter);
                        executeMode = 1; // one multiple statements one-at-a-time starting at cursor
                  }

                  if (query.Trim ().Length > 0) {
                        IdeApp.Workbench.StatusBar.BeginProgress (
                              GettextCatalog.GetString("Executing sql query on")
                              + String.Format (" {0}", Connection.Name));
                        IdeApp.Workbench.StatusBar.SetProgressFraction (0.1);

                        IdeApp.Workbench.StatusBar.SetMessage (
                              GettextCatalog.GetString ("Query sent, waiting for response."));
                        IdeApp.Workbench.StatusBar.SetProgressFraction (0.5);

                        SQLCallback callback = (SQLCallback)
                              MonoDevelop.Core.Gui.Services.DispatchService.GuiDispatch (
                              new SQLCallback (OnExecuteReturn));

                        buf.MoveMark (buf.InsertMark, iter);
                        buf.MoveMark (buf.SelectionBound, iter);

                        executeMode = 1; // Execute multiple statements one-at-a-time starting at cursor
                        offset = iter.Offset;
                        Connection.ExecuteSQL (query, callback);
                  }
            }
            
            void OnExecuteReturn (object sender, object results)
            {
                  IdeApp.Workbench.StatusBar.SetMessage (
                        GettextCatalog.GetString ("Query results received"));
                  IdeApp.Workbench.StatusBar.SetProgressFraction (0.9);
                  
                  TextBuffer buf = (TextBuffer) sourceView.Buffer;
                  if (results == null) {
                        IdeApp.Workbench.StatusBar.ShowErrorMessage (
                              GettextCatalog.GetString ("Invalid select query"));
                        if (executeMode == 1)
                              sourceView.ScrollToMark (buf.InsertMark, 0.4, true, 0.0, 1.0);
                  } else {
                        DataGridView dataView = new DataGridView (results as DataTable);
                        IdeApp.Workbench.OpenDocument (dataView, true);

                        if (executeMode == 1) { 
                              // execute multiple SQL
                              TextIter iter = buf.StartIter;
                              iter.Offset = offset;
                              string query = GetNextSqlStatement (buf, ref iter);
                              if (query.Trim ().Length > 0) {
                                    SQLCallback callback = (SQLCallback)
                                          MonoDevelop.Core.Gui.Services.DispatchService.GuiDispatch (
                                          new SQLCallback (OnExecuteReturn));

                                    // move insert mark to end of SQL statement to be executed
                                    buf.MoveMark (buf.InsertMark, iter);
                                    buf.MoveMark (buf.SelectionBound, iter);

                                    IdeApp.Workbench.StatusBar.SetMessage (
                                          GettextCatalog.GetString ("Query sent, waiting for response."));
                                    IdeApp.Workbench.StatusBar.SetProgressFraction (0.5);

                                    executeMode = 1;
                                    offset = iter.Offset;
                                    Connection.ExecuteSQL (query, callback);
                              }
                              else {
                                    sourceView.ScrollToMark (buf.InsertMark, 0.4, true, 0.0, 1.0);
                                    IdeApp.Workbench.StatusBar.EndProgress ();
                              }
                        }
                        else {
                              sourceView.ScrollToMark (buf.InsertMark, 0.4, true, 0.0, 1.0);
                              IdeApp.Workbench.StatusBar.EndProgress ();
                        }                 
                  }
            }

            // Execute first SQL statement at cursor
            public string GetSqlStatementAtCursor (TextBuffer sqlTextBuffer, out TextIter iter) 
            {
                  TextIter start_iter, end_iter, insert_iter;
                  TextIter match_start1, match_end1, match_start2, match_end2;
                  TextIter begin_iter, finish_iter;
                  string text = String.Empty;
                  int char_count = 0;
                  TextMark insert_mark;

                  insert_mark = sqlTextBuffer.InsertMark;
                  insert_iter = sqlTextBuffer.GetIterAtMark (insert_mark);
                  start_iter = sqlTextBuffer.GetIterAtOffset (0);
                  
                  char_count = sqlTextBuffer.CharCount;
                  end_iter = sqlTextBuffer.GetIterAtOffset (char_count);
                  iter = end_iter;

                  match_start1 = sqlTextBuffer.GetIterAtOffset (0);
                  match_end1 = sqlTextBuffer.GetIterAtOffset (char_count);
                  match_start2 = sqlTextBuffer.GetIterAtOffset (0);
                  match_end2 = sqlTextBuffer.GetIterAtOffset (char_count);

                  begin_iter = sqlTextBuffer.GetIterAtOffset (0);
                  finish_iter = sqlTextBuffer.GetIterAtOffset (char_count);

                  if (start_iter.IsEnd == false) 
                  {
                        if (insert_iter.BackwardSearch (";", TextSearchFlags.TextOnly, 
                                    out match_start1, out match_end1, start_iter) == true) {
                              begin_iter = match_start1;
                              begin_iter.ForwardChars (1);
                        }
                        
                        if (insert_iter.ForwardSearch (";", TextSearchFlags.TextOnly,
                                    out match_start2, out match_end2, end_iter) == true) {
                              finish_iter = match_end2;
                              finish_iter.BackwardChars (1);
                        }
                        iter = finish_iter;
                        text = sqlTextBuffer.GetText (begin_iter, finish_iter, false);    

                        // FIXME: for this to work.  GetSqlStatement has to rewritten to be line-based
                        if (text.Length > 0) {
                              // search does not work if what you are searching for is 
                              // at the end of the buffer,
                              // this compensates for this
                              int j = text.Length;
                              int cont = 1;
                              for(int i = text.Length - 1; cont == 1 && i >= 0; i--) {
                                    char ch = text[i];
                                    switch(ch) {
                                    case ' ':
                                    case ';':
                                          j--;
                                          break;
                                    default:
                                          cont = 0;
                                          break;
                                    }
                              }
                              
                              if (j != text.Length) {
                                    string t = text.Substring(0, j);
                                    text = t;
                              }
                        }
                  }

                  return text;
            }

            // get next SQL statement.  Requires GetSqlStatementAtCursor having been called first
            public string GetNextSqlStatement (TextBuffer sqlTextBuffer, ref TextIter iter) 
            {
                  TextIter start_iter, end_iter;
                  TextIter match_start2, match_end2;
                  TextIter finish_iter;
                  string text = String.Empty;
                  int char_count = 0;

                  char_count = sqlTextBuffer.CharCount;
                  end_iter = sqlTextBuffer.GetIterAtOffset (char_count);
                  if (iter.IsEnd == false) {
                        iter.ForwardChars (1);
                        if (sqlTextBuffer.GetText (iter, end_iter, false).Equals (";"))
                              iter.ForwardChars (1);
                  }

                  if (iter.IsEnd == true) 
                        return "";

                  start_iter = iter;
                  match_start2 = iter;
                  match_end2 = sqlTextBuffer.GetIterAtOffset (char_count);
                  finish_iter = sqlTextBuffer.GetIterAtOffset (char_count);

                  if (start_iter.IsEnd == false) {
                        if (iter.ForwardSearch (";", TextSearchFlags.TextOnly,
                                    out match_start2, out match_end2, end_iter) == true)  {
                              finish_iter = match_end2;
                              finish_iter.BackwardChars (1);
                        }

                        text = sqlTextBuffer.GetText (iter, finish_iter, false);
                        iter = finish_iter;

                        if(text.Length > 0) {
                              // search does not work if what you are searching for is 
                              // at the end of the buffer,
                              // this compensates for this
                              int j = text.Length;
                              int cont = 1;
                              for(int i = text.Length - 1; cont == 1 && i >= 0; i--) {
                                    char ch = text[i];
                                    switch(ch) {
                                    case ' ':
                                    case ';':
                                          j--;
                                          break;
                                    default:
                                          cont = 0;
                                          break;
                                    }
                              }
                              
                              if(j != text.Length) {
                                    string t = text.Substring(0, j);
                                    text = t;
                              }
                        }
                  }

                  return text;
            }
            
            void OnExplain (object sender, EventArgs args)
            {
                  IdeApp.Workbench.StatusBar.BeginProgress (
                        GettextCatalog.GetString("Executing sql query on")
                        + String.Format (" {0}", Connection.Name));
                  IdeApp.Workbench.StatusBar.SetProgressFraction (0.1);
                  
                  string query = sourceView.Buffer.Text;
                  SQLCallback callback = (SQLCallback)
                        MonoDevelop.Core.Gui.Services.DispatchService.GuiDispatch (
                        new SQLCallback (OnExecuteReturn));
                  
                  IdeApp.Workbench.StatusBar.SetMessage (
                        GettextCatalog.GetString ("Query sent, waiting for response."));
                  IdeApp.Workbench.StatusBar.SetProgressFraction (0.5);
                  
                  Connection.ExplainSQL (query, callback);
            }
            
            void OnStop (object sender, EventArgs args)
            {
            }
            
            void OnProvidersChanged (object sender, EventArgs args)
            {
                  DbProviderBase current = Connection;
                  model.Clear ();
                  
                  foreach (DbProviderBase p in service.Providers) {
                        TreeIter cur = model.AppendValues (p.Name, p);
                        if (p == current)
                              providers.SetActiveIter (cur);
                  }
            }
      }
}

Generated by  Doxygen 1.6.0   Back to index