ViewVC Help
View File | Revision Log | Show Annotations | Download File | View Changeset | Root Listing
root/public/ibx/trunk/design/ibupdatesqleditor.pas
(Generate patch)

Comparing ibx/trunk/design/ibupdatesqleditor.pas (file contents):
Revision 5 by tony, Fri Feb 18 16:26:16 2011 UTC vs.
Revision 19 by tony, Mon Jul 7 13:00:15 2014 UTC

# Line 1 | Line 1
1 < unit IBUpdateSQLEditor;
2 <
3 < {$mode objfpc}{$H+}
4 <
5 < interface
6 <
7 < uses
8 <  Classes, SysUtils, FileUtil, LResources, Forms, Controls, Graphics, Dialogs,
9 <  ComCtrls, StdCtrls, ExtCtrls, IBSystemTables, IBUpdateSQL;
10 <
11 < type
12 <
13 <  { TIBUpdateSQLEditorForm }
14 <
15 <  TIBUpdateSQLEditorForm = class(TForm)
16 <    Button1: TButton;
17 <    CancelButton: TButton;
18 <    FieldsPage: TTabSheet;
19 <    GenerateButton: TButton;
20 <    GroupBox1: TGroupBox;
21 <    PrimaryKeyList: TListBox;
22 <    Label1: TLabel;
23 <    Label2: TLabel;
24 <    Label3: TLabel;
25 <    Label4: TLabel;
26 <    OkButton: TButton;
27 <    PageControl: TPageControl;
28 <    QuoteFields: TCheckBox;
29 <    SQLMemo: TMemo;
30 <    SQLPage: TTabSheet;
31 <    StatementType: TRadioGroup;
32 <    FieldList: TListBox;
33 <    TableNamesCombo: TComboBox;
34 <    procedure Button1Click(Sender: TObject);
35 <    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
36 <    procedure FormShow(Sender: TObject);
37 <    procedure GenerateButtonClick(Sender: TObject);
38 <    procedure SQLMemoChange(Sender: TObject);
39 <    procedure SQLPageShow(Sender: TObject);
40 <    procedure StatementTypeClick(Sender: TObject);
41 <    procedure TableNamesComboCloseUp(Sender: TObject);
42 <  private
43 <    { private declarations }
44 <    FUpdateObject: TIBUpdateSQL;
45 <    FIBSystemTables: TIBSystemTables;
46 <    FDirty: boolean;
47 <    FCurrentStatement: integer;
48 <    FModifySQL: TStringList;
49 <    FInsertSQL: TStringList;
50 <    FDeleteSQL: TStringList;
51 <    FRefreshSQL: TStringList;
52 <    procedure UpdateSQLMemo;
53 <  public
54 <    { public declarations }
55 <    constructor Create(TheOwner: TComponent); override;
56 <    destructor Destroy; override;
57 <    procedure SetUpdateObject(AObject: TIBUpdateSQL);
58 <  end;
59 <
60 < var
61 <  IBUpdateSQLEditorForm: TIBUpdateSQLEditorForm;
62 <
63 < function EditIBUpdateSQL(UpdateObject: TIBUpdateSQL): boolean;
64 <
65 < implementation
66 <
67 < uses IBQuery;
68 <
69 < function EditIBUpdateSQL(UpdateObject: TIBUpdateSQL): boolean;
70 < begin
71 <  Result := false;
72 <  if assigned(UpdateObject.DataSet) and assigned(UpdateObject.DataSet.Database) then
73 <  begin
74 <    if not assigned(UpdateObject.DataSet.Transaction) then
75 <    begin
76 <      ShowMessage('No Default Transaction!');
77 <      Exit
78 <    end;
79 <
80 <    UpdateObject.DataSet.Database.Connected := true;
81 <  end;
82 <
83 <  with TIBUpdateSQLEditorForm.Create(Application) do
84 <  try
85 <    SetUpdateObject(UpdateObject);
86 <    Result := ShowModal = mrOK
87 <  finally
88 <    Free
89 <  end;
90 <
91 < end;
92 <
93 < { TIBUpdateSQLEditorForm }
94 <
95 < procedure TIBUpdateSQLEditorForm.FormShow(Sender: TObject);
96 < var TableName: string;
97 < begin
98 <  PageControl.ActivePage := FieldsPage;
99 <  FModifySQL.Assign(FUpdateObject.ModifySQL);
100 <  FInsertSQL.Assign(FUpdateObject.InsertSQL);
101 <  FDeleteSQL.Assign(FUpdateObject.DeleteSQL);
102 <  FRefreshSQL.Assign(FUpdateObject.RefreshSQL);
103 <  FCurrentStatement := -1;
104 <  TableNamesCombo.Items.Clear;
105 <  FIBSystemTables.GetTableNames(TableNamesCombo.Items);
106 <  if TableNamesCombo.Items.Count > 0 then
107 <  begin
108 <    TableNamesCombo.ItemIndex := 0;
109 <    if assigned(FUpdateObject.DataSet) and (FUpdateObject.DataSet is TIBQuery) and
110 <       ((FUpdateObject.DataSet as TIBQuery).SQL.Text <> '') then
111 <    try
112 <       FIBSystemTables.GetTableAndColumns((FUpdateObject.DataSet as TIBQuery).SQL.Text,TableName,nil);
113 <       TableNamesCombo.ItemIndex := TableNamesCombo.Items.IndexOf(TableName);
114 <    except  //ignore
115 <    end;
116 <    FIBSystemTables.GetFieldNames(TableNamesCombo.Text,FieldList.Items,false);
117 <    FIBSystemTables.GetPrimaryKeys(TableNamesCombo.Text,PrimaryKeyList.Items);
118 <  end;
119 < end;
120 <
121 < procedure TIBUpdateSQLEditorForm.FormClose(Sender: TObject;
122 <  var CloseAction: TCloseAction);
123 < begin
124 <  if ModalResult = mrOK then
125 <  begin
126 <    UpdateSQLMemo;
127 <    FUpdateObject.ModifySQL.Assign(FModifySQL);
128 <    FUpdateObject.InsertSQL.Assign(FInsertSQL);
129 <    FUpdateObject.DeleteSQL.Assign(FDeleteSQL);
130 <    FUpdateObject.RefreshSQL.Assign(FRefreshSQL);
131 <  end;
132 < end;
133 <
134 < procedure TIBUpdateSQLEditorForm.Button1Click(Sender: TObject);
135 < begin
136 <  if SQLMemo.Lines.Text <> '' then
137 <    FIBSystemTables.TestSQL(SQLMemo.Lines.Text);
138 < end;
139 <
140 < procedure TIBUpdateSQLEditorForm.GenerateButtonClick(Sender: TObject);
141 < var FieldNames: TStringList;
142 <    I: integer;
143 < begin
144 <  FUpdateObject.RefreshSQL.Clear;
145 <  FIBSystemTables.GenerateRefreshSQL(TableNamesCombo.Text,QuoteFields.Checked,FRefreshSQL);
146 <  FIBSystemTables.GenerateDeleteSQL(TableNamesCombo.Text,QuoteFields.Checked,FDeleteSQL);
147 <  if FieldList.SelCount = 0 then
148 <  begin
149 <    FIBSystemTables.GenerateModifySQL(TableNamesCombo.Text,QuoteFields.Checked,
150 <      FieldList.Items,FModifySQL);
151 <    FIBSystemTables.GenerateInsertSQL(TableNamesCombo.Text,QuoteFields.Checked,
152 <      FieldList.Items,FInsertSQL);
153 <
154 <  end
155 <  else
156 <  begin
157 <    FieldNames := TStringList.Create;
158 <    try
159 <      for I := 0 to FieldList.Items.Count - 1 do
160 <        if FieldList.Selected[I] then
161 <          FieldNames.Add(FieldList.Items[I]);
162 <      FIBSystemTables.GenerateModifySQL(TableNamesCombo.Text,QuoteFields.Checked,
163 <        FieldNames,FModifySQL);
164 <    FIBSystemTables.GenerateInsertSQL(TableNamesCombo.Text,QuoteFields.Checked,
165 <      FieldNames,FInsertSQL);
166 <    finally
167 <      FieldNames.Free
168 <    end;
169 <  end;
170 <  FDirty := false;
171 <  PageControl.ActivePage := SQLPage;
172 < end;
173 <
174 < procedure TIBUpdateSQLEditorForm.SQLMemoChange(Sender: TObject);
175 < begin
176 <  FDirty := true
177 < end;
178 <
179 < procedure TIBUpdateSQLEditorForm.SQLPageShow(Sender: TObject);
180 < begin
181 <  UpdateSQLMemo
182 < end;
183 <
184 < procedure TIBUpdateSQLEditorForm.StatementTypeClick(Sender: TObject);
185 < begin
186 <  UpdateSQLMemo
187 < end;
188 <
189 < procedure TIBUpdateSQLEditorForm.TableNamesComboCloseUp(Sender: TObject);
190 < begin
191 <  FIBSystemTables.GetFieldNames(TableNamesCombo.Text,FieldList.Items,false);
192 <  FIBSystemTables.GetPrimaryKeys(TableNamesCombo.Text,PrimaryKeyList.Items);
193 < end;
194 <
195 < procedure TIBUpdateSQLEditorForm.UpdateSQLMemo;
196 < begin
197 <  if FDirty then
198 <    case FCurrentStatement of
199 <    0: //Modify
200 <        FModifySQL.Assign(SQLMemo.Lines);
201 <    1: //Insert
202 <        FInsertSQL.Assign(SQLMemo.Lines);
203 <    2: // Delete
204 <        FDeleteSQL.Assign(SQLMemo.Lines);
205 <    3: //Refresh
206 <        FRefreshSQL.Assign(SQLMemo.Lines);
207 <    end;
208 <  FDirty := false;
209 <  case StatementType.ItemIndex of
210 <  0: // Modify
211 <    SQLMemo.Lines.Assign(FModifySQL)  ;
212 <  1: //Insert
213 <    SQLMemo.Lines.Assign(FInsertSQL)  ;
214 <  2: // Delete
215 <    SQLMemo.Lines.Assign(FDeleteSQL)  ;
216 <  3: //Refresh
217 <    SQLMemo.Lines.Assign(FRefreshSQL)  ;
218 <  end;
219 <  FCurrentStatement := StatementType.ItemIndex;
220 < end;
221 <
222 < constructor TIBUpdateSQLEditorForm.Create(TheOwner: TComponent);
223 < begin
224 <  inherited Create(TheOwner);
225 <  FIBSystemTables := TIBSystemTables.Create;
226 <  FModifySQL := TStringList.Create;
227 <  FInsertSQL := TStringList.Create;
228 <  FDeleteSQL := TStringList.Create;
229 <  FRefreshSQL := TStringList.Create;
230 < end;
231 <
232 < destructor TIBUpdateSQLEditorForm.Destroy;
233 < begin
234 <  if assigned(FIBSystemTables) then FIBSystemTables.Free;
235 <  if assigned(FModifySQL) then FModifySQL.Free;
236 <  if assigned(FInsertSQL) then FInsertSQL.Free;
237 <  if assigned(FDeleteSQL) then FDeleteSQL.Free;
238 <  if assigned(FRefreshSQL) then FRefreshSQL.Free;
239 <  inherited Destroy;
240 < end;
241 <
242 < procedure TIBUpdateSQLEditorForm.SetUpdateObject(AObject: TIBUpdateSQL);
243 < begin
244 <  FUpdateObject := AObject;
245 <  if assigned(FUpdateObject.DataSet) then
246 <    FIBSystemTables.SelectDatabase(FUpdateObject.DataSet.Database,FUpdateObject.DataSet.Transaction);
247 < end;
248 <
249 <
250 < initialization
251 <  {$I ibupdatesqleditor.lrs}
252 <
253 < end.
254 <
1 > (*
2 > *  IBX For Lazarus (Firebird Express)
3 > *
4 > *  The contents of this file are subject to the Initial Developer's
5 > *  Public License Version 1.0 (the "License"); you may not use this
6 > *  file except in compliance with the License. You may obtain a copy
7 > *  of the License here:
8 > *
9 > *    http://www.firebirdsql.org/index.php?op=doc&id=idpl
10 > *
11 > *  Software distributed under the License is distributed on an "AS
12 > *  IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
13 > *  implied. See the License for the specific language governing rights
14 > *  and limitations under the License.
15 > *
16 > *  The Initial Developer of the Original Code is Tony Whyman.
17 > *
18 > *  The Original Code is (C) 2011 Tony Whyman, MWA Software
19 > *  (http://www.mwasoftware.co.uk).
20 > *
21 > *  All Rights Reserved.
22 > *
23 > *  Contributor(s): ______________________________________.
24 > *
25 > *)
26 > unit IBUpdateSQLEditor;
27 >
28 > {$mode objfpc}{$H+}
29 >
30 > interface
31 >
32 > uses
33 >  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
34 >  ComCtrls, StdCtrls, ExtCtrls, IBSystemTables, IBUpdateSQL, IBDatabase;
35 >
36 > type
37 >
38 >  { TIBUpdateSQLEditorForm }
39 >
40 >  TIBUpdateSQLEditorForm = class(TForm)
41 >    GenerateParams: TCheckBox;
42 >    TestBtn: TButton;
43 >    CancelButton: TButton;
44 >    FieldsPage: TTabSheet;
45 >    GenerateBtn: TButton;
46 >    GroupBox1: TGroupBox;
47 >    IBTransaction1: TIBTransaction;
48 >    IncludePrimaryKeys: TCheckBox;
49 >    PrimaryKeyList: TListBox;
50 >    Label1: TLabel;
51 >    Label2: TLabel;
52 >    Label3: TLabel;
53 >    Label4: TLabel;
54 >    OkButton: TButton;
55 >    PageControl: TPageControl;
56 >    QuoteFields: TCheckBox;
57 >    SQLMemo: TMemo;
58 >    SQLPage: TTabSheet;
59 >    StatementType: TRadioGroup;
60 >    FieldList: TListBox;
61 >    TableNamesCombo: TComboBox;
62 >    procedure TestBtnClick(Sender: TObject);
63 >    procedure FormClose(Sender: TObject; var CloseAction: TCloseAction);
64 >    procedure FormShow(Sender: TObject);
65 >    procedure GenerateBtnClick(Sender: TObject);
66 >    procedure SQLMemoChange(Sender: TObject);
67 >    procedure SQLPageShow(Sender: TObject);
68 >    procedure StatementTypeClick(Sender: TObject);
69 >    procedure TableNamesComboCloseUp(Sender: TObject);
70 >  private
71 >    { private declarations }
72 >    FUpdateObject: TIBUpdateSQL;
73 >    FIBSystemTables: TIBSystemTables;
74 >    FDirty: boolean;
75 >    FCurrentStatement: integer;
76 >    FModifySQL: TStringList;
77 >    FInsertSQL: TStringList;
78 >    FDeleteSQL: TStringList;
79 >    FRefreshSQL: TStringList;
80 >    procedure UpdateSQLMemo;
81 >  public
82 >    { public declarations }
83 >    constructor Create(TheOwner: TComponent); override;
84 >    destructor Destroy; override;
85 >    procedure SetUpdateObject(AObject: TIBUpdateSQL);
86 >  end;
87 >
88 > var
89 >  IBUpdateSQLEditorForm: TIBUpdateSQLEditorForm;
90 >
91 > function EditIBUpdateSQL(UpdateObject: TIBUpdateSQL): boolean;
92 >
93 > implementation
94 >
95 > uses IBQuery;
96 >
97 > {$R *.lfm}
98 >
99 > function EditIBUpdateSQL(UpdateObject: TIBUpdateSQL): boolean;
100 > begin
101 >  Result := false;
102 >  if assigned(UpdateObject.DataSet) and assigned(UpdateObject.DataSet.Database) then
103 >    try
104 >      UpdateObject.DataSet.Database.Connected := true;
105 >    except on E: Exception do
106 >      ShowMessage(E.Message)
107 >    end;
108 >
109 >  with TIBUpdateSQLEditorForm.Create(Application) do
110 >  try
111 >    SetUpdateObject(UpdateObject);
112 >    if assigned(UpdateObject.DataSet) then
113 >      GenerateParams.Checked := UpdateObject.DataSet.GenerateParamNames;
114 >    Result := ShowModal = mrOK;
115 >    if Result and assigned(UpdateObject.DataSet) then
116 >      UpdateObject.DataSet.GenerateParamNames := GenerateParams.Checked
117 >  finally
118 >    Free
119 >  end;
120 >
121 > end;
122 >
123 > { TIBUpdateSQLEditorForm }
124 >
125 > procedure TIBUpdateSQLEditorForm.FormShow(Sender: TObject);
126 > var TableName: string;
127 > begin
128 >  GenerateBtn.Enabled := (IBTransaction1.DefaultDatabase <> nil) and IBTransaction1.DefaultDatabase.Connected;
129 >  TestBtn.Enabled := (IBTransaction1.DefaultDatabase <> nil) and IBTransaction1.DefaultDatabase.Connected;
130 >  PageControl.ActivePage := FieldsPage;
131 >  FModifySQL.Assign(FUpdateObject.ModifySQL);
132 >  FInsertSQL.Assign(FUpdateObject.InsertSQL);
133 >  FDeleteSQL.Assign(FUpdateObject.DeleteSQL);
134 >  FRefreshSQL.Assign(FUpdateObject.RefreshSQL);
135 >  FCurrentStatement := -1;
136 >  TableNamesCombo.Items.Clear;
137 >  FIBSystemTables.GetTableNames(TableNamesCombo.Items);
138 >  if TableNamesCombo.Items.Count > 0 then
139 >  begin
140 >    TableNamesCombo.ItemIndex := 0;
141 >    if assigned(FUpdateObject.DataSet) and (FUpdateObject.DataSet is TIBQuery) and
142 >       ((FUpdateObject.DataSet as TIBQuery).SQL.Text <> '') then
143 >    try
144 >       FIBSystemTables.GetTableAndColumns((FUpdateObject.DataSet as TIBQuery).SQL.Text,TableName,nil);
145 >       TableNamesCombo.ItemIndex := TableNamesCombo.Items.IndexOf(TableName);
146 >    except  //ignore
147 >    end;
148 >    FIBSystemTables.GetFieldNames(TableNamesCombo.Text,FieldList.Items,IncludePrimaryKeys.checked,false);
149 >    FIBSystemTables.GetPrimaryKeys(TableNamesCombo.Text,PrimaryKeyList.Items);
150 >  end;
151 > end;
152 >
153 > procedure TIBUpdateSQLEditorForm.FormClose(Sender: TObject;
154 >  var CloseAction: TCloseAction);
155 > begin
156 >  if ModalResult = mrOK then
157 >  begin
158 >    UpdateSQLMemo;
159 >    FUpdateObject.ModifySQL.Assign(FModifySQL);
160 >    FUpdateObject.InsertSQL.Assign(FInsertSQL);
161 >    FUpdateObject.DeleteSQL.Assign(FDeleteSQL);
162 >    FUpdateObject.RefreshSQL.Assign(FRefreshSQL);
163 >  end;
164 > end;
165 >
166 > procedure TIBUpdateSQLEditorForm.TestBtnClick(Sender: TObject);
167 > begin
168 >  if SQLMemo.Lines.Text <> '' then
169 >    FIBSystemTables.TestSQL(SQLMemo.Lines.Text,GenerateParams.Checked);
170 > end;
171 >
172 > procedure TIBUpdateSQLEditorForm.GenerateBtnClick(Sender: TObject);
173 > var FieldNames: TStringList;
174 >    I: integer;
175 > begin
176 >  FieldNames := TStringList.Create;
177 >  try
178 >    FUpdateObject.RefreshSQL.Clear;
179 >    FIBSystemTables.GetFieldNames(TableNamesCombo.Text,FieldNames);
180 >    FIBSystemTables.GenerateRefreshSQL(TableNamesCombo.Text,QuoteFields.Checked,FieldNames,FRefreshSQL);
181 >    FIBSystemTables.GenerateDeleteSQL(TableNamesCombo.Text,QuoteFields.Checked,FDeleteSQL);
182 >    FieldNames.Clear;
183 >    FIBSystemTables.GetFieldNames(TableNamesCombo.Text,FieldNames,true,false);
184 >    FIBSystemTables.GenerateInsertSQL(TableNamesCombo.Text,QuoteFields.Checked,
185 >        FieldNames,FInsertSQL);
186 >    if FieldList.SelCount = 0 then
187 >    begin
188 >      FIBSystemTables.GenerateModifySQL(TableNamesCombo.Text,QuoteFields.Checked,
189 >        FieldList.Items,FModifySQL);
190 >
191 >    end
192 >    else
193 >    begin
194 >      FieldNames.Clear;
195 >      for I := 0 to FieldList.Items.Count - 1 do
196 >          if FieldList.Selected[I] then
197 >               FieldNames.Add(FieldList.Items[I]);
198 >      FIBSystemTables.GenerateModifySQL(TableNamesCombo.Text,QuoteFields.Checked,
199 >           FieldNames,FModifySQL);
200 >    end;
201 >    FDirty := false;
202 >    PageControl.ActivePage := SQLPage;
203 >  finally
204 >    FieldNames.Free
205 >  end;
206 > end;
207 >
208 > procedure TIBUpdateSQLEditorForm.SQLMemoChange(Sender: TObject);
209 > begin
210 >  FDirty := true
211 > end;
212 >
213 > procedure TIBUpdateSQLEditorForm.SQLPageShow(Sender: TObject);
214 > begin
215 >  UpdateSQLMemo
216 > end;
217 >
218 > procedure TIBUpdateSQLEditorForm.StatementTypeClick(Sender: TObject);
219 > begin
220 >  UpdateSQLMemo
221 > end;
222 >
223 > procedure TIBUpdateSQLEditorForm.TableNamesComboCloseUp(Sender: TObject);
224 > begin
225 >  FIBSystemTables.GetFieldNames(TableNamesCombo.Text,FieldList.Items,IncludePrimaryKeys.checked,false);
226 >  FIBSystemTables.GetPrimaryKeys(TableNamesCombo.Text,PrimaryKeyList.Items);
227 > end;
228 >
229 > procedure TIBUpdateSQLEditorForm.UpdateSQLMemo;
230 > begin
231 >  if FDirty then
232 >    case FCurrentStatement of
233 >    0: //Modify
234 >        FModifySQL.Assign(SQLMemo.Lines);
235 >    1: //Insert
236 >        FInsertSQL.Assign(SQLMemo.Lines);
237 >    2: // Delete
238 >        FDeleteSQL.Assign(SQLMemo.Lines);
239 >    3: //Refresh
240 >        FRefreshSQL.Assign(SQLMemo.Lines);
241 >    end;
242 >  FDirty := false;
243 >  case StatementType.ItemIndex of
244 >  0: // Modify
245 >    SQLMemo.Lines.Assign(FModifySQL)  ;
246 >  1: //Insert
247 >    SQLMemo.Lines.Assign(FInsertSQL)  ;
248 >  2: // Delete
249 >    SQLMemo.Lines.Assign(FDeleteSQL)  ;
250 >  3: //Refresh
251 >    SQLMemo.Lines.Assign(FRefreshSQL)  ;
252 >  end;
253 >  FCurrentStatement := StatementType.ItemIndex;
254 > end;
255 >
256 > constructor TIBUpdateSQLEditorForm.Create(TheOwner: TComponent);
257 > begin
258 >  inherited Create(TheOwner);
259 >  FIBSystemTables := TIBSystemTables.Create;
260 >  FModifySQL := TStringList.Create;
261 >  FInsertSQL := TStringList.Create;
262 >  FDeleteSQL := TStringList.Create;
263 >  FRefreshSQL := TStringList.Create;
264 > end;
265 >
266 > destructor TIBUpdateSQLEditorForm.Destroy;
267 > begin
268 >  if assigned(FIBSystemTables) then FIBSystemTables.Free;
269 >  if assigned(FModifySQL) then FModifySQL.Free;
270 >  if assigned(FInsertSQL) then FInsertSQL.Free;
271 >  if assigned(FDeleteSQL) then FDeleteSQL.Free;
272 >  if assigned(FRefreshSQL) then FRefreshSQL.Free;
273 >  inherited Destroy;
274 > end;
275 >
276 > procedure TIBUpdateSQLEditorForm.SetUpdateObject(AObject: TIBUpdateSQL);
277 > begin
278 >  FUpdateObject := AObject;
279 >  if assigned(FUpdateObject.DataSet) then
280 >  begin
281 >    IBTransaction1.DefaultDatabase := FUpdateObject.DataSet.Database;
282 >    FIBSystemTables.SelectDatabase(FUpdateObject.DataSet.Database,IBTransaction1);
283 >  end;
284 > end;
285 >
286 >
287 > end.
288 >

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines