home *** CD-ROM | disk | FTP | other *** search
- unit TABCREAT;
-
- interface
-
- uses
- {$IFDEF WIN32}
- Bde, Windows,
- {$ELSE}
- DbiProcs, DbiTypes, DbiErrs, WinTypes, WinProcs,
- {$ENDIF}
- Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
- DBTables, DB, Grids, DBGrids, StdCtrls, DBCtrls, Mask, Buttons,
- ExtCtrls;
-
- type
- TCreateTableForm = class(TForm)
- TargetDatabase: TDatabase;
- StructureDataSource: TDataSource;
- StructureDBGrid: TDBGrid;
- StructureTable: TTable;
- CreateQuery: TQuery;
- FieldNameDBEdit: TDBEdit;
- TypeDBComboBox: TDBComboBox;
- KeyDBCheckBox: TDBCheckBox;
- SizeDBEdit: TDBEdit;
- DecDBEdit: TDBEdit;
- TableNameLabel: TLabel;
- FieldNameLabel: TLabel;
- TypeLabel: TLabel;
- SizeLabel: TLabel;
- TableNameEdit: TEdit;
- DecLabel: TLabel;
- SqlStatmentMemo: TMemo;
- OkBitBtn: TBitBtn;
- CancelBitBtn: TBitBtn;
- StructureDBNavigator: TDBNavigator;
- OrderLabel: TLabel;
- OrderDBEdit: TDBEdit;
- AddFieldButton: TButton;
- DeleteFieldButton: TButton;
- CancelFieldButton: TButton;
- SaveFieldButton: TButton;
- procedure FormCreate(Sender: TObject);
- procedure FormDestroy(Sender: TObject);
- procedure OkBitBtnClick(Sender: TObject);
- procedure StructureTableBeforePost(DataSet: TDataSet);
- procedure CancelBitBtnClick(Sender: TObject);
- procedure StructureTableAfterPost(DataSet: TDataSet);
- procedure TableNameEditExit(Sender: TObject);
- procedure TableNameEditKeyPress(Sender: TObject;
- var Key: Char);
- procedure FieldNameDBEditKeyPress(Sender: TObject;
- var Key: Char);
- procedure TypeDBComboBoxChange(Sender: TObject);
- procedure StructureDataSourceDataChange(Sender: TObject;
- Field: TField);
- procedure StructureTableAfterDelete(DataSet: TDataSet);
- procedure StructureTableAfterInsert(DataSet: TDataSet);
- procedure AddFieldButtonClick(Sender: TObject);
- procedure StructureTableNewRecord(DataSet: TDataset);
- procedure DeleteFieldButtonClick(Sender: TObject);
- procedure CancelFieldButtonClick(Sender: TObject);
- procedure SaveFieldButtonClick(Sender: TObject);
- private
- { Private declarations }
- procedure BuildSqlStatement;
- procedure SetUiState;
- public
- { Public declarations }
- procedure ExceptionHandler(Sender: TObject; E: Exception);
- end;
-
- var
- CreateTableForm: TCreateTableForm;
-
- implementation
-
- {$R *.DFM}
-
- const
- {
- Constants naming the data types available for creating tables
- on an Interbase server.
- }
- ibBlob = 'BLOB';
- ibChar = 'CHAR';
- ibDate = 'DATE';
- ibDecimal = 'DECIMAL';
- ibDouble = 'DOUBLE PRECISION';
- ibFloat = 'FLOAT';
- ibInteger = 'INTEGER';
- ibNumeric = 'NUMERIC';
- ibSmallint = 'SMALLINT';
- ibVarchar = 'VARCHAR';
-
- { Constant naming the Structure table's file name. }
- tbStructure = '___STRCT.DB';
-
- {
- Constants naming the fields in the temporary Structure table.
- }
- stFieldName = 'Field Name';
- stType = 'Type';
- stSize = 'Size';
- stDec = 'Dec';
- stKey = 'Key';
- stOrder = 'Order';
-
- {
- Constants naming indexes in the temporary Structure table.
- }
- inUniqueName = 'UniqueName';
- inFieldOrder = 'FieldOrder';
-
-
- { Application wide custom excelption handler. }
- procedure TCreateTableForm.ExceptionHandler(Sender: TObject;
- E: Exception);
- begin
- {
- The purpose of this exception handler is to catch key
- violations in the StructureTable. Key violations are
- raised as EDBEngineErrors.
- }
- if E is EDBEngineError then
- begin
-
- with EDBEngineError(E).Errors[Pred(EDBEngineError(E).ErrorCount )] do
- begin
-
- { Is it a Key violation error? }
- if (ErrorCode = DBIERR_KEYVIOL) then
- begin
-
- if Message = 'Key violation.' then
- begin
- E.Message :=
- 'The field name ''' +
- StructureTable.FieldByName( stFieldName ).AsString +
- ''' is already used';
- end
-
- { This branch is applicable only for a Paradox 7.0 table }
- else
- begin
- E.Message :=
- 'Ther order number '''+
- StructureTable.FieldByName( stOrder ).AsString +
- ''' is already used ';
- end;
- end;
- end;
- end;
-
- { Let the user know what's wrong. }
- MessageBeep( $FFFF );
- Application.ShowException( E );
-
- end;
-
-
- procedure TCreateTableForm.FormCreate(Sender: TObject);
- begin
-
- try
- TargetDatabase.Open;
- except
- on EDatabaseError do
- begin
- { Could not open database; probably bad login. }
- Application.Terminate;
- end;
- end;
-
-
- try
-
- {
- Create the structure table on disk. Notice the usage of
- the Private directory of the current session to give
- the temporary structure table a place where to live.
- }
-
- with StructureTable do
- begin
-
- DatabaseName := Session.PrivateDir;
- TableName := tbStructure;
- TableType := ttParadox;
-
- {
- Define the... structure of the temporary structure table.
- }
- with FieldDefs do
- begin
- Clear;
- Add( stFieldName, ftString, 31, true );
- Add( stType, ftString, 18, true );
- Add( stSize, ftSmallint, 0, false );
- Add( stDec, ftSmallint, 0, false );
- Add( stKey, ftBoolean, 0, false );
- Add( stOrder, ftSmallint, 0, true );
- end;
-
- {
- Define its indexes.
- }
- with IndexDefs do
- begin
- Add( inUniqueName, stFieldName, [ixPrimary, ixUnique] );
-
- {$IFDEF WIN32}
- { Paradox 7.0 format supports unique secondary indexes. }
- Add( inFieldOrder, stOrder, [ixUnique] );
- {$ELSE}
- { Paradox 5.0 does not. The index options must be given
- nonetheless. }
- Add( inFieldOrder, stOrder, [ixCaseInsensitive] );
- {$ENDIF}
- end;
-
- CreateTable;
-
- { Display the table according to ascending values of the
- Order field. }
- IndexName := inFieldOrder;
-
- end;
-
- StructureTable.Open;
-
- except
- on EDatabaseError do
- begin
- { Couldn't create the Structure table. }
- Application.Terminate;
- end;
- end;
-
- { Initialize the combo box. }
- with TypeDBComboBox.Items do
- begin
- { Add supported Interbase field types to the combo box list}
- Add( ibBlob );
- Add( ibChar );
- Add( ibDate );
- Add( ibDecimal );
- Add( ibDouble );
- Add( ibFloat );
- Add( ibInteger );
- Add( ibNumeric );
- Add( ibSmallint );
- Add( ibVarchar );
- end;
-
-
- {
- Make sure all data aware controls get to the right data fields.
- }
- FieldNameDBEdit.DataField := stFieldName;
- TypeDBComboBox.DataField := stType;
- SizeDBEdit.DataField := stSize;
- DecDBEdit.DataField := stDec;
- KeyDBCheckBox.DataField := stKey;
- OrderDBEdit.DataField := stOrder;
-
- {
- Set up the application wide exception handler.
- }
- Application.OnException := ExceptionHandler;
-
- end;
-
- procedure TCreateTableForm.FormDestroy(Sender: TObject);
- begin
-
- StructureTable.Close;
- {
- The structure table is temporary. Delete it.
- }
- StructureTable.DeleteTable;
-
- TargetDatabase.Close;
-
- end;
-
- procedure TCreateTableForm.OkBitBtnClick(Sender: TObject);
- begin
-
- if TableNameEdit.Text = '' then
- begin
- raise EDataBaseError.Create( 'Missing Table Name' );
- end;
-
- if StructureTable.State in [dsInsert, dsEdit] then
- begin
- StructureTable.Post;
- end;
-
- {
- Make sure the sql statement is up to date even if previous
- error conditions occurred on the name field,
- }
- BuildSqlStatement;
-
- {
- Move the sql statment to the Query object, and execute it.
- Note that if execution fails, it will raise an exception
- that will be caught (and displayed) by the application wide
- exception handler.
- }
- With CreateQuery do
- begin
- Close;
- Sql.Clear;
- Sql.AddStrings( SqlStatmentMemo.Lines );
- ExecSql;
- end;
-
- MessageBeep( $FFFF );
- ShowMessage( 'Table created successfully.' );
-
- end;
-
- procedure TCreateTableForm.CancelBitBtnClick(Sender: TObject);
- begin
-
- Close;
-
- end;
-
- procedure TCreateTableForm.StructureTableBeforePost(
- DataSet: TDataSet);
- var
- CurrentType: String;
- begin
-
- {
- Note that Field Name, Type and Order are required by the
- structure of the Structure table. Other fields might need
- information, depending on what type the user has selected.
- }
-
- CurrentType := TypeDBComboBox.Items[ TypeDBComboBox.ItemIndex ];
-
- if (CurrentType = ibChar) or
- (CurrentType = ibVarchar) or
- (CurrentType = ibDecimal) or
- (CurrentType = ibNumeric) then
- begin
- if StructureTable.FieldByName( stSize ).isNull then
- begin
- raise EDataBaseError.Create( 'Missing Size' );
- end;
- end;
-
- if (CurrentType = ibDecimal) or
- (CurrentType = ibNumeric) then
- begin
- if StructureTable.FieldByName( stDec ).isNull then
- begin
- raise EDataBaseError.Create( 'Missing Decimals' );
- end;
- end;
-
- end;
-
- procedure TCreateTableForm.StructureTableAfterPost(
- DataSet: TDataSet);
- begin
-
- BuildSqlStatement;
-
- end;
-
- procedure TCreateTableForm.StructureTableAfterDelete(
- DataSet: TDataSet);
- begin
-
- BuildSqlStatement;
-
- end;
-
- procedure TCreateTableForm.StructureTableAfterInsert(
- DataSet: TDataSet);
- begin
-
- With StructureTable do
- begin
- FieldByName( stOrder ).AsInteger := Succ( RecordCount );
- FieldByName( stKey ).AsBoolean := False;
- end;
-
- end;
-
- procedure TCreateTableForm.StructureTableNewRecord(
- DataSet: TDataset);
- begin
-
- SetUiState;
-
- end;
-
- procedure TCreateTableForm.BuildSqlStatement;
- var
- CurrentRecord: TBookmark;
- FieldLine: String;
- PrimaryKeyFields: String;
- NeedComma: Boolean;
- begin
- {
- The SQL statment that will be used to create the table on
- the Interbase server will be built and stored in the
- SqlStatmentMemo component. In this way, the user can actually
- see what will be sent to the server.
- }
- with SqlStatmentMemo.Lines do
- begin
-
- Clear;
- Add( 'CREATE TABLE ' + TableNameEdit.Text + ' (' );
-
- {
- The building process is straightforward: scan through the
- Structure Table and add lines to the SQL statment as you
- go, taking into account all relevant SQL syntax rules.
- }
- with StructureTable do
- begin
- DisableControls;
-
- {
- Since the scanning process will move the table pointer to
- the bottom, use a bookmark so that you can get back to
- the current record at the end of the loop.
- }
- CurrentRecord := GetBookmark;
-
- {
- Initialize all loop entry conditions.
- }
- PrimaryKeyFields := '';
- NeedComma := False;
- First;
-
- { Scan through the structure table. }
-
- while not Eof do
- begin
-
- { If needed, add a comma to the end of the last line. }
- if NeedComma then
- begin
- Strings[Pred(Count)] := Strings[Pred(Count)] + ',';
- end;
-
- { Start building the new line, add the field name. }
- FieldLine := ' ' + FieldByName( stFieldName ).AsString +
- ' ' + FieldByName( stType).AsString;
-
- { Add the field size if present. }
- if not FieldByName( stSize).IsNull then
- begin
- FieldLine := FieldLine + '( ' +
- FieldByName( stSize ).AsString;
-
- { Add the field precision if present. }
- if not FieldByName( stDec).IsNull then
- begin
- FieldLine := FieldLine + ', ' +
- FieldByName( stDec ).AsString;
- end;
- FieldLine := FieldLine + ' )';
- end;
-
- { Check out for key fields. }
- if FieldByName( stKey ).AsBoolean then
- begin
-
- { Add the NOT NULL constraint. }
- FieldLine := FieldLine + ' NOT NULL';
-
- { Expand the primary key clause. }
- if PrimaryKeyFields <> '' then
- begin
- PrimaryKeyFields := PrimaryKeyFields + ', ';
- end;
- PrimaryKeyFields := PrimaryKeyFields +
- FieldByName( stFieldName ).AsString;
- end;
-
- { Add the newly constructed line. }
- Add( FieldLine );
- NeedComma := True;
- Next;
- end;
-
- GotoBookmark( CurrentRecord );
- EnableControls;
- FreeBookmark( CurrentRecord );
-
- { If there is a primary key, add its clause. }
- if PrimaryKeyFields <> '' then
- begin
- Strings[Pred(Count)] := Strings[Pred(Count)] + ',';
- Add( ' PRIMARY KEY (' + PrimaryKeyFields + ')' );
- end;
- end;
- Add( ');' );
- end;
- end;
-
- procedure TCreateTableForm.SetUiState;
- var
- CurrentType: String;
- begin;
-
- CurrentType := TypeDBComboBox.Items[ TypeDBComboBox.ItemIndex ];
-
- {
- Allow the user to create a table only if there exists at least
- one field.
- }
- OkBitBtn.Enabled := Not (
- StructureTable.BOF and StructureTable.EOF
- );
-
- {
- If the user is editing SetUiState will be called only from
- the TypeDBComboBox's OnChange event handler, so initialize
- fields according to the field type selected by the user.
- }
- if StructureTable.State in [dsInsert, dsEdit] then
- begin
- StructureTable.FieldByName( stSize ).Clear;
- StructureTable.FieldByName( stDec ).Clear;
- StructureTable.FieldByName( stKey ).AsBoolean := False;
- end;
-
- {
- Set visibile and enabled properties as required.
- }
- if (CurrentType = ibChar) or (CurrentType = ibVarchar) then
- begin
- SizeDBEdit.Enabled := True;
- SizeDBEdit.Color := clWindow;
- SizeLabel.Enabled := True;
- DecDBEdit.Enabled := False;
- DecDBEdit.Color := clBtnFace;
- DecLabel.Enabled := False;
- KeyDBCheckBox.Enabled := True;
- end
-
- else if (CurrentType = ibDecimal ) or
- (CurrentType = ibNumeric) then
- begin
- SizeDBEdit.Enabled := True;
- SizeDBEdit.Color := clWindow;
- SizeLabel.Enabled := True;
- DecDBEdit.Enabled := True;
- DecDBEdit.Color := clWindow;
- DecLabel.Enabled := True;
- KeyDBCheckBox.Enabled := True;
- end
-
- else if (CurrentType = ibBlob ) then
- begin
- SizeDBEdit.Enabled := False;
- SizeDBEdit.Color := clBtnFace;
- SizeLabel.Enabled := False;
- DecDBEdit.Enabled := False;
- DecDBEdit.Color := clBtnFace;
- DecLabel.Enabled := False;
- KeyDBCheckBox.Enabled := False;
- end
-
- else
- begin
- SizeDBEdit.Enabled := False;
- SizeDBEdit.Color := clBtnFace;
- SizeLabel.Enabled := False;
- DecDBEdit.Enabled := False;
- DecDBEdit.Color := clBtnFace;
- DecLabel.Enabled := False;
- KeyDBCheckBox.Enabled := True;
- end;
-
- end;
-
- procedure TCreateTableForm.TableNameEditExit(Sender: TObject);
- begin
-
- BuildSqlStatement;
-
- end;
-
- procedure TCreateTableForm.TableNameEditKeyPress(Sender: TObject;
- var Key: Char);
- begin
-
- Key := UpCase( Key );
- if Key = ' ' then
- begin
- Key := '_'
- end;
-
- end;
-
- procedure TCreateTableForm.FieldNameDBEditKeyPress(Sender: TObject;
- var Key: Char);
- begin
-
- Key := UpCase( Key );
- if Key = ' ' then
- begin
- Key := '_'
- end;
-
- end;
-
- procedure TCreateTableForm.TypeDBComboBoxChange(Sender: TObject);
- begin
-
- SetUiState;
-
- end;
-
- procedure TCreateTableForm.StructureDataSourceDataChange(
- Sender: TObject; Field: TField);
- begin
-
- if StructureDataSource.DataSet <> Nil then
- begin
- if StructureDataSource.DataSet.State in [dsBrowse] then
- begin
- SetUiState;
- end;
- end;
-
- end;
-
- procedure TCreateTableForm.AddFieldButtonClick(Sender: TObject);
- begin
-
- FieldNameDBEdit.SetFocus;
- StructureTable.Append;
-
- end;
-
- procedure TCreateTableForm.DeleteFieldButtonClick(Sender: TObject);
- begin
-
- StructureTable.Delete;
-
- end;
-
- procedure TCreateTableForm.CancelFieldButtonClick(Sender: TObject);
- begin
-
- StructureTable.Cancel;
-
- end;
-
- procedure TCreateTableForm.SaveFieldButtonClick(Sender: TObject);
- begin
-
- StructureTable.Post;
-
- end;
-
- end.
-