diff --git a/cubesql-webadmin.xojo_project b/cubesql-webadmin.xojo_project
index 0beb3b8..66c1d87 100644
--- a/cubesql-webadmin.xojo_project
+++ b/cubesql-webadmin.xojo_project
@@ -4,6 +4,7 @@ MinIDEVersion=20200200
OrigIDEVersion=20240100
Folder=resources;resources;&h0000000035B107FF;&h0000000000000000;false
Folder=styles;styles;&h00000000139DBFFF;&h0000000000000000;false
+Class=CheckboxCellRenderer;styles/CheckboxCellRenderer.xojo_code;&h000000007F7FF7FF;&h00000000139DBFFF;false
Folder=webapp;webapp;&h0000000018D38FFF;&h0000000000000000;false
Folder=main;webapp/main;&h000000001D9447FF;&h0000000018D38FFF;false
WebView=LoginPage;webapp/main/LoginPage.xojo_code;&h000000005492FFFF;&h000000001D9447FF;false
@@ -16,6 +17,9 @@ WebView=dlgGetServerKey;webapp/dialogs/dlgGetServerKey.xojo_code;&h0000000076F62
WebView=dlgDatabaseCreate;webapp/dialogs/dlgDatabaseCreate.xojo_code;&h0000000045C397FF;&h0000000054A427FF;false
WebView=dlgDatabaseUpload;webapp/dialogs/dlgDatabaseUpload.xojo_code;&h00000000375D2FFF;&h0000000054A427FF;false
WebView=dlgDatabaseSchedules;webapp/dialogs/dlgDatabaseSchedules.xojo_code;&h00000000514E3FFF;&h0000000054A427FF;false
+WebView=dlgIndexCreate;webapp/dialogs/dlgIndexCreate.xojo_code;&h000000000919DFFF;&h0000000054A427FF;false
+WebView=dlgTableEditor;webapp/dialogs/dlgTableEditor.xojo_code;&h0000000035FA4FFF;&h0000000054A427FF;false
+WebView=dlgTableEditorField;webapp/dialogs/dlgTableEditorField.xojo_code;&h000000007BD80FFF;&h0000000054A427FF;false
WebView=dlgSchedule;webapp/dialogs/dlgSchedule.xojo_code;&h00000000476F1FFF;&h0000000054A427FF;false
WebView=dlgScheduleDatabases;webapp/dialogs/dlgScheduleDatabases.xojo_code;&h000000005565B7FF;&h0000000054A427FF;false
WebView=dlgUserCreate;webapp/dialogs/dlgUserCreate.xojo_code;&h0000000064C14FFF;&h0000000054A427FF;false
@@ -33,6 +37,7 @@ Folder=server;webapp/containers/server;&h0000000045A527FF;&h000000005859EFFF;fal
Folder=data;webapp/containers/data;&h00000000107E37FF;&h000000005859EFFF;false
WebContainer=cntDatabases;webapp/containers/data/cntDatabases.xojo_code;&h0000000040B4DFFF;&h00000000107E37FF;false
WebContainer=cntDatabasesEncryption;webapp/containers/data/cntDatabasesEncryption.xojo_code;&h0000000044B7E7FF;&h00000000107E37FF;false
+WebContainer=cntTablesIndexes;webapp/containers/data/cntTablesIndexes.xojo_code;&h000000004B6CDFFF;&h00000000107E37FF;false
WebContainer=cntBackups;webapp/containers/data/cntBackups.xojo_code;&h000000004237B7FF;&h00000000107E37FF;false
WebContainer=cntSchedules;webapp/containers/data/cntSchedules.xojo_code;&h000000002F98DFFF;&h00000000107E37FF;false
WebContainer=cntRegistrationAction;webapp/containers/server/cntRegistrationAction.xojo_code;&h000000000788EFFF;&h0000000045A527FF;false
@@ -97,7 +102,7 @@ WebDebugPort=8080
WebLivePort=80
WebSecurePort=443
WebProtocol=1
-WebHTMLHeader=
+WebHTMLHeader=
WebHostingIdentifier=
WebHostingAppName=cubeSQLWebAdmin
WebHostingDomain=
diff --git a/styles/CheckboxCellRenderer.xojo_code b/styles/CheckboxCellRenderer.xojo_code
new file mode 100644
index 0000000..eaed0ca
--- /dev/null
+++ b/styles/CheckboxCellRenderer.xojo_code
@@ -0,0 +1,145 @@
+#tag Class
+Protected Class CheckboxCellRenderer
+Inherits WebListboxCellRenderer
+ #tag Event
+ Sub Deserialize(js As JSONItem)
+ // Restore the values of the column to the object
+
+ Checked = js.Lookup("checked", False).BooleanValue
+
+ End Sub
+ #tag EndEvent
+
+ #tag Event
+ Function JavascriptClassCode(s As WebSession) As String
+ #Pragma unused s
+
+ Var code() As String
+
+ // All custom cells extend the XojoWeb.ListboxCellRenderer class
+ code.Add "class CheckboxCell extends XojoWeb.ListboxCellRenderer {"
+
+ // You must override the "render" method
+ // controlID (string): The identifier of the listbox control that the renderer is currently running under
+ // row (HTMLElement): The HTML DOM element of the entire row. This is provided so that you can make modifications to the entire row if necessary, like applying a style.
+ // data (object): The data that the Xojo portion of your control provided for this column
+ // rowIndex (number): The row number that is currently being rendered
+ // columnIndex (number): The column number that is currently being rendered
+ // cell (HTMLElement): The HTML DOM element of the cell that your renderer is responsible for.
+ code.Add " render(controlID, row, data, rowIndex, columnIndex, cell) {"
+
+ // Remove the text that's already in the cell
+ code.Add " cell.innerHTML= '';"
+
+ // Make a bootstrap checkbox
+ code.Add " let checkbox = document.createElement('input');"
+ code.Add " checkbox.type = 'checkbox';"
+ code.Add " checkbox.className = 'form-check-input';"
+ code.Add " checkbox.checked = data.checked;"
+ code.Add " checkbox.style.marginLeft = '6px'"
+ code.Add " checkbox.style.marginRight = '6px'"
+
+ // Handle clicking on the button
+ code.Add " checkbox.addEventListener('click', function(ev) {"
+ code.Add " ev.stopPropagation();"
+ code.Add " var obj = new XojoWeb.JSONItem;"
+ code.Add " obj.set('row', rowIndex);" // All extensions should include the row (default is -1)
+ code.Add " obj.set('column', columnIndex);" // All extensions should include the column (default is -1)
+ code.Add " obj.set('identifier', 'idCheckbox');" // All extensions should include an identifier (default is "")
+ code.Add " obj.set('value', checkbox.checked);" // Including a value is optional (default is null)
+ code.Add " XojoWeb.controls.lookup(controlID).triggerServerEvent('CustomCellAction', obj);"
+ code.Add " return false;"
+ code.Add " });"
+
+ // Add our new content
+ code.Add " cell.appendChild(checkbox);"
+ code.Add " }"
+ code.Add "}"
+
+ Return String.FromArray(code, EndOfLine.Windows)
+
+
+ End Function
+ #tag EndEvent
+
+ #tag Event
+ Function Serialize() As JSONItem
+ // Use this code to convert the value(s) needed to render your codes to JSON.
+ // This is also used by non-datasource listboxes to store these settings for your column.
+
+ Var js As New JSONItem
+ js.Value("checked") = Checked
+
+ return js
+ End Function
+ #tag EndEvent
+
+
+ #tag Method, Flags = &h0
+ Sub Constructor(isChecked As Boolean)
+ // Calling the overridden superclass constructor.
+ Super.Constructor
+
+ Self.Checked = isChecked
+
+ End Sub
+ #tag EndMethod
+
+
+ #tag Property, Flags = &h0
+ Checked As Boolean
+ #tag EndProperty
+
+
+ #tag ViewBehavior
+ #tag ViewProperty
+ Name="Name"
+ Visible=true
+ Group="ID"
+ InitialValue=""
+ Type="String"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Index"
+ Visible=true
+ Group="ID"
+ InitialValue="-2147483648"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Super"
+ Visible=true
+ Group="ID"
+ InitialValue=""
+ Type="String"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Left"
+ Visible=true
+ Group="Position"
+ InitialValue="0"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Top"
+ Visible=true
+ Group="Position"
+ InitialValue="0"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Checked"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag EndViewBehavior
+End Class
+#tag EndClass
diff --git a/webapp/Session.xojo_code b/webapp/Session.xojo_code
index 4621f9d..9be067d 100644
--- a/webapp/Session.xojo_code
+++ b/webapp/Session.xojo_code
@@ -38,6 +38,18 @@ Inherits WebSession
rs.Close
End If
+ rs = db.SelectSQL("SHOW INFO FOR KEY engine_version")
+ If (rs <> Nil) Then
+
+ If (rs.RowCount > 0) Then
+ rs.MoveToFirstRow
+
+ DBEngineVersion = Version_AsDouble(rs.Column("value").StringValue)
+ End If
+
+ rs.Close
+ End If
+
Catch err As DatabaseException
Return False
@@ -60,6 +72,7 @@ Inherits WebSession
DB = Nil
ClientId = -1
+ DBEngineVersion = 0.0
End Sub
#tag EndMethod
@@ -73,6 +86,10 @@ Inherits WebSession
DB As CubeSQLServer
#tag EndProperty
+ #tag Property, Flags = &h0
+ DBEngineVersion As Double
+ #tag EndProperty
+
#tag ViewBehavior
#tag ViewProperty
diff --git a/webapp/containers/data/cntTablesIndexes.xojo_code b/webapp/containers/data/cntTablesIndexes.xojo_code
new file mode 100644
index 0000000..86c008d
--- /dev/null
+++ b/webapp/containers/data/cntTablesIndexes.xojo_code
@@ -0,0 +1,1059 @@
+#tag WebContainerControl
+Begin cntDatasourceBase cntTablesIndexes
+ Compatibility = ""
+ ControlCount = 0
+ ControlID = ""
+ Enabled = True
+ Height = 500
+ Indicator = 0
+ LayoutDirection = 0
+ LayoutType = 0
+ Left = 0
+ LockBottom = False
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ ScrollDirection = 0
+ TabIndex = 0
+ Top = 0
+ Visible = True
+ Width = 750
+ _mDesignHeight = 0
+ _mDesignWidth = 0
+ _mPanelIndex = -1
+ Begin WebListBox lstInfos
+ ColumnCount = 1
+ ColumnWidths = ""
+ ControlID = ""
+ Enabled = True
+ HasHeader = True
+ Height = 342
+ HighlightSortedColumn= True
+ Index = -2147483648
+ Indicator = 0
+ InitialValue = ""
+ LastAddedRowIndex= 0
+ LastColumnIndex = 0
+ LastRowIndex = 0
+ Left = 0
+ LockBottom = True
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = True
+ LockTop = True
+ LockVertical = False
+ NoRowsMessage = "No Tables & Indexes"
+ ProcessingMessage= ""
+ RowCount = 0
+ RowSelectionType= 1
+ Scope = 2
+ SearchCriteria = ""
+ SelectedRowColor= &c0d6efd
+ SelectedRowIndex= 0
+ TabIndex = 0
+ TabStop = True
+ Tooltip = ""
+ Top = 0
+ Visible = True
+ Width = 750
+ _mPanelIndex = -1
+ End
+ Begin WebRectangle rctFilter
+ BackgroundColor = &cFFFFFF
+ ControlCount = 0
+ ControlID = ""
+ Enabled = True
+ HasBackgroundColor= False
+ Height = 75
+ Index = -2147483648
+ Indicator = 0
+ LayoutDirection = 0
+ LayoutType = 0
+ Left = 0
+ LockBottom = True
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = True
+ LockTop = False
+ LockVertical = False
+ PanelIndex = "0"
+ Scope = 2
+ TabIndex = 1
+ TabStop = True
+ Tooltip = ""
+ Top = 350
+ Visible = True
+ Width = 750
+ _mDesignHeight = 0
+ _mDesignWidth = 0
+ _mPanelIndex = -1
+ Begin WebLabel labFilter
+ Bold = True
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 0.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Italic = False
+ Left = 20
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ PanelIndex = "0"
+ Parent = "rctFilter"
+ Scope = 2
+ TabIndex = 0
+ TabPanelIndex = -1
+ TabStop = True
+ Text = "View"
+ TextAlignment = 0
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 370
+ Underline = False
+ Visible = True
+ Width = 60
+ _mPanelIndex = -1
+ End
+ Begin WebLabel labFilterDatabase
+ Bold = False
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 0.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Italic = False
+ Left = 151
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ PanelIndex = "0"
+ Parent = "rctFilter"
+ Scope = 2
+ TabIndex = 1
+ TabPanelIndex = -1
+ TabStop = True
+ Text = "Database:"
+ TextAlignment = 0
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 370
+ Underline = False
+ Visible = True
+ Width = 140
+ _mPanelIndex = -1
+ End
+ Begin WebPopupMenu lstFilterDatabase
+ ControlID = ""
+ Enabled = True
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ InitialValue = ""
+ LastAddedRowIndex= 0
+ LastRowIndex = 0
+ Left = 299
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ PanelIndex = "0"
+ Parent = "rctFilter"
+ RowCount = 0
+ Scope = 2
+ SelectedRowIndex= 0
+ SelectedRowText = ""
+ TabIndex = 2
+ TabPanelIndex = -1
+ TabStop = True
+ Tooltip = ""
+ Top = 370
+ Visible = True
+ Width = 400
+ _mPanelIndex = -1
+ End
+ End
+ Begin WebButton btnDrop
+ AllowAutoDisable= False
+ Cancel = False
+ Caption = "Drop"
+ ControlID = ""
+ Default = False
+ Enabled = False
+ Height = 38
+ Index = -2147483648
+ Indicator = 4
+ Left = 630
+ LockBottom = True
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = True
+ LockTop = False
+ LockVertical = False
+ PanelIndex = "0"
+ Scope = 2
+ TabIndex = 4
+ TabStop = True
+ Tooltip = ""
+ Top = 442
+ Visible = True
+ Width = 100
+ _mPanelIndex = -1
+ End
+ Begin WebMessageDialog dlgDrop
+ ControlID = ""
+ Enabled = True
+ Explanation = ""
+ Index = -2147483648
+ Indicator = 0
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ Message = ""
+ PanelIndex = "0"
+ Scope = 2
+ Title = ""
+ Tooltip = ""
+ _mPanelIndex = -1
+ End
+ Begin WebButton btnCreateTable
+ AllowAutoDisable= False
+ Cancel = False
+ Caption = "Create Table"
+ ControlID = ""
+ Default = False
+ Enabled = True
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Left = 20
+ LockBottom = True
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = False
+ LockVertical = False
+ PanelIndex = "0"
+ Scope = 2
+ TabIndex = 2
+ TabStop = True
+ Tooltip = ""
+ Top = 442
+ Visible = True
+ Width = 120
+ _mPanelIndex = -1
+ End
+ Begin WebButton btnCreateIndex
+ AllowAutoDisable= False
+ Cancel = False
+ Caption = "Create Index"
+ ControlID = ""
+ Default = False
+ Enabled = True
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Left = 148
+ LockBottom = True
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = False
+ LockVertical = False
+ PanelIndex = "0"
+ Scope = 2
+ TabIndex = 3
+ TabStop = True
+ Tooltip = ""
+ Top = 442
+ Visible = True
+ Width = 120
+ _mPanelIndex = -1
+ End
+ Begin WebButton btnAlterTable
+ AllowAutoDisable= False
+ Cancel = False
+ Caption = "Alter Table"
+ ControlID = ""
+ Default = False
+ Enabled = True
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Left = 502
+ LockBottom = True
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = True
+ LockTop = False
+ LockVertical = False
+ PanelIndex = "0"
+ Scope = 2
+ TabIndex = 5
+ TabStop = True
+ Tooltip = ""
+ Top = 442
+ Visible = True
+ Width = 120
+ _mPanelIndex = -1
+ End
+End
+#tag EndWebContainerControl
+
+#tag WindowCode
+ #tag Event
+ Sub Closed()
+ Try
+ Session.DB.ExecuteSQL("CLEAR CURRENT DATABASE")
+
+ Catch err As DatabaseException
+
+ End Try
+
+ End Sub
+ #tag EndEvent
+
+
+ #tag Method, Flags = &h21
+ Private Sub ActionAlterTable()
+ Var selectedItem As Dictionary = Me.GetSelectedTableRowTag()
+ If (selectedItem = Nil) Then Return
+ If (selectedItem.Lookup("type", "").StringValue <> "table") Then Return
+ If (selectedItem.Lookup("name", "").StringValue = "") Then Return
+
+ Var dlgTable As New dlgTableEditor
+ AddHandler dlgTable.TableEditorSaveAction, WeakAddressOf ActionAlterTableButtonPressed
+ dlgTable.ShowAsAlter(selectedItem.Lookup("name", "").StringValue)
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function ActionAlterTableButtonPressed(obj As dlgTableEditor, Name As String, SQLStatements() As String) As Boolean
+ #Pragma unused obj
+
+ If (Name = "") Then Return False
+ If (SQLStatements.LastIndex < 0) Then Return False
+
+ Try
+
+ For i As Integer = 0 To SQLStatements.LastIndex
+ Session.DB.ExecuteSQL(SQLStatements(i))
+ Next
+
+ Session.DB.ExecuteSQL("COMMIT")
+
+ Catch err As DatabaseException
+ ShowErrorDialog("Alter Table", "Could not alter table.", err)
+ Return False
+
+ End Try
+
+ 'Success - no dialog
+ Var selectRowTag As New Dictionary
+ selectRowTag.Value("type") = "table"
+ selectRowTag.Value("name") = Name
+
+ Me.RefreshInfos(selectRowTag)
+ Return True
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub ActionCreateIndex()
+ Var databasename As String = Me.GetSelectedDatabasename()
+ If (databasename = "") Then Return
+
+ Var dlgIndex As New dlgIndexCreate
+ AddHandler dlgIndex.IndexCreateAction, WeakAddressOf ActionCreateIndexButtonPressed
+ dlgIndex.Show(databasename)
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function ActionCreateIndexButtonPressed(obj As dlgIndexCreate, Name As String, Table As String, Fields() As String) As Boolean
+ #Pragma unused obj
+
+ If (Name = "") Or (Table = "") Then Return False
+ If (Fields.LastIndex < 0) Then Return False
+
+ Try
+ Var escapedFields() As String
+ For i As Integer = 0 To Fields.LastIndex
+ escapedFields.Add(Fields(i).EscapeSqlFieldIfRequired)
+ Next
+
+ Session.DB.ExecuteSQL("CREATE INDEX " + Name.EscapeSqlFieldIfRequired + " ON " + Table.EscapeSqlFieldIfRequired + " (" + String.FromArray(escapedFields, ", ") + ")")
+ Session.DB.ExecuteSQL("COMMIT")
+
+ Catch err As DatabaseException
+ ShowErrorDialog("Create Index", "Could not create index.", err)
+ Return False
+
+ End Try
+
+ 'Success - no dialog
+ Var selectRowTag As New Dictionary
+ selectRowTag.Value("type") = "index"
+ selectRowTag.Value("name") = Name
+
+ Me.RefreshInfos(selectRowTag)
+ Return True
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub ActionCreateTable()
+ Var dlgTable As New dlgTableEditor
+ AddHandler dlgTable.TableEditorSaveAction, WeakAddressOf ActionCreateTableButtonPressed
+ dlgTable.ShowAsCreate()
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function ActionCreateTableButtonPressed(obj As dlgTableEditor, Name As String, SQLStatements() As String) As Boolean
+ #Pragma unused obj
+
+ If (Name = "") Then Return False
+ If (SQLStatements.LastIndex < 0) Then Return False
+
+ Try
+
+ For i As Integer = 0 To SQLStatements.LastIndex
+ Session.DB.ExecuteSQL(SQLStatements(i))
+ Next
+
+ Session.DB.ExecuteSQL("COMMIT")
+
+ Catch err As DatabaseException
+ ShowErrorDialog("Create Table", "Could not create table.", err)
+ Return False
+
+ End Try
+
+ 'Success - no dialog
+ Var selectRowTag As New Dictionary
+ selectRowTag.Value("type") = "table"
+ selectRowTag.Value("name") = Name
+
+ Me.RefreshInfos(selectRowTag)
+ Return True
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub ActionDrop()
+ Var item As Dictionary = Me.GetSelectedTableRowTag()
+ If (item = Nil) Then Return
+
+ dlgDrop.Title = "Drop " + item.Lookup("type", "").StringValue.Titlecase
+ dlgDrop.Indicator = Indicators.Danger
+ dlgDrop.ActionButton.Caption = "Drop"
+ dlgDrop.CancelButton.Visible = True
+ dlgDrop.Message = "Are you sure you want to drop " + item.Lookup("type", "").StringValue + " '" + item.Lookup("name", "").StringValue + "'?"
+ dlgDrop.Explanation = "This action cannot be undone."
+
+ edictActionItem = item
+
+ dlgDrop.ShowWithActionDanger()
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub ActionDropButtonPressed(obj As WebMessageDialog, button As WebMessageDialogButton)
+ Var dictDropItem As Dictionary = edictActionItem
+ edictActionItem = Nil
+
+ If (button <> obj.ActionButton) Then Return
+ If (dictDropItem = Nil) Then Return
+
+ Try
+ Session.DB.ExecuteSQL("DROP " + dictDropItem.Lookup("type", "").StringValue.Uppercase + " IF EXISTS " + dictDropItem.Lookup("name", "").StringValue.EscapeSqlFieldIfRequired)
+ Session.DB.ExecuteSQL("COMMIT")
+
+ Catch err As DatabaseException
+ ShowErrorDialog("Drop " + dictDropItem.Lookup("type", "").StringValue.Titlecase, "Could not drop " + dictDropItem.Lookup("type", "").StringValue.Lowercase + ".", err)
+
+ Finally
+ Me.RefreshInfos()
+
+ End Try
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h0
+ Sub Constructor()
+ Super.Constructor
+
+ Me.Area = "Data"
+ Me.Title = "Tables & Indexes"
+ Me.Table = lstInfos
+ Me.SearchAvailable = True
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function GetSelectedDatabasename() As String
+ If (lstFilterDatabase.SelectedRowIndex < 0) Then Return ""
+ Return lstFilterDatabase.RowTagAt(lstFilterDatabase.SelectedRowIndex)
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h1
+ Protected Sub Load()
+ Me.LoadDatabases()
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub LoadDatabases()
+ lstFilterDatabase.RemoveAllRows
+
+ Try
+ Var rs As RowSet = Session.DB.SelectSQL("SHOW DATABASES")
+ If (rs = Nil) Then Return
+
+ If (rs.RowCount > 0) Then
+ rs.MoveToFirstRow
+ While (Not rs.AfterLastRow)
+ lstFilterDatabase.AddRow(rs.Column("databasename").StringValue, rs.Column("databasename").StringValue)
+
+ rs.MoveToNextRow
+ Wend
+ End If
+
+ rs.Close
+
+ Catch DatabaseException
+
+ Finally
+ If (lstFilterDatabase.RowCount > 0) Then lstFilterDatabase.SelectedRowIndex = 0
+
+ End Try
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub RefreshButtons()
+ Var bCreateTable, bAlterTable, bCreateIndex, bDrop As Boolean
+
+ Var selectedDatabasename As String = Me.GetSelectedDatabasename()
+ Var selectedItem As Dictionary = Me.GetSelectedTableRowTag()
+
+ If (selectedDatabasename <> "") Then
+ bCreateTable = True
+ bCreateIndex = True
+ End If
+
+ If (selectedItem <> Nil) And (selectedItem.Lookup("type", "").StringValue = "table") And (selectedItem.Lookup("name", "").StringValue <> "") Then
+ bAlterTable = True
+ End If
+
+ If (selectedItem <> Nil) And (selectedItem.Lookup("type", "").StringValue <> "") And (selectedItem.Lookup("name", "").StringValue <> "") Then
+ bDrop = True
+ End If
+
+ If (btnCreateTable.Enabled <> bCreateTable) Then btnCreateTable.Enabled = bCreateTable
+ If (btnCreateIndex.Enabled <> bCreateIndex) Then btnCreateIndex.Enabled = bCreateIndex
+ If (btnAlterTable.Enabled <> bAlterTable) Then btnAlterTable.Enabled = bAlterTable
+ If (btnDrop.Enabled <> bDrop) Then btnDrop.Enabled = bDrop
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub RefreshInfos(selectRowTag As Dictionary = nil)
+ If (selectRowTag = Nil) Then
+ selectRowTag = Me.GetSelectedTableRowTag()
+ End If
+
+ edictSelectAfterReload = selectRowTag
+
+ Me.TableLoad()
+
+ 'Select Row async via TableRowDataLoaded
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h1
+ Protected Sub TableInitColumns()
+ Super.TableInitColumns()
+
+ Var col As DatasourceColumn
+
+ col = New DatasourceColumn()
+ col.Width = "15%"
+ col.DatabaseColumnName = "type"
+ col.Heading = "Type"
+ col.FieldType = DatasourceColumn.FieldTypes.Text
+ col.Sortable = True
+ col.SortDirection = WebListBox.SortDirections.Descending
+ Me.Columns.Add(col)
+
+ col = New DatasourceColumn()
+ col.Width = "20%"
+ col.DatabaseColumnName = "name"
+ col.Heading = "Name"
+ col.FieldType = DatasourceColumn.FieldTypes.Text
+ col.Sortable = True
+ col.SortDirection = WebListBox.SortDirections.None
+ Me.Columns.Add(col)
+
+ col = New DatasourceColumn()
+ col.Width = "65%"
+ col.DatabaseColumnName = "sql"
+ col.Heading = "SQL"
+ col.FieldType = DatasourceColumn.FieldTypes.Text
+ col.Sortable = False
+ col.SortDirection = WebListBox.SortDirections.None
+ Me.Columns.Add(col)
+
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h1
+ Protected Function TableLoadRowSet() As RowSet
+ Var filterDatabasename As String = Me.GetSelectedDatabasename()
+
+
+ Try
+ If (filterDatabasename <> "") Then
+ Session.DB.ExecuteSQL("USE DATABASE '" + filterDatabasename.EscapeSqlQuotes + "'")
+ Else
+ Session.DB.ExecuteSQL("CLEAR CURRENT DATABASE")
+ End If
+
+ Catch err As DatabaseException
+
+ End Try
+
+ If (filterDatabasename <> "") Then
+ Return Session.DB.SelectSQL("SELECT type, name, sql FROM sqlite_master WHERE (type='table' OR type='index') AND (name NOT LIKE 'sqlite_%') AND (name NOT LIKE 'cubesql_temp_%') ORDER BY type DESC, name")
+ End If
+
+ Return Nil
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h1
+ Protected Function TableNoRowsMessage() As String
+ Var sInfo As String = "No Tables & Indexes"
+
+ Var filterDatabasename As String = Me.GetSelectedDatabasename()
+ If (filterDatabasename <> "") Then
+ sInfo = sInfo + " for Database " + filterDatabasename
+ End If
+
+ If (Me.SearchValue <> "") Then
+ sInfo = sInfo + " matching '" + Me.SearchValue + "'"
+ End If
+
+ Return sInfo
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h1
+ Protected Sub TableRowDataLoaded()
+ Super.TableRowDataLoaded()
+
+ If (edictSelectAfterReload = Nil) Then
+ Me.RefreshButtons()
+ Return
+ End If
+
+ Var sSelectAfterReload As Dictionary = edictSelectAfterReload
+ edictSelectAfterReload = Nil
+
+ Var bFound As Boolean = False
+ For i As Integer = Me.Table.LastRowIndex DownTo 0
+ Var rowTag As Dictionary = Me.Table.RowTagAt(i)
+ If (rowTag IsA Dictionary) Then
+ If (rowTag.Lookup("type", "").StringValue = sSelectAfterReload.Lookup("type", "-").StringValue) And _
+ (rowTag.Lookup("name", "").StringValue = sSelectAfterReload.Lookup("name", "-").StringValue) Then
+
+ Me.Table.SelectedRowIndex = i
+ bFound = True
+ Exit 'Loop
+ End If
+ End If
+ Next
+
+ If (Not bFound) Then Me.Table.SelectedRowIndex = -1
+
+ Me.RefreshButtons()
+
+ End Sub
+ #tag EndMethod
+
+
+ #tag Property, Flags = &h21
+ Private edictActionItem As Dictionary
+ #tag EndProperty
+
+ #tag Property, Flags = &h21
+ Private edictSelectAfterReload As Dictionary
+ #tag EndProperty
+
+
+#tag EndWindowCode
+
+#tag Events lstInfos
+ #tag Event
+ Sub SelectionChanged(rows() As Integer)
+ #Pragma unused rows
+
+ Self.RefreshButtons()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events lstFilterDatabase
+ #tag Event
+ Sub SelectionChanged(item As WebMenuItem)
+ #Pragma unused item
+
+ If (Not ebOpened) Then Return
+
+ Self.TableLoad()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events btnDrop
+ #tag Event
+ Sub Pressed()
+ Self.ActionDrop()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events dlgDrop
+ #tag Event
+ Sub ButtonPressed(button As WebMessageDialogButton)
+ Self.ActionDropButtonPressed(Me, button)
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events btnCreateTable
+ #tag Event
+ Sub Pressed()
+ Self.ActionCreateTable()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events btnCreateIndex
+ #tag Event
+ Sub Pressed()
+ Self.ActionCreateIndex()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events btnAlterTable
+ #tag Event
+ Sub Pressed()
+ Self.ActionAlterTable()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag ViewBehavior
+ #tag ViewProperty
+ Name="Area"
+ Visible=false
+ Group="Behavior"
+ InitialValue="Home"
+ Type="String"
+ EditorType="MultiLineEditor"
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="SearchAvailable"
+ Visible=false
+ Group="Behavior"
+ InitialValue="False"
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mPanelIndex"
+ Visible=false
+ Group="Behavior"
+ InitialValue="-1"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="ControlCount"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Name"
+ Visible=true
+ Group="ID"
+ InitialValue=""
+ Type="String"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Super"
+ Visible=true
+ Group="ID"
+ InitialValue=""
+ Type="String"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Left"
+ Visible=true
+ Group="Position"
+ InitialValue="0"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Top"
+ Visible=true
+ Group="Position"
+ InitialValue="0"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="ControlID"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="String"
+ EditorType="MultiLineEditor"
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Enabled"
+ Visible=true
+ Group="Behavior"
+ InitialValue="True"
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockBottom"
+ Visible=true
+ Group="Behavior"
+ InitialValue="False"
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockHorizontal"
+ Visible=true
+ Group="Behavior"
+ InitialValue="False"
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockLeft"
+ Visible=true
+ Group="Behavior"
+ InitialValue="True"
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockRight"
+ Visible=true
+ Group="Behavior"
+ InitialValue="False"
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockTop"
+ Visible=true
+ Group="Behavior"
+ InitialValue="True"
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockVertical"
+ Visible=true
+ Group="Behavior"
+ InitialValue="False"
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Visible"
+ Visible=true
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mDesignHeight"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mDesignWidth"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mName"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="String"
+ EditorType="MultiLineEditor"
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="ScrollDirection"
+ Visible=true
+ Group="Behavior"
+ InitialValue="ScrollDirections.None"
+ Type="WebContainer.ScrollDirections"
+ EditorType="Enum"
+ #tag EnumValues
+ "0 - None"
+ "1 - Horizontal"
+ "2 - Vertical"
+ "3 - Both"
+ #tag EndEnumValues
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="TabIndex"
+ Visible=true
+ Group="Visual Controls"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Indicator"
+ Visible=false
+ Group="Visual Controls"
+ InitialValue=""
+ Type="WebUIControl.Indicators"
+ EditorType="Enum"
+ #tag EnumValues
+ "0 - Default"
+ "1 - Primary"
+ "2 - Secondary"
+ "3 - Success"
+ "4 - Danger"
+ "5 - Warning"
+ "6 - Info"
+ "7 - Light"
+ "8 - Dark"
+ "9 - Link"
+ #tag EndEnumValues
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LayoutType"
+ Visible=true
+ Group="View"
+ InitialValue="LayoutTypes.Fixed"
+ Type="LayoutTypes"
+ EditorType="Enum"
+ #tag EnumValues
+ "0 - Fixed"
+ "1 - Flex"
+ #tag EndEnumValues
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LayoutDirection"
+ Visible=true
+ Group="View"
+ InitialValue="LayoutDirections.LeftToRight"
+ Type="LayoutDirections"
+ EditorType="Enum"
+ #tag EnumValues
+ "0 - LeftToRight"
+ "1 - RightToLeft"
+ "2 - TopToBottom"
+ "3 - BottomToTop"
+ #tag EndEnumValues
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Title"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="String"
+ EditorType="MultiLineEditor"
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Width"
+ Visible=false
+ Group=""
+ InitialValue="250"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Height"
+ Visible=false
+ Group=""
+ InitialValue="250"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+#tag EndViewBehavior
diff --git a/webapp/dialogs/dlgIndexCreate.xojo_code b/webapp/dialogs/dlgIndexCreate.xojo_code
new file mode 100644
index 0000000..7b57335
--- /dev/null
+++ b/webapp/dialogs/dlgIndexCreate.xojo_code
@@ -0,0 +1,798 @@
+#tag WebPage
+Begin dlgBase dlgIndexCreate
+ Compatibility = ""
+ ControlCount = 0
+ ControlID = ""
+ Enabled = True
+ Height = 600
+ Index = -2147483648
+ Indicator = 0
+ LayoutDirection = 0
+ LayoutType = 0
+ Left = 0
+ LockBottom = False
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = False
+ LockTop = False
+ LockVertical = False
+ TabIndex = 0
+ Top = 0
+ Visible = True
+ Width = 600
+ _mDesignHeight = 0
+ _mDesignWidth = 0
+ _mPanelIndex = -1
+ Begin WebLabel labTitle
+ Bold = True
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 24.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Italic = False
+ Left = 20
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = True
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ Scope = 2
+ TabIndex = 0
+ TabStop = True
+ Text = "Create Index"
+ TextAlignment = 2
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 20
+ Underline = False
+ Visible = True
+ Width = 560
+ _mPanelIndex = -1
+ End
+ Begin WebRectangle rctFormContent
+ BackgroundColor = &cFFFFFF
+ ControlCount = 0
+ ControlID = ""
+ Enabled = True
+ HasBackgroundColor= False
+ Height = 457
+ Index = -2147483648
+ Indicator = 0
+ LayoutDirection = 0
+ LayoutType = 0
+ Left = 20
+ LockBottom = True
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = True
+ LockTop = True
+ LockVertical = False
+ Scope = 2
+ TabIndex = 1
+ TabStop = True
+ Tooltip = ""
+ Top = 66
+ Visible = True
+ Width = 560
+ _mDesignHeight = 0
+ _mDesignWidth = 0
+ _mPanelIndex = -1
+ Begin WebLabel labName
+ Bold = False
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 0.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ InitialParent = "rctFormContent"
+ Italic = False
+ Left = 40
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ Scope = 2
+ TabIndex = 0
+ TabPanelIndex = 0
+ TabStop = True
+ Text = "Name:"
+ TextAlignment = 0
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 86
+ Underline = False
+ Visible = True
+ Width = 140
+ _mPanelIndex = -1
+ End
+ Begin WebTextField edtName
+ AllowAutoComplete= False
+ AllowSpellChecking= False
+ Caption = ""
+ ControlID = ""
+ Enabled = True
+ FieldType = 0
+ Height = 38
+ Hint = ""
+ Index = -2147483648
+ Indicator = 0
+ InitialParent = "rctFormContent"
+ Left = 188
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = True
+ LockTop = True
+ LockVertical = False
+ MaximumCharactersAllowed= 0
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ ReadOnly = False
+ Scope = 2
+ TabIndex = 1
+ TabPanelIndex = 0
+ TabStop = True
+ Text = ""
+ TextAlignment = 0
+ Tooltip = ""
+ Top = 86
+ Visible = True
+ Width = 372
+ _mPanelIndex = -1
+ End
+ Begin WebLabel labTable
+ Bold = False
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 0.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ InitialParent = "rctFormContent"
+ Italic = False
+ Left = 40
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ Scope = 2
+ TabIndex = 2
+ TabPanelIndex = 0
+ TabStop = True
+ Text = "Table:"
+ TextAlignment = 0
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 132
+ Underline = False
+ Visible = True
+ Width = 140
+ _mPanelIndex = -1
+ End
+ Begin WebPopupMenu lstTable
+ ControlID = ""
+ Enabled = True
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ InitialParent = "rctFormContent"
+ InitialValue = ""
+ LastAddedRowIndex= 0
+ LastRowIndex = 0
+ Left = 188
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ Parent = "rctFormContent"
+ RowCount = 0
+ Scope = 2
+ SelectedRowIndex= 0
+ SelectedRowText = ""
+ TabIndex = 3
+ TabPanelIndex = 0
+ TabStop = True
+ Tooltip = ""
+ Top = 132
+ Visible = True
+ Width = 372
+ _mPanelIndex = -1
+ End
+ Begin WebListBox lstFields
+ ColumnCount = 2
+ ColumnWidths = "30, *"
+ ControlID = ""
+ Enabled = True
+ HasHeader = False
+ Height = 325
+ HighlightSortedColumn= True
+ Index = -2147483648
+ Indicator = 0
+ InitialValue = ""
+ LastAddedRowIndex= 0
+ LastColumnIndex = 0
+ LastRowIndex = 0
+ Left = 188
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ NoRowsMessage = "No Fields"
+ Parent = "rctFormContent"
+ ProcessingMessage= ""
+ RowCount = 0
+ RowSelectionType= 0
+ Scope = 0
+ SearchCriteria = ""
+ SelectedRowColor= &c0d6efd
+ SelectedRowIndex= 0
+ TabIndex = 5
+ TabPanelIndex = 0
+ TabStop = True
+ Tooltip = ""
+ Top = 178
+ Visible = True
+ Width = 372
+ _mPanelIndex = -1
+ End
+ Begin WebLabel labFields
+ Bold = False
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 0.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Italic = False
+ Left = 40
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ Scope = 2
+ TabIndex = 4
+ TabPanelIndex = 0
+ TabStop = True
+ Text = "Fields:"
+ TextAlignment = 0
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 178
+ Underline = False
+ Visible = True
+ Width = 140
+ _mPanelIndex = -1
+ End
+ End
+ Begin WebButton btnCreate
+ AllowAutoDisable= False
+ Cancel = False
+ Caption = "Create"
+ ControlID = ""
+ Default = True
+ Enabled = False
+ Height = 38
+ Index = -2147483648
+ Indicator = 1
+ Left = 480
+ LockBottom = True
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = True
+ LockTop = False
+ LockVertical = False
+ Scope = 2
+ TabIndex = 3
+ TabStop = True
+ Tooltip = ""
+ Top = 542
+ Visible = True
+ Width = 100
+ _mPanelIndex = -1
+ End
+ Begin WebButton btnCancel
+ AllowAutoDisable= False
+ Cancel = True
+ Caption = "Cancel"
+ ControlID = ""
+ Default = False
+ Enabled = True
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Left = 372
+ LockBottom = True
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = True
+ LockTop = False
+ LockVertical = False
+ Scope = 2
+ TabIndex = 2
+ TabStop = True
+ Tooltip = ""
+ Top = 542
+ Visible = True
+ Width = 100
+ _mPanelIndex = -1
+ End
+End
+#tag EndWebPage
+
+#tag WindowCode
+ #tag Event
+ Sub Shown()
+ edtName.SetFocus()
+
+ End Sub
+ #tag EndEvent
+
+
+ #tag Method, Flags = &h21
+ Private Function GetFields() As String()
+ Var fields() As String
+
+ Var dictRowTag As Dictionary
+ Var addField As String
+ Var isChecked As Boolean
+ For i As Integer = 0 To lstFields.LastRowIndex
+ Var rowTag As Variant = lstFields.RowTagAt(i)
+ If (rowTag IsA Dictionary) Then
+ dictRowTag = Dictionary(rowTag)
+ addField = dictRowTag.Lookup("name", "")
+ isChecked = dictRowTag.Lookup("checked", False)
+
+ If (isChecked And (addField <> "")) Then
+ fields.Add(addField)
+ End If
+ End If
+ Next
+
+ Return fields
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function GetTablename() As String
+ If (lstTable.SelectedRowIndex >= 0) Then Return lstTable.RowTagAt(lstTable.SelectedRowIndex)
+ Return ""
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub Load()
+ Try
+ Session.DB.ExecuteSQL("USE DATABASE '" + esDatabasename.EscapeSqlQuotes + "'")
+
+ Catch err As DatabaseException
+
+ Finally
+
+ Me.LoadTables()
+ Me.LoadFields()
+
+ Me.RefreshButtons()
+ End Try
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub LoadFields()
+ lstFields.RemoveAllRows
+
+ Var tablename As String = Me.GetTablename()
+ If (tablename = "") Then Return
+
+ Try
+ Var rs As RowSet = Session.DB.SelectSQL("PRAGMA table_info('" + tablename.EscapeSqlQuotes + "')")
+ If (rs <> Nil) Then
+ If (rs.RowCount > 0) Then
+ rs.MoveToFirstRow
+ While (Not rs.AfterLastRow)
+ lstFields.AddRow("", rs.Column("name").StringValue, rs.Column("name").StringValue)
+ lstFields.CellTextAt(lstFields.LastAddedRowIndex, 0) = New CheckboxCellRenderer(False)
+
+ Var rowTag As Dictionary = New Dictionary
+ rowTag.Value("name") = rs.Column("name").StringValue
+ rowTag.Value("checked") = False
+ lstFields.RowTagAt(lstFields.LastAddedRowIndex) = rowTag
+
+ rs.MoveToNextRow
+ Wend
+ End If
+
+ rs.Close
+ End If
+
+ Catch err As DatabaseException
+
+ Finally
+ lstFields.SelectedRowIndex = -1
+
+ End Try
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub LoadTables()
+ lstTable.RemoveAllRows
+
+ Try
+ Var rs As RowSet = Session.DB.SelectSQL("SHOW TABLES")
+ If (rs <> Nil) Then
+ If (rs.RowCount > 0) Then
+ rs.MoveToFirstRow
+ While (Not rs.AfterLastRow)
+ lstTable.AddRow(rs.Column("tablename").StringValue, rs.Column("tablename").StringValue)
+
+ rs.MoveToNextRow
+ Wend
+ End If
+
+ rs.Close
+ End If
+
+ Catch err As DatabaseException
+
+ Finally
+ If (lstTable.LastRowIndex >= 0) Then lstTable.SelectedRowIndex = 0
+
+ End Try
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub RefreshButtons()
+ btnCreate.Enabled = (edtName.Text.Trim <> "") And (Me.GetTablename() <> "") And (Me.GetFields().LastIndex >= 0)
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h0
+ Sub Show(Databasename As String)
+ esDatabasename = Databasename
+
+ Me.Load()
+
+ Super.Show()
+ End Sub
+ #tag EndMethod
+
+
+ #tag Hook, Flags = &h0
+ Event IndexCreateAction(Name As String, Table As String, Fields() As String) As Boolean
+ #tag EndHook
+
+
+ #tag Property, Flags = &h21
+ Private esDatabasename As String
+ #tag EndProperty
+
+
+#tag EndWindowCode
+
+#tag Events edtName
+ #tag Event
+ Sub TextChanged()
+ Self.RefreshButtons()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events lstTable
+ #tag Event
+ Sub SelectionChanged(item As WebMenuItem)
+ #Pragma unused item
+
+ If (Not ebShown) Then Return
+
+ Self.LoadFields()
+ Self.RefreshButtons()
+
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events lstFields
+ #tag Event
+ Sub CustomCellAction(row As Integer, column As Integer, identifier As String, value As Variant)
+ #Pragma unused column
+ #Pragma unused identifier
+
+ If (Not ebShown) Then Return
+
+ Var rowTag As Dictionary
+ If (row <= Me.LastRowIndex) Then rowTag = Me.RowTagAt(row)
+
+ If (rowTag = Nil) Then Return
+
+ rowTag.Value("checked") = value.BooleanValue
+
+ Self.RefreshButtons()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events btnCreate
+ #tag Event
+ Sub Pressed()
+ If IndexCreateAction(edtName.Text.Trim, Self.GetTablename().Trim, Self.GetFields()) Then
+ Self.Close()
+ End If
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events btnCancel
+ #tag Event
+ Sub Pressed()
+ Self.Close()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag ViewBehavior
+ #tag ViewProperty
+ Name="ControlCount"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mPanelIndex"
+ Visible=false
+ Group="Behavior"
+ InitialValue="-1"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Index"
+ Visible=false
+ Group="ID"
+ InitialValue="-2147483648"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Name"
+ Visible=true
+ Group="ID"
+ InitialValue=""
+ Type="String"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Super"
+ Visible=true
+ Group="ID"
+ InitialValue=""
+ Type="String"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Left"
+ Visible=true
+ Group="Position"
+ InitialValue="0"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Top"
+ Visible=true
+ Group="Position"
+ InitialValue="0"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="ControlID"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="String"
+ EditorType="MultiLineEditor"
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Enabled"
+ Visible=true
+ Group="Behavior"
+ InitialValue="True"
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Height"
+ Visible=true
+ Group="Behavior"
+ InitialValue="400"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LayoutType"
+ Visible=true
+ Group="Behavior"
+ InitialValue="LayoutTypes.Fixed"
+ Type="LayoutTypes"
+ EditorType="Enum"
+ #tag EnumValues
+ "0 - Fixed"
+ "1 - Flex"
+ #tag EndEnumValues
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockBottom"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockHorizontal"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockLeft"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockRight"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockTop"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockVertical"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Visible"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Width"
+ Visible=true
+ Group="Behavior"
+ InitialValue="600"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mDesignHeight"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mDesignWidth"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mName"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="String"
+ EditorType="MultiLineEditor"
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="TabIndex"
+ Visible=true
+ Group="Visual Controls"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Indicator"
+ Visible=false
+ Group="Visual Controls"
+ InitialValue=""
+ Type="WebUIControl.Indicators"
+ EditorType="Enum"
+ #tag EnumValues
+ "0 - Default"
+ "1 - Primary"
+ "2 - Secondary"
+ "3 - Success"
+ "4 - Danger"
+ "5 - Warning"
+ "6 - Info"
+ "7 - Light"
+ "8 - Dark"
+ "9 - Link"
+ #tag EndEnumValues
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LayoutDirection"
+ Visible=true
+ Group="WebView"
+ InitialValue="LayoutDirections.LeftToRight"
+ Type="LayoutDirections"
+ EditorType="Enum"
+ #tag EnumValues
+ "0 - LeftToRight"
+ "1 - RightToLeft"
+ "2 - TopToBottom"
+ "3 - BottomToTop"
+ #tag EndEnumValues
+ #tag EndViewProperty
+#tag EndViewBehavior
diff --git a/webapp/dialogs/dlgTableEditor.xojo_code b/webapp/dialogs/dlgTableEditor.xojo_code
new file mode 100644
index 0000000..df717d5
--- /dev/null
+++ b/webapp/dialogs/dlgTableEditor.xojo_code
@@ -0,0 +1,1293 @@
+#tag WebPage
+Begin dlgBase dlgTableEditor
+ Compatibility = ""
+ ControlCount = 0
+ ControlID = ""
+ Enabled = True
+ Height = 700
+ Index = -2147483648
+ Indicator = 0
+ LayoutDirection = 0
+ LayoutType = 0
+ Left = 0
+ LockBottom = False
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = False
+ LockTop = False
+ LockVertical = False
+ TabIndex = 0
+ Top = 0
+ Visible = True
+ Width = 800
+ _mDesignHeight = 0
+ _mDesignWidth = 0
+ _mPanelIndex = -1
+ Begin WebLabel labTitle
+ Bold = True
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 24.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Italic = False
+ Left = 20
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = True
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ Scope = 2
+ TabIndex = 0
+ TabStop = True
+ Text = "Table Editor"
+ TextAlignment = 2
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 20
+ Underline = False
+ Visible = True
+ Width = 760
+ _mPanelIndex = -1
+ End
+ Begin WebRectangle rctFormContent
+ BackgroundColor = &cFFFFFF
+ ControlCount = 0
+ ControlID = ""
+ Enabled = True
+ HasBackgroundColor= False
+ Height = 557
+ Index = -2147483648
+ Indicator = 0
+ LayoutDirection = 0
+ LayoutType = 0
+ Left = 20
+ LockBottom = True
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = True
+ LockTop = True
+ LockVertical = False
+ Scope = 2
+ TabIndex = 1
+ TabStop = True
+ Tooltip = ""
+ Top = 66
+ Visible = True
+ Width = 760
+ _mDesignHeight = 0
+ _mDesignWidth = 0
+ _mPanelIndex = -1
+ Begin WebLabel labTablename
+ Bold = False
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 0.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ InitialParent = "rctFormContent"
+ Italic = False
+ Left = 40
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ Scope = 2
+ TabIndex = 0
+ TabPanelIndex = 0
+ TabStop = True
+ Text = "Table Name:"
+ TextAlignment = 0
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 86
+ Underline = False
+ Visible = True
+ Width = 140
+ _mPanelIndex = -1
+ End
+ Begin WebTextField edtTablename
+ AllowAutoComplete= False
+ AllowSpellChecking= False
+ Caption = ""
+ ControlID = ""
+ Enabled = True
+ FieldType = 0
+ Height = 38
+ Hint = ""
+ Index = -2147483648
+ Indicator = 0
+ InitialParent = "rctFormContent"
+ Left = 188
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = True
+ LockTop = True
+ LockVertical = False
+ MaximumCharactersAllowed= 0
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ ReadOnly = False
+ Scope = 2
+ TabIndex = 1
+ TabPanelIndex = 0
+ TabStop = True
+ Text = ""
+ TextAlignment = 0
+ Tooltip = ""
+ Top = 86
+ Visible = True
+ Width = 572
+ _mPanelIndex = -1
+ End
+ Begin WebListBox lstFields
+ ColumnCount = 5
+ ColumnWidths = "40, *, 20%, 20%, 25%"
+ ControlID = ""
+ Enabled = True
+ HasHeader = True
+ Height = 418
+ HighlightSortedColumn= False
+ Index = -2147483648
+ Indicator = 0
+ InitialValue = ""
+ LastAddedRowIndex= 0
+ LastColumnIndex = 0
+ LastRowIndex = 0
+ Left = 40
+ LockBottom = False
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ NoRowsMessage = "No Fields"
+ Parent = "rctFormContent"
+ ProcessingMessage= ""
+ RowCount = 0
+ RowSelectionType= 1
+ Scope = 0
+ SearchCriteria = ""
+ SelectedRowColor= &c0d6efd
+ SelectedRowIndex= 0
+ TabIndex = 5
+ TabPanelIndex = 0
+ TabStop = True
+ Tooltip = ""
+ Top = 132
+ Visible = True
+ Width = 720
+ _mPanelIndex = -1
+ End
+ Begin WebButton btnFieldAdd
+ AllowAutoDisable= False
+ Cancel = False
+ Caption = "Add"
+ ControlID = ""
+ Default = False
+ Enabled = True
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Left = 660
+ LockBottom = True
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = True
+ LockTop = False
+ LockVertical = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ Scope = 2
+ TabIndex = 11
+ TabPanelIndex = 0
+ TabStop = True
+ Tooltip = ""
+ Top = 565
+ Visible = True
+ Width = 100
+ _mPanelIndex = -1
+ End
+ Begin WebLabel labField
+ Bold = False
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 0.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Italic = False
+ Left = 40
+ LockBottom = False
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ Scope = 2
+ TabIndex = 12
+ TabPanelIndex = 0
+ TabStop = True
+ Text = "Field:"
+ TextAlignment = 0
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 565
+ Underline = False
+ Visible = True
+ Width = 140
+ _mPanelIndex = -1
+ End
+ Begin WebButton btnFieldEdit
+ AllowAutoDisable= False
+ Cancel = False
+ Caption = "Edit"
+ ControlID = ""
+ Default = False
+ Enabled = True
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Left = 552
+ LockBottom = True
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = True
+ LockTop = False
+ LockVertical = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ Scope = 2
+ TabIndex = 13
+ TabPanelIndex = 0
+ TabStop = True
+ Tooltip = ""
+ Top = 565
+ Visible = True
+ Width = 100
+ _mPanelIndex = -1
+ End
+ Begin WebButton btnFieldDelete
+ AllowAutoDisable= False
+ Cancel = False
+ Caption = "Delete"
+ ControlID = ""
+ Default = False
+ Enabled = True
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Left = 444
+ LockBottom = True
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = True
+ LockTop = False
+ LockVertical = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ Scope = 2
+ TabIndex = 14
+ TabPanelIndex = 0
+ TabStop = True
+ Tooltip = ""
+ Top = 565
+ Visible = True
+ Width = 100
+ _mPanelIndex = -1
+ End
+ End
+ Begin WebButton btnSave
+ AllowAutoDisable= False
+ Cancel = False
+ Caption = "Create"
+ ControlID = ""
+ Default = True
+ Enabled = False
+ Height = 38
+ Index = -2147483648
+ Indicator = 1
+ Left = 680
+ LockBottom = True
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = True
+ LockTop = False
+ LockVertical = False
+ Scope = 2
+ TabIndex = 3
+ TabStop = True
+ Tooltip = ""
+ Top = 642
+ Visible = True
+ Width = 100
+ _mPanelIndex = -1
+ End
+ Begin WebButton btnCancel
+ AllowAutoDisable= False
+ Cancel = True
+ Caption = "Cancel"
+ ControlID = ""
+ Default = False
+ Enabled = True
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Left = 572
+ LockBottom = True
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = True
+ LockTop = False
+ LockVertical = False
+ Scope = 2
+ TabIndex = 2
+ TabStop = True
+ Tooltip = ""
+ Top = 642
+ Visible = True
+ Width = 100
+ _mPanelIndex = -1
+ End
+End
+#tag EndWebPage
+
+#tag WindowCode
+ #tag Event
+ Sub Shown()
+ If ebIsCreate Then
+ edtTablename.SetFocus()
+ End If
+
+ End Sub
+ #tag EndEvent
+
+
+ #tag Method, Flags = &h21
+ Private Sub ActionFieldAdd()
+ Var dlgField As New dlgTableEditorField
+ AddHandler dlgField.FieldSaveAction, WeakAddressOf ActionFieldAddButtonPressed
+ dlgField.ShowAsAdd()
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function ActionFieldAddButtonPressed(obj As dlgTableEditorField, Name As String, Type As String, Default As String, Constraint As String) As Boolean
+ #Pragma unused obj
+
+ If (Name = "") Then Return False
+
+ Var dictField As New Dictionary
+ dictField.Value("isNew") = True
+ dictField.Value("fieldname") = Name
+ dictField.Value("fieldtype") = Type
+ dictField.Value("defaultvalue") = Default
+ dictField.Value("constraint") = Constraint
+
+ Var sanityMessage As String = Me.SanityCheckField(dictField)
+ If (sanityMessage <> "") Then
+ ShowWarningDialog("Add Field", "Can't add field.", sanityMessage)
+ Return False
+ End If
+
+ Me.AddField(dictField)
+
+ Self.RefreshButtons()
+ Return True
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub ActionFieldDelete()
+ Var selectedField As Dictionary = Me.GetSelectedField()
+ If (selectedField = Nil) Then Return
+
+ If (selectedField.Lookup("isNew", True).BooleanValue = False) Then
+ If (Not ebDropColumnSupported) Then Return
+ If selectedField.Lookup("constraint", "").StringValue.Contains("PRIMARY", ComparisonOptions.CaseInsensitive) Or _
+ selectedField.Lookup("constraint", "").StringValue.Contains("UNIQUE", ComparisonOptions.CaseInsensitive) Or _
+ selectedField.Lookup("isIndexed", False).BooleanValue Then
+ Return
+ End If
+
+ 'Drop existing Column
+ If (lstFields.SelectedRowIndex >= 0) And (selectedField = lstFields.RowTagAt(lstFields.SelectedRowIndex)) Then
+ selectedField.Value("isDropped") = (Not selectedField.Lookup("isDropped", False).BooleanValue)
+ lstFields.CellTextAt(lstFields.SelectedRowIndex, 0) = Me.GetFieldIcon(selectedField)
+ lstFields.RowTagAt(lstFields.SelectedRowIndex) = selectedField
+ End If
+
+ Self.RefreshButtons()
+ Return
+ End If
+
+ 'Remove new added Field
+ If (lstFields.SelectedRowIndex >= 0) Then
+ Var rowTag As Variant = lstFields.RowTagAt(lstFields.SelectedRowIndex)
+ If (rowTag IsA Dictionary) Then
+ If (Dictionary(rowTag).Lookup("isNew", False).BooleanValue = True) Then
+ lstFields.RemoveRowAt(lstFields.SelectedRowIndex)
+ End If
+ End If
+ End If
+
+ Self.RefreshButtons()
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub ActionFieldEdit()
+ Var selectedField As Dictionary = Me.GetSelectedField()
+ If (selectedField = Nil) Then Return
+
+ If (selectedField.Lookup("isNew", True).BooleanValue = False) Then
+ If (Not ebRenameColumnSupported) Then Return
+ End If
+
+ Var dlgField As New dlgTableEditorField
+ AddHandler dlgField.FieldSaveAction, WeakAddressOf ActionFieldEditButtonPressed
+
+ If (selectedField.Lookup("isNew", True).BooleanValue = True) Then
+ dlgField.ShowAsEdit(selectedField.Lookup("fieldname", ""), selectedField.Lookup("fieldtype", ""), selectedField.Lookup("defaultvalue", ""), selectedField.Lookup("constraint", ""))
+ Else
+ dlgField.ShowAsRename(selectedField.Lookup("fieldname", ""), selectedField.Lookup("fieldtype", ""), selectedField.Lookup("defaultvalue", ""), selectedField.Lookup("constraint", ""))
+ End If
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function ActionFieldEditButtonPressed(obj As dlgTableEditorField, Name As String, Type As String, Default As String, Constraint As String) As Boolean
+ #Pragma unused obj
+
+ If (Name = "") Then Return False
+
+ Var selectedField As Dictionary = Me.GetSelectedField()
+ If (selectedField = Nil) Then Return False
+
+ Var modifiedField As New Dictionary
+ For Each vKey As Variant In selectedField.Keys
+ modifiedField.Value(vKey) = selectedField.Value(vKey)
+ Next
+
+ modifiedField.Value("fieldname") = Name
+ modifiedField.Value("fieldtype") = Type
+ modifiedField.Value("defaultvalue") = Default
+ modifiedField.Value("constraint") = Constraint
+
+ If (modifiedField.Lookup("isNew", False).BooleanValue = False) Then
+ Var bIsRenamed As Boolean = (modifiedField.Lookup("fieldname_loaded", "").StringValue.Compare(Name, ComparisonOptions.CaseInsensitive) <> 0)
+ modifiedField.Value("isRenamed") = bIsRenamed
+ End If
+
+ Var sanityMessage As String = Me.SanityCheckField(modifiedField)
+ If (sanityMessage <> "") Then
+ ShowWarningDialog("Edit Field", "Can't edit field.", sanityMessage)
+ Return False
+ End If
+
+ lstFields.CellTextAt(lstFields.SelectedRowIndex, 0) = Me.GetFieldIcon(modifiedField)
+ lstFields.CellTextAt(lstFields.SelectedRowIndex, 1) = modifiedField.Lookup("fieldname", "").StringValue
+ lstFields.CellTextAt(lstFields.SelectedRowIndex, 2) = modifiedField.Lookup("fieldtype", "").StringValue
+ lstFields.CellTextAt(lstFields.SelectedRowIndex, 3) = modifiedField.Lookup("defaultvalue", "").StringValue
+ lstFields.CellTextAt(lstFields.SelectedRowIndex, 4) = modifiedField.Lookup("constraint", "").StringValue
+ lstFields.RowTagAt(lstFields.SelectedRowIndex) = modifiedField
+
+ Self.RefreshButtons()
+ Return True
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub AddField(dictField As Dictionary)
+ If (dictField = Nil) Then Return
+
+ lstFields.AddRow("")
+ lstFields.CellTextAt(lstFields.LastAddedRowIndex, 0) = Me.GetFieldIcon(dictField)
+ lstFields.CellTextAt(lstFields.LastAddedRowIndex, 1) = dictField.Lookup("fieldname", "").StringValue
+ lstFields.CellTextAt(lstFields.LastAddedRowIndex, 2) = dictField.Lookup("fieldtype", "").StringValue
+ lstFields.CellTextAt(lstFields.LastAddedRowIndex, 3) = dictField.Lookup("defaultvalue", "").StringValue
+ lstFields.CellTextAt(lstFields.LastAddedRowIndex, 4) = dictField.Lookup("constraint", "").StringValue
+ lstFields.RowTagAt(lstFields.LastAddedRowIndex) = dictField
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function GetFieldIcon(field As Dictionary) As WebListboxImageRenderer
+ Var icon As WebPicture
+
+ If (field.Lookup("isNew", False).BooleanValue = True) Then
+ icon = WebPicture.BootstrapIcon("plus-circle-fill", Color.Green)
+ Else
+ icon = WebPicture.BootstrapIcon("circle-fill", Color.Green)
+ If (field.Lookup("isRenamed", False).BooleanValue = True) Then
+ icon = WebPicture.BootstrapIcon("c-circle-fill", Color.Orange)
+ End If
+ If (field.Lookup("isDropped", False).BooleanValue = True) Then
+ icon = WebPicture.BootstrapIcon("x-circle-fill", Color.Red)
+ End If
+ End If
+
+ Return New WebListboxImageRenderer(icon.URL, True)
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function GetFields() As Dictionary()
+ Var fields() As Dictionary
+
+ For i As Integer = 0 To lstFields.LastRowIndex
+
+ Var rowTag As Variant = lstFields.RowTagAt(i)
+ If (rowTag IsA Dictionary) Then
+ fields.Add(Dictionary(rowTag))
+ End If
+ Next
+
+ Return fields
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function GetSelectedField() As Dictionary
+ If (lstFields.SelectedRowIndex >= 0) Then
+ Var rowTag As Variant = lstFields.RowTagAt(lstFields.SelectedRowIndex)
+ If (rowTag IsA Dictionary) Then
+ Return Dictionary(rowTag)
+ End If
+ End If
+
+ Return Nil
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub LoadTableForAlter(Tablename As String)
+ lstFields.RemoveAllRows()
+
+ Try
+ Var rs As RowSet
+
+ Var uniqueColumns() As String
+ Try
+ If (Session.DBEngineVersion >= Version_AsDouble("3.16.0")) Then
+ rs = Session.DB.SelectSQL("SELECT DISTINCT ii.name AS unique_column_name FROM sqlite_master AS m, pragma_index_list(m.name) AS il, pragma_index_info(il.name) AS ii WHERE m.type = 'table' AND m.name = '" + Tablename.EscapeSqlQuotes + "' AND il.[unique] = 1")
+ If (rs <> Nil) And (rs.RowCount > 0) Then
+
+ rs.MoveToFirstRow
+ While (Not rs.AfterLastRow)
+ uniqueColumns.Add(rs.Column("unique_column_name").StringValue)
+ rs.MoveToNextRow
+ Wend
+ End If
+ End If
+ Catch err As DatabaseException
+ 'ignore
+ End Try
+
+ Var indexedColumns() As String
+ Try
+ If (Session.DBEngineVersion >= Version_AsDouble("3.16.0")) Then
+ rs = Session.DB.SelectSQL("SELECT DISTINCT ii.name AS indexed_column_name FROM sqlite_master AS m, pragma_index_list(m.name) AS il, pragma_index_info(il.name) AS ii WHERE m.type = 'table' AND m.name = '" + Tablename.EscapeSqlQuotes + "'")
+ If (rs <> Nil) And (rs.RowCount > 0) Then
+
+ rs.MoveToFirstRow
+ While (Not rs.AfterLastRow)
+ indexedColumns.Add(rs.Column("indexed_column_name").StringValue)
+ rs.MoveToNextRow
+ Wend
+ End If
+ End If
+ Catch err As DatabaseException
+ 'ignore
+ End Try
+
+
+ rs = Session.DB.SelectSQL("PRAGMA TABLE_INFO(" + Tablename.EscapeSqlFieldIfRequired + ")")
+ If (rs = Nil) Then Return
+
+ If (rs.RowCount > 0) Then
+ rs.MoveToFirstRow
+ While (Not rs.AfterLastRow)
+ Var defaultValue As String = rs.Column("dflt_value").StringValue
+ If (defaultValue.Length >= 2) And (defaultValue.Left(1) = "'") And (defaultValue.Right(1) = "'") Then
+ defaultValue = defaultValue.Middle(1, defaultValue.Length-2)
+ End If
+
+ Var dictField As New Dictionary
+ dictField.Value("isNew") = False
+ dictField.Value("fieldname") = rs.Column("name").StringValue
+ dictField.Value("fieldname_loaded") = rs.Column("name").StringValue
+ dictField.Value("fieldtype") = rs.Column("type").StringValue
+ dictField.Value("defaultvalue") = defaultValue
+
+ If (rs.Column("pk").StringValue = "1") Then
+ dictField.Value("constraint") = "PRIMARY KEY"
+ ElseIf (rs.Column("notnull").StringValue = "1") Then
+ dictField.Value("constraint") = "NOT NULL"
+ ElseIf (uniqueColumns.IndexOf(rs.Column("name").StringValue) >= 0) Then
+ dictField.Value("constraint") = "UNIQUE"
+ End If
+
+ If (indexedColumns.IndexOf(rs.Column("name").StringValue) >= 0) Then
+ dictField.Value("isIndexed") = True
+ Else
+ dictField.Value("isIndexed") = False
+ End If
+
+ Me.AddField(dictField)
+
+ rs.MoveToNextRow
+ Wend
+ End If
+
+ rs.Close
+
+ Catch DatabaseException
+
+ End Try
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub RefreshButtons()
+ Var bHasRenamedTablename As Boolean
+ Var bHasNewFields As Boolean
+ Var bHasRenamedFields As Boolean
+ Var bHasDroppedFields As Boolean
+
+ If ebIsAlter And ebRenameTablenameSupported And (esLoadedTablename <> edtTablename.Text.Trim) Then
+ bHasRenamedTablename = True
+ End If
+
+ Var fields() As Dictionary = Me.GetFields()
+ For Each field As Dictionary In fields
+ If (field.Lookup("isNew", False).BooleanValue = True) Then bHasNewFields = True
+ If ebIsAlter And (field.Lookup("isNew", True).BooleanValue = False) Then
+ If (field.Lookup("isDropped", False) = True) Then
+ bHasDroppedFields = True
+ ElseIf (field.Lookup("isRenamed", False) = True) Then
+ bHasRenamedFields = True
+ End If
+ End If
+ Next
+
+ Var selectedField As Dictionary = Me.GetSelectedField()
+
+ Var bAdd As Boolean = True
+ If (btnFieldAdd.Enabled <> bAdd) Then btnFieldAdd.Enabled = bAdd
+
+ Var bEdit As Boolean = (selectedField <> Nil)
+ If (bEdit = True) Then
+ If (selectedField.Lookup("isNew", True).BooleanValue = True) Then
+ If (btnFieldEdit.Indicator <> Indicators.Default) Then btnFieldEdit.Indicator = Indicators.Default
+ If (btnFieldEdit.Caption <> "Edit") Then btnFieldEdit.Caption = "Edit"
+ bEdit = True
+ Else
+ If (btnFieldEdit.Indicator <> Indicators.Warning) Then btnFieldEdit.Indicator = Indicators.Warning
+ If (btnFieldEdit.Caption <> "Rename") Then btnFieldEdit.Caption = "Rename"
+ bEdit = ebRenameColumnSupported
+ End If
+ End If
+ If (btnFieldEdit.Enabled <> bEdit) Then btnFieldEdit.Enabled = bEdit
+ If (btnFieldEdit.Visible <> bEdit) Then btnFieldEdit.Visible = bEdit
+
+ Var bDelete As Boolean = (selectedField <> Nil)
+ If (bDelete = True) Then
+ If (selectedField.Lookup("isNew", False).BooleanValue = True) Then
+ If (btnFieldDelete.Indicator <> Indicators.Default) Then btnFieldDelete.Indicator = Indicators.Default
+ If (btnFieldDelete.Caption <> "Delete") Then btnFieldDelete.Caption = "Delete"
+ bDelete = True
+ Else
+ Var dropCaption As String = If(selectedField.Lookup("isDropped", False).BooleanValue = True, "UnDrop", "Drop")
+ If (btnFieldDelete.Caption <> dropCaption) Then btnFieldDelete.Caption = dropCaption
+ If (btnFieldDelete.Indicator <> Indicators.Danger) Then btnFieldDelete.Indicator = Indicators.Danger
+ bDelete = ebDropColumnSupported And _
+ (Not selectedField.Lookup("constraint", "").StringValue.Contains("PRIMARY", ComparisonOptions.CaseInsensitive)) And _
+ (Not selectedField.Lookup("constraint", "").StringValue.Contains("UNIQUE", ComparisonOptions.CaseInsensitive)) And _
+ (Not selectedField.Lookup("isIndexed", False).BooleanValue)
+ End If
+ End If
+ If (btnFieldDelete.Enabled <> bDelete) Then btnFieldDelete.Enabled = bDelete
+ If (btnFieldDelete.Visible <> bDelete) Then btnFieldDelete.Visible = bDelete
+
+ Var bSave As Boolean = (edtTablename.Text.Trim <> "") And (bHasNewFields Or bHasDroppedFields Or bHasRenamedFields Or bHasRenamedTablename)
+ If (btnSave.Enabled <> bSave) Then btnSave.Enabled = bSave
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function SanityCheckField(field As Dictionary) As String
+ If (field = Nil) Then Return ""
+
+ If ebIsAlter And (field.Lookup("isNew", False).BooleanValue = True) Then
+ 'new Fields in ALTER TABLE
+ Var defaultValue As String = field.Lookup("defaultvalue", "").StringValue
+ Select Case defaultValue
+ Case "CURRENT_TIME", "CURRENT_DATE", "CURRENT_TIMESTAMP"
+ Return "The column may not have a default value of CURRENT_TIME, CURRENT_DATE or CURRENT_TIMESTAMP in an ALTER TABLE command."
+ End Select
+
+ Var constraint As String = field.Lookup("constraint", "").StringValue
+ If (constraint.Contains("PRIMARY KEY") Or constraint.Contains("UNIQUE")) Then
+ Return "The column may not have a PRIMARY KEY or UNIQUE constraint in an ALTER TABLE command."
+ End If
+ End If
+
+ Return ""
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function SaveAsSQL() As String()
+ If ebIsCreate Then
+ Return Me.SaveAsSQLCreate()
+ End If
+
+ If ebIsAlter Then
+ Return Me.SaveAsSQLAlter()
+ End If
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function SaveAsSQLAlter() As String()
+ Var sqlStatements() As String
+
+ If (esLoadedTablename <> edtTablename.Text.Trim) Then
+ If ebRenameTablenameSupported Then
+ 'Rename Table
+ Var sqlRename As String = "ALTER TABLE " + esLoadedTablename.EscapeSqlFieldIfRequired + _
+ " RENAME TO " + edtTablename.Text.Trim.EscapeSqlFieldIfRequired
+ sqlStatements.Add(sqlRename)
+
+ Else
+ 'Oops, should not have happened...make sure altering the loaded tablename
+ edtTablename.Text = esLoadedTablename
+ End If
+ End If
+
+ Var fields() As Dictionary = Me.GetFields()
+
+ Var field As Dictionary
+ For i As Integer = 0 To fields.LastIndex
+ field = fields(i)
+ If (field.Lookup("isNew", False).BooleanValue <> True) Then
+ If (field.Lookup("isDropped", False) = True) And ebDropColumnSupported Then
+ 'Drop Column
+ Var sqlDrop As String = "ALTER TABLE " + edtTablename.Text.Trim.EscapeSqlFieldIfRequired + _
+ " DROP COLUMN " + field.Lookup("fieldname_loaded", "").StringValue.EscapeSqlFieldIfRequired
+ sqlStatements.Add(sqlDrop)
+
+ Continue
+ End If
+
+ If (field.Lookup("isRenamed", False) = True) And ebRenameColumnSupported Then
+ 'Rename Column
+ Var sqlRename As String = "ALTER TABLE " + edtTablename.Text.Trim.EscapeSqlFieldIfRequired + _
+ " RENAME COLUMN " + field.Lookup("fieldname_loaded", "").StringValue.EscapeSqlFieldIfRequired + _
+ " TO " + field.Lookup("fieldname", "").StringValue.EscapeSqlFieldIfRequired
+ sqlStatements.Add(sqlRename)
+
+ Continue
+ End If
+
+ Continue
+ End If
+
+ 'Add Column
+ Var sqlField As String = field.Lookup("fieldname", "").StringValue.EscapeSqlFieldIfRequired + _
+ If(field.Lookup("fieldtype", "").StringValue <> "", " " + field.Lookup("fieldtype", "").StringValue, "")
+
+ Select Case field.Lookup("constraint", "").StringValue
+ Case "UNIQUE (multi)"
+ 'not allowed in ALTER TABLE
+ Case "UNIQUE (single)"
+ 'not allowed in ALTER TABLE
+ Else
+ sqlField = sqlField + " " + field.Lookup("constraint", "").StringValue
+ End Select
+
+ If (field.Lookup("defaultvalue", "").StringValue <> "") Then
+ sqlField = sqlField + " DEFAULT " + field.Lookup("defaultvalue", "").StringValue.EscapeSqlDefaultValueIfRequired
+ End If
+
+ Var sql As String = "ALTER TABLE " + edtTablename.Text.Trim.EscapeSqlFieldIfRequired + _
+ " ADD COLUMN " + sqlField
+
+ sqlStatements.Add(sql)
+ Next
+
+ Return sqlStatements
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Function SaveAsSQLCreate() As String()
+ Var fields() As Dictionary = Me.GetFields()
+
+ Var field As Dictionary
+ Var sqlFields() As String
+ Var multiUniqueFields() As String
+ For i As Integer = 0 To fields.LastIndex
+ field = fields(i)
+ If (field.Lookup("isNew", False).BooleanValue <> True) Then Continue
+
+ Var sqlField As String = field.Lookup("fieldname", "").StringValue.EscapeSqlFieldIfRequired + _
+ If(field.Lookup("fieldtype", "").StringValue <> "", " " + field.Lookup("fieldtype", "").StringValue, "")
+
+ Select Case field.Lookup("constraint", "").StringValue
+ Case "UNIQUE (multi)"
+ 'add later at table level
+ multiUniqueFields.Add(field.Lookup("fieldname", "").StringValue.EscapeSqlFieldIfRequired)
+ Case "UNIQUE (single)"
+ sqlField = sqlField + " UNIQUE"
+ Else
+ sqlField = sqlField + " " + field.Lookup("constraint", "").StringValue
+ End Select
+
+ If (field.Lookup("defaultvalue", "").StringValue <> "") Then
+ sqlField = sqlField + " DEFAULT " + field.Lookup("defaultvalue", "").StringValue.EscapeSqlDefaultValueIfRequired
+ End If
+
+ sqlFields.Add(sqlField)
+ Next
+
+ Var sqlUniqueMulti As String
+ If (multiUniqueFields.LastIndex >= 0) Then
+ sqlUniqueMulti = ", UNIQUE (" + String.FromArray(multiUniqueFields, ", ") + ")"
+ End If
+
+ Var sql As String = "CREATE TABLE " + edtTablename.Text.Trim.EscapeSqlFieldIfRequired + " (" + _
+ String.FromArray(sqlFields, ", ") + _
+ sqlUniqueMulti + _
+ ")"
+
+ Return Array(sql)
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h0
+ Sub ShowAsAlter(Tablename As String)
+ btnSave.Caption = "Alter"
+ edtTablename.Text = Tablename
+ ebIsCreate = False
+ ebIsAlter = True
+ esLoadedTablename = Tablename
+
+ Me.Show_InitSupportedCommands()
+ Me.LoadTableForAlter(Tablename)
+ edtTablename.Enabled = ebRenameTablenameSupported
+
+ Me.RefreshButtons()
+
+ Super.Show()
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h0
+ Sub ShowAsCreate()
+ btnSave.Caption = "Create"
+ ebIsCreate = True
+ ebIsAlter = False
+ esLoadedTablename = ""
+
+ Me.Show_InitSupportedCommands()
+ Me.RefreshButtons()
+
+ Super.Show()
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub Show_InitSupportedCommands()
+ ebRenameColumnSupported = (Session.DBEngineVersion >= Version_AsDouble("3.25.0"))
+ ebDropColumnSupported = (Session.DBEngineVersion >= Version_AsDouble("3.35.0"))
+
+ 'The behavior of ALTER TABLE when renaming a table was enhanced in versions 3.25.0 (2018-09-15) and 3.26.0 (2018-12-01) in order to carry the rename operation forward into triggers and views that reference the renamed table.
+ ebRenameTablenameSupported = (Session.DBEngineVersion >= Version_AsDouble("3.26.0"))
+ End Sub
+ #tag EndMethod
+
+
+ #tag Hook, Flags = &h0
+ Event TableEditorSaveAction(Name As String, SQLStatements() As String) As Boolean
+ #tag EndHook
+
+
+ #tag Property, Flags = &h21
+ Private ebDropColumnSupported As Boolean
+ #tag EndProperty
+
+ #tag Property, Flags = &h21
+ Private ebIsAlter As Boolean
+ #tag EndProperty
+
+ #tag Property, Flags = &h21
+ Private ebIsCreate As Boolean
+ #tag EndProperty
+
+ #tag Property, Flags = &h21
+ Private ebRenameColumnSupported As Boolean
+ #tag EndProperty
+
+ #tag Property, Flags = &h21
+ Private ebRenameTablenameSupported As Boolean
+ #tag EndProperty
+
+ #tag Property, Flags = &h21
+ Private esLoadedTablename As String
+ #tag EndProperty
+
+
+#tag EndWindowCode
+
+#tag Events edtTablename
+ #tag Event
+ Sub TextChanged()
+ If ebIsAlter Then
+ If (Me.Text.Trim <> esLoadedTablename) Then
+ labTablename.TextColor = Color.Orange
+ Else
+ labTablename.TextColor = nil
+ End If
+ End If
+
+ Self.RefreshButtons()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events lstFields
+ #tag Event
+ Sub Opening()
+ Me.HeaderAt(0) = " "
+ Me.HeaderAt(1) = "Fieldname"
+ Me.HeaderAt(2) = "Type"
+ Me.HeaderAt(3) = "Default"
+ Me.HeaderAt(4) = "Constraint"
+
+ Me.ColumnSortTypeAt(0) = WebListBox.SortTypes.Unsortable
+ Me.ColumnSortTypeAt(1) = WebListBox.SortTypes.Unsortable
+ Me.ColumnSortTypeAt(2) = WebListBox.SortTypes.Unsortable
+ Me.ColumnSortTypeAt(3) = WebListBox.SortTypes.Unsortable
+ Me.ColumnSortTypeAt(4) = WebListBox.SortTypes.Unsortable
+
+ End Sub
+ #tag EndEvent
+ #tag Event
+ Sub SelectionChanged(rows() As Integer)
+ #Pragma unused rows
+
+ Self.RefreshButtons()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events btnFieldAdd
+ #tag Event
+ Sub Pressed()
+ Self.ActionFieldAdd()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events btnFieldEdit
+ #tag Event
+ Sub Pressed()
+ Self.ActionFieldEdit()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events btnFieldDelete
+ #tag Event
+ Sub Pressed()
+ Self.ActionFieldDelete()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events btnSave
+ #tag Event
+ Sub Pressed()
+ If TableEditorSaveAction(edtTablename.Text.Trim, Self.SaveAsSQL()) Then
+ Self.Close()
+ End If
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events btnCancel
+ #tag Event
+ Sub Pressed()
+ Self.Close()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag ViewBehavior
+ #tag ViewProperty
+ Name="ControlCount"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mPanelIndex"
+ Visible=false
+ Group="Behavior"
+ InitialValue="-1"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Index"
+ Visible=false
+ Group="ID"
+ InitialValue="-2147483648"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Name"
+ Visible=true
+ Group="ID"
+ InitialValue=""
+ Type="String"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Super"
+ Visible=true
+ Group="ID"
+ InitialValue=""
+ Type="String"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Left"
+ Visible=true
+ Group="Position"
+ InitialValue="0"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Top"
+ Visible=true
+ Group="Position"
+ InitialValue="0"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="ControlID"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="String"
+ EditorType="MultiLineEditor"
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Enabled"
+ Visible=true
+ Group="Behavior"
+ InitialValue="True"
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Height"
+ Visible=true
+ Group="Behavior"
+ InitialValue="400"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LayoutType"
+ Visible=true
+ Group="Behavior"
+ InitialValue="LayoutTypes.Fixed"
+ Type="LayoutTypes"
+ EditorType="Enum"
+ #tag EnumValues
+ "0 - Fixed"
+ "1 - Flex"
+ #tag EndEnumValues
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockBottom"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockHorizontal"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockLeft"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockRight"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockTop"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockVertical"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Visible"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Width"
+ Visible=true
+ Group="Behavior"
+ InitialValue="600"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mDesignHeight"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mDesignWidth"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mName"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="String"
+ EditorType="MultiLineEditor"
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="TabIndex"
+ Visible=true
+ Group="Visual Controls"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Indicator"
+ Visible=false
+ Group="Visual Controls"
+ InitialValue=""
+ Type="WebUIControl.Indicators"
+ EditorType="Enum"
+ #tag EnumValues
+ "0 - Default"
+ "1 - Primary"
+ "2 - Secondary"
+ "3 - Success"
+ "4 - Danger"
+ "5 - Warning"
+ "6 - Info"
+ "7 - Light"
+ "8 - Dark"
+ "9 - Link"
+ #tag EndEnumValues
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LayoutDirection"
+ Visible=true
+ Group="WebView"
+ InitialValue="LayoutDirections.LeftToRight"
+ Type="LayoutDirections"
+ EditorType="Enum"
+ #tag EnumValues
+ "0 - LeftToRight"
+ "1 - RightToLeft"
+ "2 - TopToBottom"
+ "3 - BottomToTop"
+ #tag EndEnumValues
+ #tag EndViewProperty
+#tag EndViewBehavior
diff --git a/webapp/dialogs/dlgTableEditorField.xojo_code b/webapp/dialogs/dlgTableEditorField.xojo_code
new file mode 100644
index 0000000..8b48bc2
--- /dev/null
+++ b/webapp/dialogs/dlgTableEditorField.xojo_code
@@ -0,0 +1,840 @@
+#tag WebPage
+Begin dlgBase dlgTableEditorField
+ Compatibility = ""
+ ControlCount = 0
+ ControlID = ""
+ Enabled = True
+ Height = 362
+ Index = -2147483648
+ Indicator = 0
+ LayoutDirection = 0
+ LayoutType = 0
+ Left = 0
+ LockBottom = False
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = False
+ LockTop = False
+ LockVertical = False
+ TabIndex = 0
+ Top = 0
+ Visible = True
+ Width = 600
+ _mDesignHeight = 0
+ _mDesignWidth = 0
+ _mPanelIndex = -1
+ Begin WebLabel labTitle
+ Bold = True
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 24.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Italic = False
+ Left = 20
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = True
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ Scope = 2
+ TabIndex = 0
+ TabStop = True
+ Text = "Field"
+ TextAlignment = 2
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 20
+ Underline = False
+ Visible = True
+ Width = 560
+ _mPanelIndex = -1
+ End
+ Begin WebRectangle rctFormContent
+ BackgroundColor = &cFFFFFF
+ ControlCount = 0
+ ControlID = ""
+ Enabled = True
+ HasBackgroundColor= False
+ Height = 219
+ Index = -2147483648
+ Indicator = 0
+ LayoutDirection = 0
+ LayoutType = 0
+ Left = 20
+ LockBottom = True
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = True
+ LockTop = True
+ LockVertical = False
+ Scope = 2
+ TabIndex = 1
+ TabStop = True
+ Tooltip = ""
+ Top = 66
+ Visible = True
+ Width = 560
+ _mDesignHeight = 0
+ _mDesignWidth = 0
+ _mPanelIndex = -1
+ Begin WebLabel labName
+ Bold = False
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 0.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ InitialParent = "rctFormContent"
+ Italic = False
+ Left = 40
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ Scope = 2
+ TabIndex = 0
+ TabPanelIndex = 0
+ TabStop = True
+ Text = "Name:"
+ TextAlignment = 0
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 86
+ Underline = False
+ Visible = True
+ Width = 140
+ _mPanelIndex = -1
+ End
+ Begin WebTextField edtName
+ AllowAutoComplete= False
+ AllowSpellChecking= False
+ Caption = ""
+ ControlID = ""
+ Enabled = True
+ FieldType = 0
+ Height = 38
+ Hint = ""
+ Index = -2147483648
+ Indicator = 0
+ InitialParent = "rctFormContent"
+ Left = 188
+ LockBottom = False
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = True
+ LockTop = True
+ LockVertical = False
+ MaximumCharactersAllowed= 0
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ ReadOnly = False
+ Scope = 2
+ TabIndex = 1
+ TabPanelIndex = 0
+ TabStop = True
+ Text = ""
+ TextAlignment = 0
+ Tooltip = ""
+ Top = 86
+ Visible = True
+ Width = 372
+ _mPanelIndex = -1
+ End
+ Begin WebPopupMenu lstType
+ ControlID = ""
+ Enabled = True
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ InitialValue = ""
+ LastAddedRowIndex= 0
+ LastRowIndex = 0
+ Left = 188
+ LockBottom = False
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ RowCount = 0
+ Scope = 2
+ SelectedRowIndex= -1
+ SelectedRowText = ""
+ TabIndex = 2
+ TabPanelIndex = 0
+ TabStop = True
+ Tooltip = ""
+ Top = 132
+ Visible = True
+ Width = 372
+ _mPanelIndex = -1
+ End
+ Begin WebLabel labType
+ Bold = False
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 0.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Italic = False
+ Left = 40
+ LockBottom = False
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ Scope = 2
+ TabIndex = 4
+ TabPanelIndex = 0
+ TabStop = True
+ Text = "Type:"
+ TextAlignment = 0
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 132
+ Underline = False
+ Visible = True
+ Width = 140
+ _mPanelIndex = -1
+ End
+ Begin WebLabel labDefault
+ Bold = False
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 0.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Italic = False
+ Left = 40
+ LockBottom = False
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ Scope = 2
+ TabIndex = 5
+ TabPanelIndex = 0
+ TabStop = True
+ Text = "Default Value:"
+ TextAlignment = 0
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 178
+ Underline = False
+ Visible = True
+ Width = 140
+ _mPanelIndex = -1
+ End
+ Begin WebTextField edtDefault
+ AllowAutoComplete= False
+ AllowSpellChecking= False
+ Caption = ""
+ ControlID = ""
+ Enabled = True
+ FieldType = 0
+ Height = 38
+ Hint = ""
+ Index = -2147483648
+ Indicator = 0
+ Left = 188
+ LockBottom = False
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = True
+ LockTop = True
+ LockVertical = False
+ MaximumCharactersAllowed= 0
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ ReadOnly = False
+ Scope = 2
+ TabIndex = 6
+ TabPanelIndex = 0
+ TabStop = True
+ Text = ""
+ TextAlignment = 0
+ Tooltip = ""
+ Top = 178
+ Visible = True
+ Width = 372
+ _mPanelIndex = -1
+ End
+ Begin WebPopupMenu lstConstraint
+ ControlID = ""
+ Enabled = True
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ InitialValue = ""
+ LastAddedRowIndex= 0
+ LastRowIndex = 0
+ Left = 188
+ LockBottom = False
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ RowCount = 0
+ Scope = 2
+ SelectedRowIndex= -1
+ SelectedRowText = ""
+ TabIndex = 7
+ TabPanelIndex = 0
+ TabStop = True
+ Tooltip = ""
+ Top = 224
+ Visible = True
+ Width = 372
+ _mPanelIndex = -1
+ End
+ Begin WebLabel labConstraint
+ Bold = False
+ ControlID = ""
+ Enabled = True
+ FontName = ""
+ FontSize = 0.0
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Italic = False
+ Left = 40
+ LockBottom = False
+ LockedInPosition= False
+ LockHorizontal = False
+ LockLeft = True
+ LockRight = False
+ LockTop = True
+ LockVertical = False
+ Multiline = False
+ PanelIndex = "0"
+ Parent = "rctFormContent"
+ Scope = 2
+ TabIndex = 8
+ TabPanelIndex = 0
+ TabStop = True
+ Text = "Constraint:"
+ TextAlignment = 0
+ TextColor = &c000000FF
+ Tooltip = ""
+ Top = 224
+ Underline = False
+ Visible = True
+ Width = 140
+ _mPanelIndex = -1
+ End
+ End
+ Begin WebButton btnSave
+ AllowAutoDisable= False
+ Cancel = False
+ Caption = "Create"
+ ControlID = ""
+ Default = True
+ Enabled = False
+ Height = 38
+ Index = -2147483648
+ Indicator = 1
+ Left = 480
+ LockBottom = True
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = True
+ LockTop = False
+ LockVertical = False
+ Scope = 2
+ TabIndex = 3
+ TabStop = True
+ Tooltip = ""
+ Top = 304
+ Visible = True
+ Width = 100
+ _mPanelIndex = -1
+ End
+ Begin WebButton btnCancel
+ AllowAutoDisable= False
+ Cancel = True
+ Caption = "Cancel"
+ ControlID = ""
+ Default = False
+ Enabled = True
+ Height = 38
+ Index = -2147483648
+ Indicator = 0
+ Left = 372
+ LockBottom = True
+ LockedInPosition= True
+ LockHorizontal = False
+ LockLeft = False
+ LockRight = True
+ LockTop = False
+ LockVertical = False
+ Scope = 2
+ TabIndex = 2
+ TabStop = True
+ Tooltip = ""
+ Top = 304
+ Visible = True
+ Width = 100
+ _mPanelIndex = -1
+ End
+End
+#tag EndWebPage
+
+#tag WindowCode
+ #tag Event
+ Sub Shown()
+ edtName.SetFocus()
+
+ End Sub
+ #tag EndEvent
+
+
+ #tag Method, Flags = &h21
+ Private Sub RefreshButtons()
+ btnSave.Enabled = (edtName.Text.Trim <> "")
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h0
+ Sub ShowAsAdd()
+ labTitle.Text = "Add Field"
+ btnSave.Caption = "Add"
+ Super.Show()
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h0
+ Sub ShowAsEdit(Name As String, Type As String, Default As String, Constraint As String)
+ labTitle.Text = "Edit Field"
+ btnSave.Caption = "Edit"
+ btnSave.Indicator = Indicators.Primary
+
+ Me.ShowAsEdit_FillValues(Name, Type, Default, Constraint)
+
+ Me.RefreshButtons()
+
+ Super.Show()
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h21
+ Private Sub ShowAsEdit_FillValues(Name As String, Type As String, Default As String, Constraint As String)
+ #Pragma BreakOnExceptions False
+ edtName.Text = Name
+
+ lstType.SelectedRowIndex = -1
+ Try
+ lstType.SelectRowWithTag(Type)
+ Catch InvalidArgumentException
+ lstType.AddRow("-")
+ lstType.AddRow(Type, Type)
+ lstType.SelectRowWithTag(Type)
+ End Try
+
+ edtDefault.Text = Default
+
+ lstConstraint.SelectedRowIndex = -1
+ Try
+ lstConstraint.SelectRowWithTag(Constraint)
+ Catch InvalidArgumentException
+ lstConstraint.AddRow("-")
+ lstConstraint.AddRow(Constraint, Constraint)
+ lstConstraint.SelectRowWithTag(Constraint)
+ End Try
+
+ End Sub
+ #tag EndMethod
+
+ #tag Method, Flags = &h0
+ Sub ShowAsRename(Name As String, Type As String, Default As String, Constraint As String)
+ labTitle.Text = "Rename Field"
+ btnSave.Caption = "Rename"
+ btnSave.Indicator = Indicators.Warning
+
+ Me.ShowAsEdit_FillValues(Name, Type, Default, Constraint)
+
+ labType.Enabled = False
+ lstType.Enabled = False
+ labDefault.Enabled = False
+ edtDefault.Enabled = False
+ labConstraint.Enabled = False
+ lstConstraint.Enabled = False
+
+ Me.RefreshButtons()
+
+ Super.Show()
+ End Sub
+ #tag EndMethod
+
+
+ #tag Hook, Flags = &h0
+ Event FieldSaveAction(Name As String, Type As String, Default As String, Constraint As String) As Boolean
+ #tag EndHook
+
+
+#tag EndWindowCode
+
+#tag Events edtName
+ #tag Event
+ Sub TextChanged()
+ Self.RefreshButtons()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events lstType
+ #tag Event
+ Sub Opening()
+ Me.RemoveAllRows()
+
+ Me.AddRow("(no type)", "")
+ Me.AddRow("-")
+
+ Me.AddRow("TEXT", "TEXT")
+ Me.AddRow("INTEGER", "INTEGER")
+ Me.AddRow("REAL", "REAL")
+ Me.AddRow("BLOB", "BLOB")
+ Me.AddRow("CURRENCY", "CURRENCY")
+ Me.AddRow("BOOLEAN", "BOOLEAN")
+ Me.AddRow("DATE", "DATE")
+ Me.AddRow("TIME", "TIME")
+ Me.AddRow("TIMESTAMP", "TIMESTAMP")
+ Me.AddRow("DOUBLE", "DOUBLE")
+ Me.AddRow("FLOAT", "FLOAT")
+ Me.AddRow("SMALLINT", "SMALLINT")
+ Me.AddRow("VARCHAR", "VARCHAR")
+ Me.AddRow("BINARY", "BINARY")
+
+ Me.SelectedRowIndex = 0
+
+ End Sub
+ #tag EndEvent
+ #tag Event
+ Sub SelectionChanged(item As WebMenuItem)
+ #Pragma unused item
+
+ Self.RefreshButtons()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events edtDefault
+ #tag Event
+ Sub TextChanged()
+ Self.RefreshButtons()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events lstConstraint
+ #tag Event
+ Sub Opening()
+ Me.RemoveAllRows()
+
+ Me.AddRow("(no constraint)", "")
+ Me.AddRow("-")
+
+ Me.AddRow("NOT NULL", "NOT NULL")
+ Me.AddRow("PRIMARY KEY", "PRIMARY KEY")
+ Me.AddRow("PRIMARY KEY AUTOINCREMENT", "PRIMARY KEY AUTOINCREMENT")
+ Me.AddRow("UNIQUE (single)", "UNIQUE (single)")
+ Me.AddRow("UNIQUE (multi)", "UNIQUE (multi)")
+
+ Me.SelectedRowIndex = 0
+
+ End Sub
+ #tag EndEvent
+ #tag Event
+ Sub SelectionChanged(item As WebMenuItem)
+ #Pragma unused item
+
+ Self.RefreshButtons()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events btnSave
+ #tag Event
+ Sub Pressed()
+ If FieldSaveAction(edtName.Text.Trim, _
+ lstType.RowTagAt(lstType.SelectedRowIndex).StringValue, _
+ edtDefault.Text.Trim, _
+ lstConstraint.RowTagAt(lstConstraint.SelectedRowIndex)) Then
+ Self.Close()
+ End If
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag Events btnCancel
+ #tag Event
+ Sub Pressed()
+ Self.Close()
+
+ End Sub
+ #tag EndEvent
+#tag EndEvents
+#tag ViewBehavior
+ #tag ViewProperty
+ Name="ControlCount"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mPanelIndex"
+ Visible=false
+ Group="Behavior"
+ InitialValue="-1"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Index"
+ Visible=false
+ Group="ID"
+ InitialValue="-2147483648"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Name"
+ Visible=true
+ Group="ID"
+ InitialValue=""
+ Type="String"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Super"
+ Visible=true
+ Group="ID"
+ InitialValue=""
+ Type="String"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Left"
+ Visible=true
+ Group="Position"
+ InitialValue="0"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Top"
+ Visible=true
+ Group="Position"
+ InitialValue="0"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="ControlID"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="String"
+ EditorType="MultiLineEditor"
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Enabled"
+ Visible=true
+ Group="Behavior"
+ InitialValue="True"
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Height"
+ Visible=true
+ Group="Behavior"
+ InitialValue="400"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LayoutType"
+ Visible=true
+ Group="Behavior"
+ InitialValue="LayoutTypes.Fixed"
+ Type="LayoutTypes"
+ EditorType="Enum"
+ #tag EnumValues
+ "0 - Fixed"
+ "1 - Flex"
+ #tag EndEnumValues
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockBottom"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockHorizontal"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockLeft"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockRight"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockTop"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LockVertical"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Visible"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Boolean"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Width"
+ Visible=true
+ Group="Behavior"
+ InitialValue="600"
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mDesignHeight"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mDesignWidth"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="_mName"
+ Visible=false
+ Group="Behavior"
+ InitialValue=""
+ Type="String"
+ EditorType="MultiLineEditor"
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="TabIndex"
+ Visible=true
+ Group="Visual Controls"
+ InitialValue=""
+ Type="Integer"
+ EditorType=""
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="Indicator"
+ Visible=false
+ Group="Visual Controls"
+ InitialValue=""
+ Type="WebUIControl.Indicators"
+ EditorType="Enum"
+ #tag EnumValues
+ "0 - Default"
+ "1 - Primary"
+ "2 - Secondary"
+ "3 - Success"
+ "4 - Danger"
+ "5 - Warning"
+ "6 - Info"
+ "7 - Light"
+ "8 - Dark"
+ "9 - Link"
+ #tag EndEnumValues
+ #tag EndViewProperty
+ #tag ViewProperty
+ Name="LayoutDirection"
+ Visible=true
+ Group="WebView"
+ InitialValue="LayoutDirections.LeftToRight"
+ Type="LayoutDirections"
+ EditorType="Enum"
+ #tag EnumValues
+ "0 - LeftToRight"
+ "1 - RightToLeft"
+ "2 - TopToBottom"
+ "3 - BottomToTop"
+ #tag EndEnumValues
+ #tag EndViewProperty
+#tag EndViewBehavior
diff --git a/webapp/main/CubeSQLAdminPage.xojo_code b/webapp/main/CubeSQLAdminPage.xojo_code
index 5d0ea6c..7bd8df0 100644
--- a/webapp/main/CubeSQLAdminPage.xojo_code
+++ b/webapp/main/CubeSQLAdminPage.xojo_code
@@ -197,6 +197,9 @@ End
Case ContainerKey.Databases
showContainer = New cntDatabases
+ Case ContainerKey.TablesAndIndexes
+ showContainer = New cntTablesIndexes
+
Case ContainerKey.Backups
showContainer = New cntBackups
@@ -277,6 +280,7 @@ End
btn.Style = WebToolbarButton.ButtonStyles.Menu
btn.Caption = "Data"
btn.Menu.AddMenuItem(New WebMenuItem("Databases", ContainerKey.Databases))
+ btn.Menu.AddMenuItem(New WebMenuItem("Tables & Indexes", ContainerKey.TablesAndIndexes))
btn.Menu.AddMenuItem(New WebMenuItem("Backups", ContainerKey.Backups))
btn.Menu.AddMenuItem(New WebMenuItem("Schedules", ContainerKey.Schedules))
Me.AddItem(btn)
diff --git a/webapp/modCubeSQLAdmin.xojo_code b/webapp/modCubeSQLAdmin.xojo_code
index 9a89c15..7750fec 100644
--- a/webapp/modCubeSQLAdmin.xojo_code
+++ b/webapp/modCubeSQLAdmin.xojo_code
@@ -1,8 +1,30 @@
#tag Module
Protected Module modCubeSQLAdmin
#tag Method, Flags = &h0
- Function EscapeSqlQuotes(Extends sql As String) As String
- Return sql.ReplaceAll("'", "''")
+ Function EscapeSqlDefaultValueIfRequired(Extends defaultValue As String) As String
+ If (defaultValue.Contains(" ") Or defaultValue.Contains("'")) Then
+ Return "'" + defaultValue.EscapeSqlQuotes + "'"
+ End If
+
+ Return defaultValue
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h0
+ Function EscapeSqlFieldIfRequired(Extends fieldname As String) As String
+ If (fieldname.Contains(" ") Or fieldname.Contains("""")) Then
+ Return """" + fieldname.ReplaceAll("""", """""") + """"
+ End If
+
+ Return fieldname
+
+ End Function
+ #tag EndMethod
+
+ #tag Method, Flags = &h0
+ Function EscapeSqlQuotes(Extends value As String) As String
+ Return value.ReplaceAll("'", "''")
End Function
#tag EndMethod
@@ -77,15 +99,16 @@ Protected Module modCubeSQLAdmin
Registration=1
Console = 2
Databases = 11
- Backups = 12
+ TablesAndIndexes=12
+ Schedules=14
+ Backups = 13
Groups = 21
Users = 22
Privileges = 23
EnginePreferences = 24
Commands = 31
Clients = 32
- Log = 33
- Schedules=13
+ Log = 33
#tag EndEnum