fpdatadict.pp 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941
  1. {
  2. This file is part of the Free Pascal run time library.
  3. Copyright (c) 2007 by Michael Van Canneyt, member of the
  4. Free Pascal development team
  5. Data Dictionary Implementation.
  6. See the file COPYING.FPC, included in this distribution,
  7. for details about the copyright.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. **********************************************************************}
  12. unit fpdatadict;
  13. {$mode objfpc}{$H+}
  14. interface
  15. uses
  16. Classes, SysUtils,inicol, inifiles, contnrs, db;
  17. Type
  18. // Supported objects in this data dictionary
  19. TObjectType = (otUnknown,otDictionary,otTables,otTable,otFields,otField,
  20. otConnection,otTableData,otIndexDefs,otIndexDef);
  21. TDDProgressEvent = Procedure(Sender : TObject; Const Msg : String) of Object;
  22. { TDDFieldDef }
  23. TDDFieldDef = Class(TIniCollectionItem)
  24. private
  25. FAlignMent: TAlignMent;
  26. FConstraint: string;
  27. FConstraintErrorMessage: string;
  28. FCustomConstraint: string;
  29. FDefault: String;
  30. FDefaultExpression: string;
  31. FDisplayLabel: string;
  32. FDisplayWidth: Longint;
  33. FFieldName: string;
  34. FFieldType: TFieldType;
  35. FHint: String;
  36. FPrecision: Integer;
  37. FReadOnly: Boolean;
  38. FRequired: Boolean;
  39. FSize: Integer;
  40. FVisible: Boolean;
  41. Function IsSizeStored : Boolean;
  42. Function IsPrecisionStored : Boolean;
  43. protected
  44. function GetSectionName: String; override;
  45. procedure SetSectionName(const Value: String); override;
  46. Public
  47. Constructor Create(ACollection : TCollection); override;
  48. Procedure ImportFromField(F: TField; Existing : Boolean = True);
  49. Procedure ApplyToField(F : TField);
  50. Procedure Assign(Source : TPersistent); override;
  51. Procedure SaveToIni(Ini: TCustomInifile; ASection : String); override;
  52. Procedure LoadFromIni(Ini: TCustomInifile; ASection : String); override;
  53. Published
  54. property FieldType : TFieldType Read FFieldType Write FFieldType;
  55. property AlignMent : TAlignMent Read FAlignMent write FAlignment default taLeftJustify;
  56. property CustomConstraint: string read FCustomConstraint write FCustomConstraint;
  57. property ConstraintErrorMessage: string read FConstraintErrorMessage write FConstraintErrorMessage;
  58. Property DBDefault : String Read FDefault Write FDEfault;
  59. property DefaultExpression: string read FDefaultExpression write FDefaultExpression;
  60. property DisplayLabel : string read FDisplayLabel write FDisplayLabel;
  61. property DisplayWidth: Longint read FDisplayWidth write FDisplayWidth;
  62. property FieldName: string read FFieldName write FFieldName;
  63. property Constraint: string read FConstraint write FConstraint;
  64. property ReadOnly: Boolean read FReadOnly write FReadOnly;
  65. property Required: Boolean read FRequired write FRequired;
  66. property Visible: Boolean read FVisible write FVisible default True;
  67. Property Size : Integer Read FSize Write FSize Stored IsSizeStored;
  68. Property Precision : Integer Read FPrecision Write FPrecision Stored IsPrecisionStored;
  69. Property Hint : String Read FHint Write FHint;
  70. end;
  71. { TDDFieldDefs }
  72. TDDFieldDefs = Class(TIniCollection)
  73. private
  74. FTableName: String;
  75. function GetField(Index : Integer): TDDFieldDef;
  76. procedure SetField(Index : Integer; const AValue: TDDFieldDef);
  77. procedure SetTableName(const AValue: String);
  78. Public
  79. Constructor Create(ATableName : String);
  80. Function AddField(AFieldName: String = '') : TDDFieldDef;
  81. Function IndexOfField(AFieldName : String) : Integer;
  82. Function FindField(AFieldName : String) : TDDFieldDef;
  83. Function FieldByName(AFieldName : String) : TDDFieldDef;
  84. Property Fields[Index : Integer] : TDDFieldDef Read GetField Write SetField; default;
  85. Property TableName : String Read FTableName Write SetTableName;
  86. end;
  87. { TDDIndexDef }
  88. TDDIndexDef = Class(TIniCollectionItem)
  89. private
  90. FCaseinsFields: string;
  91. FDescFields: string;
  92. FExpression: string;
  93. FFields: string;
  94. FIndexName: String;
  95. FOptions: TIndexOptions;
  96. FSource: string;
  97. protected
  98. function GetSectionName: String; override;
  99. procedure SetSectionName(const Value: String); override;
  100. procedure Assign(ASource : TPersistent); override;
  101. Published
  102. Property IndexName : String Read FIndexName Write FIndexName;
  103. property Expression: string read FExpression write FExpression;
  104. property Fields: string read FFields write FFields;
  105. property CaseInsFields: string read FCaseinsFields write FCaseInsFields;
  106. property DescFields: string read FDescFields write FDescFields;
  107. property Options: TIndexOptions read FOptions write FOptions;
  108. property Source: string read FSource write FSource;
  109. end;
  110. { TDDIndexDefs }
  111. TDDIndexDefs = Class(TIniCollection)
  112. private
  113. FTableName : String;
  114. function GetIndex(Index : Integer): TDDIndexDef;
  115. procedure SetIndex(Index : Integer; const AValue: TDDIndexDef);
  116. procedure SetTableName(const AValue: String);
  117. Public
  118. Constructor Create(ATableName : String);
  119. Function AddDDIndexDef(AName : String) : TDDIndexDef;
  120. Property TableName : String Read FTableName Write SetTableName;
  121. Property Indexes[Index : Integer] : TDDIndexDef Read GetIndex Write SetIndex; default;
  122. end;
  123. { TDDTableDef }
  124. TDDTableDef = Class(TIniCollectionItem)
  125. private
  126. FFieldDefs: TDDFieldDefs;
  127. FIndexDefs: TDDIndexDefs;
  128. FPrimaryKeyName: String;
  129. FTableName: String;
  130. function GetOnProgress: TDDProgressEvent;
  131. function GetPrimaryKeyName: String;
  132. procedure SetTableName(const AValue: String);
  133. protected
  134. function GetSectionName: String; override;
  135. procedure SetSectionName(const Value: String); override;
  136. Public
  137. Constructor Create(ACollection : TCollection); override;
  138. Destructor Destroy; override;
  139. Function ImportFromDataset(Dataset : TDataSet; DoClear : Boolean = False; UpdateExisting : Boolean = True) : Integer;
  140. Procedure ApplyToDataset(Dataset : TDataset);
  141. Function AddField(AFieldName : String = '') : TDDFieldDef;
  142. Procedure SaveToIni(Ini: TCustomInifile; ASection : String); override;
  143. Procedure LoadFromIni(Ini: TCustomInifile; ASection : String); override;
  144. Property Fields : TDDFieldDefs Read FFieldDefs;
  145. Property Indexes : TDDIndexDefs Read FIndexDefs;
  146. Property OnProgress : TDDProgressEvent Read GetOnProgress;
  147. Published
  148. Property TableName : String Read FTableName Write SetTableName;
  149. Property PrimaryKeyConstraintName : String Read GetPrimaryKeyName Write FPrimaryKeyName;
  150. end;
  151. { TDDTableDefs }
  152. TDDTableDefs = Class(TIniCollection)
  153. private
  154. FOnProgress: TDDProgressEvent;
  155. function GetTable(Index : Integer): TDDTableDef;
  156. procedure SetTable(Index : Integer; const AValue: TDDTableDef);
  157. Public
  158. Function AddTable(ATableName : String = '') : TDDTableDef;
  159. Function IndexOfTable(ATableName : String) : Integer;
  160. Function FindTable(ATableName : String) : TDDTableDef;
  161. Function TableByName(ATableName : String) : TDDTableDef;
  162. Property Tables[Index : Integer] : TDDTableDef Read GetTable Write SetTable; default;
  163. Property OnProgress : TDDProgressEvent Read FOnProgress Write FOnProgress;
  164. end;
  165. { TFPDataDictionary }
  166. TOnApplyDataDictEvent = Procedure (Sender : TObject; Source : TDDFieldDef; Dest : TField; Var Allow : Boolean) of object;
  167. TFPDataDictionary = Class(TPersistent)
  168. private
  169. FDDName: String;
  170. FFileName: String;
  171. FOnApplyDataDictEvent: TOnApplyDataDictEvent;
  172. FOnProgress: TDDProgressEvent;
  173. FTables: TDDTableDefs;
  174. // Last table that returned a match for findfieldDef
  175. FLastMatchTableDef : TDDTableDef;
  176. procedure SetOnProgress(const AValue: TDDProgressEvent);
  177. Public
  178. Constructor Create;
  179. Destructor Destroy; override;
  180. Procedure SaveToFile(AFileName : String; KeepBackup: Boolean = True);
  181. Procedure SaveToIni(Ini : TCustomIniFile; ASection : String); virtual;
  182. Procedure LoadFromFile(AFileName : String);
  183. Procedure LoadFromIni(Ini : TCustomIniFile; ASection : String); virtual;
  184. Procedure ApplyToDataset(ADataset : TDataset);
  185. Procedure ApplyToDataset(ADataset : TDataset; OnApply : TOnApplyDataDictEvent);
  186. Function FindFieldDef(FieldName : String; out TableName : String) : TDDFieldDef;
  187. Function FindFieldDef(FieldName : String) : TDDFieldDef;
  188. function CanonicalizeFieldName(const InFN: String; Out TN, FN: String): Boolean;
  189. function CanonicalizeFieldName(const InFN: String; Out TableDef : TDDTableDef; Out FN: String): Boolean;
  190. Property Tables : TDDTableDefs Read FTables;
  191. Property FileName : String Read FFileName;
  192. Property Name : String Read FDDName Write FDDName;
  193. Property OnProgress : TDDProgressEvent Read FOnProgress Write SetOnProgress;
  194. Published
  195. // Using name confuses the object inspector grid.
  196. Property DataDictionaryName : String Read FDDName Write FDDName;
  197. Property OnApplyDataDictEvent : TOnApplyDataDictEvent Read FOnApplyDataDictEvent Write FOnApplyDataDictEvent;
  198. end;
  199. { TFPDDFieldList }
  200. TFPDDFieldList = Class(TObjectList)
  201. private
  202. function GetFieldDef(Index : Integer): TDDFieldDef;
  203. procedure SetFieldDef(Index : Integer; const AValue: TDDFieldDef);
  204. Public
  205. Constructor CreateFromTableDef(TD : TDDTableDef);
  206. Constructor CreateFromFieldDefs(FD : TDDFieldDefs);
  207. Property FieldDefs[Index : Integer] : TDDFieldDef Read GetFieldDef Write SetFieldDef; default;
  208. end;
  209. { TFPDDSQLEngine }
  210. TSQLEngineOption = (eoLineFeedAfterField,eoUseOldInWhereParams,eoAndTermsInBrackets,eoQuoteFieldNames,eoLineFeedAfterAndTerm,eoAddTerminator);
  211. TSQLEngineOptions = Set of TSQLEngineOption;
  212. TFPDDSQLEngine = Class(TPersistent)
  213. private
  214. FFieldQuoteChar: Char;
  215. FIndent: Integer;
  216. FMaxLineLength: Integer;
  217. FLastLength: integer;
  218. FOptions: TSQLEngineOptions;
  219. FTableDef: TDDTableDef;
  220. FNoIndent : Boolean;
  221. FTerminatorChar : Char;
  222. Protected
  223. procedure CheckTableDef;
  224. Procedure NoIndent;
  225. Procedure ResetLine;
  226. Procedure AddToStringLN(Var Res : String; S : String);
  227. Procedure AddToString(Var Res : String; S : String);
  228. Procedure FixUpStatement(var Res : String);
  229. Procedure AddWhereClause(Var Res : String; FieldList: TFPDDFieldList; UseOldParam:Boolean);
  230. Function CreateAndTerm(FD : TDDFieldDef; UseOldParam : Boolean): string;
  231. // Primitives. Override for engine-specifics
  232. Procedure AddFieldString(Var Res: String; S : String);
  233. Function FieldNameString(FD : TDDFieldDef) : string; virtual;
  234. Function TableNameString(TD : TDDTableDef) : string; virtual;
  235. Function FieldParamString(FD : TDDFieldDef; UseOldParam : Boolean) : string; virtual;
  236. Function FieldTypeString(FD : TDDFieldDef) : String; virtual;
  237. Function FieldDefaultString(FD : TDDFieldDef) : String; virtual;
  238. Function FieldCheckString(FD : TDDFieldDef) : String; virtual;
  239. Function FieldDeclarationString(FD : TDDFieldDef) : String; virtual;
  240. Property FieldQuoteChar : Char Read FFieldQuoteChar Write FFieldQuoteChar;
  241. Property TerminatorChar : Char Read FTerminatorChar Write FTerminatorChar;
  242. Public
  243. Constructor Create; virtual;
  244. function CreateWhereSQL(Var Res : String; FieldList: TFPDDFieldList; UseOldParam:Boolean): String;
  245. Procedure CreateSelectSQLStrings(FieldList,KeyFields : TFPDDFieldList; SQL : TStrings);
  246. Procedure CreateInsertSQLStrings(FieldList : TFPDDFieldList; SQL : TStrings);
  247. Procedure CreateUpdateSQLStrings(FieldList,KeyFields : TFPDDFieldList; SQL : TStrings);
  248. Procedure CreateDeleteSQLStrings(KeyFields : TFPDDFieldList; SQL : TStrings);
  249. Procedure CreateCreateSQLStrings(Fields,KeyFields : TFPDDFieldList; SQL : TStrings);
  250. Procedure CreateCreateSQLStrings(KeyFields : TFPDDFieldList; SQL : TStrings);
  251. Function CreateSelectSQL(FieldList,KeyFields : TFPDDFieldList) : String; virtual;
  252. Function CreateInsertSQL(FieldList : TFPDDFieldList) : String; virtual;
  253. Function CreateUpdateSQL(FieldList,KeyFields : TFPDDFieldList) : String; virtual;
  254. Function CreateDeleteSQL(KeyFields : TFPDDFieldList) : String; virtual;
  255. Function CreateCreateSQL(Fields,KeyFields : TFPDDFieldList) : String; virtual;
  256. Function CreateCreateSQL(KeyFields : TFPDDFieldList) : String; virtual;
  257. Property TableDef : TDDTableDef Read FTableDef Write FTableDef;
  258. Published
  259. Property MaxLineLength : Integer Read FMaxLineLength Write FMaxLineLength default 72;
  260. Property Indent : Integer Read FIndent Write FIndent default 2;
  261. Property Options : TSQLEngineOptions Read FOptions Write FOptions;
  262. end;
  263. { TFPDDEngine }
  264. TFPDDEngineCapability =(ecImport,ecCreateTable,ecViewTable, ecTableIndexes, ecRunQuery, ecRowsAffected);
  265. TFPDDEngineCapabilities = set of TFPDDEngineCapability;
  266. {
  267. to avoid dependencies on GUI elements in the data dictionary engines,
  268. connection string dialogs must be registered separately.
  269. TGetConnectionEvent is the callback prototype for such a dialog
  270. }
  271. TGetConnectionEvent = Procedure(Sender: TObject; Var Connection : String) of object;
  272. TFPDDEngine = Class(TComponent)
  273. private
  274. FOnProgress: TDDProgressEvent;
  275. Protected
  276. FConnected: Boolean;
  277. FConnectString: String;
  278. Procedure DoProgress(Const Msg : String);
  279. // Utility routine which can be used by descendents.
  280. procedure IndexDefsToDDIndexDefs(IDS : TIndexDefs; DDIDS : TDDindexDefs);
  281. Public
  282. Destructor Destroy; override;
  283. Function GetConnectString : String; virtual;
  284. Function ImportTables(Tables : TDDTableDefs; List : TStrings; UpdateExisting : Boolean) : Integer;
  285. // Mandatory for all data dictionary engines.
  286. Class function Description : string; virtual; abstract;
  287. Class function DBType : String; virtual; abstract;
  288. Class function EngineCapabilities : TFPDDEngineCapabilities; virtual;
  289. Function Connect(const ConnectString : String) : Boolean; virtual; abstract;
  290. Procedure Disconnect ; virtual; abstract;
  291. Function GetTableList(List : TStrings) : Integer; virtual; abstract;
  292. Function ImportFields(Table : TDDTableDef) : Integer; virtual; abstract;
  293. // Override depending on capabilities
  294. Procedure CreateTable(Table : TDDTableDef); virtual;
  295. // Should not open the dataset.
  296. Function ViewTable(Const TableName: String; DatasetOwner : TComponent) : TDataset; virtual;
  297. // Run a non-select query. If possible, returns the number of modified records.
  298. Function RunQuery(SQL : String) : Integer; Virtual;
  299. // Create a select query TDataset. Do not open the resulting dataset.
  300. Function CreateQuery(SQL : String; DatasetOwner : TComponent) : TDataset; Virtual;
  301. // Assign a select query and open the resulting dataset.
  302. Procedure SetQueryStatement(SQL : String; AQuery : TDataset); Virtual;
  303. // Get table index defs. Return number of defs (if ecTableIndexes in capabilities)
  304. Function GetTableIndexDefs(ATableName : String; Defs : TDDIndexDefs) : integer ;virtual;
  305. // Override if a better implementation exists.
  306. Function CreateSQLEngine : TFPDDSQLEngine; virtual;
  307. Property OnProgress : TDDProgressEvent Read FOnProgress Write FOnProgress;
  308. Property ConnectString : String Read FConnectString;
  309. Property Connected : Boolean Read FConnected Write FConnected;
  310. end;
  311. TFPDDEngineClass = Class of TFPDDEngine;
  312. EDataDict = Class(Exception);
  313. Procedure RegisterDictionaryEngine(AEngine :TFPDDEngineClass);
  314. Function IsDictionaryEngineRegistered(AEngine :TFPDDEngineClass) : boolean;
  315. Procedure RegisterConnectionStringCallback(Const AName: String; CallBack : TGetConnectionEvent);
  316. Procedure UnRegisterDictionaryEngine(AEngine :TFPDDEngineClass);
  317. Function GetDictionaryEngineList(List : TStrings) : Integer;
  318. Function GetDictionaryEngineInfo(Const AName : String; out ADescription,ADBType: String; out ACapabilities : TFPDDEngineCapabilities) : boolean;
  319. Function CreateDictionaryEngine(AName : String; AOWner : TComponent) : TFPDDEngine;
  320. Function IndexOptionsToString (Options : TIndexOptions) : String;
  321. Var
  322. DefaultDDExt : String = '.fpd';
  323. // Default values for SQL Engine properties.
  324. DefaultSQLEngineOptions : TSQLEngineOptions
  325. = [eoLineFeedAfterField,eoUseOldInWhereParams,
  326. eoAndTermsInBrackets,eoLineFeedAfterAndTerm];
  327. DefaultSQLEngineIndent : Integer = 2;
  328. DefaultSQLEngineLineLength : Integer = 72;
  329. DefaultSQLTerminatorChar : Char = ';';
  330. DefaultSQLFieldQuoteChar : Char = '"';
  331. implementation
  332. uses typinfo;
  333. { ---------------------------------------------------------------------
  334. Constants, not to be localized
  335. ---------------------------------------------------------------------}
  336. Const
  337. // Datadict saving
  338. SDataDict = 'FPDataDict';
  339. KeyDataDictName = 'DataDictName';
  340. // Tables Saving
  341. SDataDictTables = SDataDict+'_Tables';
  342. KeyTableName = 'TableName';
  343. KeyPrimaryKeyConstraint = 'PrimaryKeyConstraint';
  344. // Fields Saving
  345. SFieldSuffix = '_Fields';
  346. SIndexSuffix = '_Indices';
  347. KeyAlignMent = 'AlignMent';
  348. KeyCustomConstraint = 'CustomConstraint';
  349. KeyConstraintErrorMessage = 'ConstraintErrorMessage';
  350. KeyDBDefault = 'DBDefault';
  351. KeyDefaultExpression = 'DefaultExpression';
  352. KeyDisplayLabel = 'DisplayLabel';
  353. KeyDisplayWidth = 'DisplayWidth';
  354. KeyFieldName = 'FieldName';
  355. KeyConstraint = 'Constraint';
  356. KeyReadOnly = 'ReadOnly';
  357. KeyRequired = 'Required';
  358. KeyVisible = 'Visible';
  359. KeySize = 'Size';
  360. KeyPrecision = 'Precision';
  361. KeyFieldType = 'FieldType';
  362. KeyHint = 'Hint';
  363. // SQL Keywords
  364. SSelect = 'SELECT';
  365. SFrom = 'FROM';
  366. SWhere = 'WHERE';
  367. SInsertInto = 'INSERT INTO';
  368. SUpdate = 'UPDATE';
  369. SSet = 'SET';
  370. SDeleteFrom = 'DELETE FROM';
  371. SAnd = 'AND';
  372. SOLD = 'OLD';
  373. SValues = 'VALUES';
  374. SCreateTable = 'CREATE TABLE';
  375. SNotNull = 'NOT NULL';
  376. SDefault = 'DEFAULT';
  377. SCheck = 'CHECK'; // Check constraint
  378. SPrimaryKey = 'PRIMARY KEY';
  379. SConstraint = 'CONSTRAINT';
  380. SQLFieldTypes : Array[TFieldType] of string = (
  381. '', 'VARCHAR', 'SMALLINT', 'INT', 'SMALLINT',
  382. 'BOOL', 'FLOAT', 'DECIMAL','DECIMAL','DATE', 'TIME', 'TIMESTAMP',
  383. '', '', 'INT', 'BLOB', 'BLOB', 'BLOB', 'BLOB',
  384. '', '', '', '', 'CHAR',
  385. 'CHAR', 'DOUBLE PRECISION', '', '', '',
  386. '', '', '', '', '',
  387. '', '', 'TIMESTAMP', 'DECIMAL','CHAR','BLOB');
  388. { ---------------------------------------------------------------------
  389. Constants which can be localized
  390. ---------------------------------------------------------------------}
  391. Resourcestring
  392. SErrFieldNotFound = '"%s": Field "%s" not found.';
  393. SErrTableNotFound = 'Table "%s" not found.';
  394. SErrDuplicateTableName = 'Duplicate table name: "%s"';
  395. SErrDuplicateFieldName = '"%s": Duplicate field name: "%s"';
  396. SNewTable = 'NewTable';
  397. SNewField = 'NewField';
  398. SErrNoFileName = 'No filename given for save';
  399. SErrNotRegistering = 'Not registering data dictionary engine "%s": %s';
  400. SErrNoEngineCapabilities = 'It reports no capabilities.';
  401. SErrNoEngineDBType = 'It reports no database type';
  402. SErrNoEngineDescription = 'It reports no description';
  403. SErrUnknownEngine = 'Unknown datadictionary: "%s"';
  404. SErrMissingTableDef = 'Cannot perform this operation without tabledef.';
  405. SErrFieldTypeNotSupported = 'Field type "%s" is not supported in this SQL dialect';
  406. SErrNoConnectionDialog = 'No connection dialog registered for data dictionary engine "%s".';
  407. SDDImportingTable = 'Importing table definition for table "%s"';
  408. SErrCreateTableNotSupported = 'Creating tables is not supported by the "%s" engine.';
  409. SErrViewTableNotSupported = 'Viewing tables is not supported by the "%s" engine.';
  410. SErrRunQueryNotSupported = 'Running queries is not supported by the "%s" engine.';
  411. SErrOpenQueryNotSupported = 'Running and opening SELECT queries is not supported by the "%s" engine.';
  412. SErrSetQueryStatementNotSupported = 'Setting the SQL statement is not supported by the "%s" engine.';
  413. SErrGetTableIndexDefsNotSupported = 'Getting index definitions of a table is not supported by the "%s" engine.';
  414. SSavingFieldsFrom = 'Saving fields from %s';
  415. SLoadingFieldsFrom = 'Loading fields from %s';
  416. SIndexOptionPrimary = 'Primary key';
  417. SIndexOptionUnique = 'Unique';
  418. SIndexOptionDescending = 'Descending';
  419. SIndexOptionCaseInsensitive = 'Case insensitive';
  420. SIndexOptionExpression = 'Expression';
  421. SIndexOptionNonMaintained = 'Not maintained';
  422. SWarnFieldNotFound = 'Could not find field "%s".';
  423. SLogFieldFoundIn = 'Field "%s" found in table "%s".';
  424. Const
  425. IndexOptionNames : Array [TIndexOption] of String
  426. = (SIndexOptionPrimary, SIndexOptionUnique,
  427. SIndexOptionDescending, SIndexOptionCaseInsensitive,
  428. SIndexOptionExpression, SIndexOptionNonMaintained);
  429. { ---------------------------------------------------------------------
  430. Dictionary Engine registration
  431. ---------------------------------------------------------------------}
  432. Var
  433. DDEngines : TStringList = nil;
  434. Type
  435. { TEngineRegistration }
  436. TEngineRegistration = Class(TObject)
  437. Private
  438. FEngine : TFPDDEngineClass;
  439. FCallBack : TGetConnectionEvent;
  440. Public
  441. Constructor Create(AEngine : TFPDDEngineClass);
  442. end;
  443. { TEngineRegistration }
  444. constructor TEngineRegistration.Create(AEngine: TFPDDEngineClass);
  445. begin
  446. FEngine:=AEngine;
  447. end;
  448. procedure RegisterDictionaryEngine(AEngine: TFPDDEngineClass);
  449. begin
  450. If (AEngine.EngineCapabilities=[]) then
  451. Raise EDataDict.CreateFmt(SErrNotRegistering,[AEngine.ClassName,SErrNoEngineCapabilities]);
  452. If (AEngine.DBType='') then
  453. Raise EDataDict.CreateFmt(SErrNotRegistering,[AEngine.ClassName,SErrNoEngineDBType]);
  454. If (AEngine.Description='') then
  455. Raise EDataDict.CreateFmt(SErrNotRegistering,[AEngine.ClassName,SErrNoEngineDescription]);
  456. If not assigned(DDEngines) then
  457. begin
  458. DDEngines:=TStringList.Create;
  459. DDEngines.Sorted:=true;
  460. DDEngines.Duplicates:=dupError;
  461. end;
  462. DDEngines.AddObject(Aengine.ClassName,TEngineRegistration.Create(AEngine));
  463. end;
  464. procedure UnRegisterDictionaryEngine(AEngine: TFPDDEngineClass);
  465. Var
  466. I : Integer;
  467. begin
  468. If Assigned(DDEngines) then
  469. begin
  470. I:=DDEngines.IndexOf(Aengine.ClassName);
  471. If (i<>-1) then
  472. begin
  473. DDEngines.Objects[i].Free;
  474. DDEngines.Delete(i);
  475. end;
  476. if (DDEngines.Count=0) then
  477. FreeAndNil(DDEngines);
  478. end;
  479. end;
  480. function GetDictionaryEngineList(List: TStrings): Integer;
  481. begin
  482. If Not Assigned(DDEngines) then
  483. Result:=0
  484. else
  485. begin
  486. If Assigned(List) then
  487. List.Text:=DDEngines.Text;
  488. Result:=DDEngines.Count;
  489. end;
  490. end;
  491. Function IndexOfDDEngine(Const AName: String) : Integer;
  492. begin
  493. If Assigned(DDEngines) then
  494. Result:=DDEngines.IndexOf(AName)
  495. else
  496. Result:=-1;
  497. end;
  498. Function FindEngineRegistration(Const AName : String) : TEngineRegistration;
  499. Var
  500. I : integer;
  501. begin
  502. I:=IndexOfDDEngine(AName);
  503. if (I<>-1) then
  504. Result:=TEngineRegistration(DDEngines.Objects[i])
  505. else
  506. Result:=Nil;
  507. end;
  508. Function GetEngineRegistration(Const AName : String) : TEngineRegistration;
  509. begin
  510. Result:=FindEngineRegistration(AName);
  511. If (Result=Nil) then
  512. Raise EDataDict.CreateFmt(SErrUnknownEngine,[AName]);
  513. end;
  514. Function FindDictionaryClass(Const AName : String) : TFPDDEngineClass;
  515. Var
  516. R : TEngineRegistration;
  517. begin
  518. R:=FindEngineRegistration(AName);
  519. If (R=Nil) then
  520. Result:=Nil
  521. else
  522. Result:=R.FEngine;
  523. end;
  524. Function GetDictionaryClass(Const AName : String) : TFPDDEngineClass;
  525. begin
  526. Result:=GetEngineRegistration(AName).FEngine;
  527. end;
  528. function IsDictionaryEngineRegistered(AEngine: TFPDDEngineClass): boolean;
  529. Var
  530. I : Integer;
  531. begin
  532. Result:=Assigned(DDEngines);
  533. If Result then
  534. begin
  535. Result:=False;
  536. I:=0;
  537. While (Not Result) and (I<DDEngines.Count) do
  538. begin
  539. Result:=(TEngineRegistration(DDEngines.Objects[i]).FEngine=AEngine);
  540. inc(I);
  541. end;
  542. end;
  543. end;
  544. procedure RegisterConnectionStringCallback(Const AName : String;
  545. CallBack: TGetConnectionEvent);
  546. begin
  547. GetEngineRegistration(AName).FCallBack:=CallBack;
  548. end;
  549. function GetEngineConnectionStringCallBack(Const AName : String) : TGetConnectionEvent;
  550. begin
  551. Result:=GetEngineRegistration(AName).FCallBack;
  552. end;
  553. Function GetDictionaryEngineInfo(Const AName : String; out ADescription,ADBType: String;out ACapabilities : TFPDDEngineCapabilities) : boolean;
  554. Var
  555. DDEC : TFPDDEngineClass;
  556. begin
  557. DDEC:=FindDictionaryClass(AName);
  558. Result:=DDEC<>Nil;
  559. If Result then
  560. begin
  561. ADescription:=DDEC.Description;
  562. ADBType:=DDEC.DBType;
  563. ACapabilities:=DDEC.EngineCapabilities;
  564. end;
  565. end;
  566. function CreateDictionaryEngine(AName: String; AOWner : TComponent): TFPDDEngine;
  567. begin
  568. Result:=GetDictionaryClass(AName).Create(AOwner);
  569. end;
  570. function IndexOptionsToString(Options: TIndexOptions): String;
  571. Var
  572. IO : TIndexOption;
  573. begin
  574. Result:='';
  575. For IO:=Low(TIndexOption) to High(TIndexOption) do
  576. If IO in Options then
  577. begin
  578. If (Result<>'') then
  579. Result:=Result+',';
  580. Result:=Result+IndexOptionNames[IO];
  581. end;
  582. end;
  583. { ---------------------------------------------------------------------
  584. TDDFieldDef
  585. ---------------------------------------------------------------------}
  586. function TDDFieldDef.IsSizeStored: Boolean;
  587. begin
  588. Result:=FieldType in [ftUnknown, ftString, ftBCD,
  589. ftBytes, ftVarBytes, ftBlob, ftMemo, ftGraphic, ftFmtMemo,
  590. ftParadoxOle, ftDBaseOle, ftTypedBinary, ftFixedChar,
  591. ftWideString,ftArray, ftOraBlob, ftOraClob, ftFMTBcd];
  592. end;
  593. function TDDFieldDef.IsPrecisionStored: Boolean;
  594. begin
  595. Result:=FieldType in [ftFloat,ftBCD,ftFMTBCD];
  596. end;
  597. function TDDFieldDef.GetSectionName: String;
  598. begin
  599. Result:=FFieldName;
  600. end;
  601. procedure TDDFieldDef.SetSectionName(const Value: String);
  602. begin
  603. FFieldName:=Value;
  604. end;
  605. constructor TDDFieldDef.Create(ACollection: TCollection);
  606. begin
  607. Inherited;
  608. FVisible:=True;
  609. FAlignMent:=taLeftJustify;
  610. end;
  611. procedure TDDFieldDef.ImportFromField(F: TField; Existing : Boolean = True);
  612. begin
  613. FieldName:=F.FieldName;
  614. FieldType:=F.DataType;
  615. If IsSizeStored then
  616. Size:=F.Size;
  617. If IsPrecisionStored then
  618. begin
  619. If F is TBCDFIeld then
  620. Precision:=TBCDField(F).Precision
  621. else if F is TFloatField then
  622. Precision:=TFloatField(F).Precision;
  623. end;
  624. if not Existing then
  625. begin
  626. AlignMent:=F.AlignMent;
  627. DisplayWidth:=F.DisplayWidth;
  628. CustomConstraint:=F.CustomConstraint;
  629. ConstraintErrorMessage:=F.ConstraintErrorMessage;
  630. DefaultExpression:=F.DefaultExpression;
  631. DisplayLabel:=F.DisplayLabel;
  632. ReadOnly:=F.ReadOnly;
  633. Required:=F.Required;
  634. Visible:=F.Visible;
  635. end;
  636. end;
  637. procedure TDDFieldDef.ApplyToField(F: TField);
  638. begin
  639. { // Normally, these should never be assigned...
  640. F.FieldName := FieldName;
  641. F.DataType := FieldType;
  642. If IsSizeStored then
  643. F.Size:=Size;
  644. }
  645. F.AlignMent := AlignMent;
  646. F.DisplayWidth := DisplayWidth;
  647. F.CustomConstraint := CustomConstraint;
  648. F.ConstraintErrorMessage := ConstraintErrorMessage;
  649. F.DefaultExpression := DefaultExpression;
  650. F.DisplayLabel := DisplayLabel;
  651. F.ReadOnly := ReadOnly;
  652. F.Required := Required;
  653. F.Visible := Visible;
  654. end;
  655. procedure TDDFieldDef.Assign(Source: TPersistent);
  656. Var
  657. DF : TDDFieldDef;
  658. begin
  659. if Source is TField then
  660. ImportFromField(TField(Source))
  661. else If Source is TDDFieldDef then
  662. begin
  663. DF:=TDDFieldDef(Source);
  664. FieldType:=DF.FieldType;
  665. If IsSizeStored then
  666. Size:=DF.Size;
  667. AlignMent:=DF.AlignMent;
  668. DisplayWidth:=DF.DisplayWidth;
  669. CustomConstraint:=DF.CustomConstraint;
  670. ConstraintErrorMessage:=DF.ConstraintErrorMessage;
  671. DefaultExpression:=DF.DefaultExpression;
  672. DBDefault:=DF.DBDefault;
  673. DisplayLabel:=DisplayLabel;
  674. FieldName:=DF.FieldName;
  675. Constraint:=DF.Constraint;
  676. Hint:=DF.Hint;
  677. ReadOnly:=DF.ReadOnly;
  678. Required:=DF.Required;
  679. Visible:=DF.Visible;
  680. end
  681. else
  682. Inherited;
  683. end;
  684. procedure TDDFieldDef.SaveToIni(Ini: TCustomInifile; ASection: String);
  685. begin
  686. With Ini do
  687. begin
  688. WriteInteger(ASection,KeyFieldType,Ord(Fieldtype));
  689. If IsSizeStored then
  690. WriteInteger(ASection,KeySize,Size);
  691. If IsPrecisionStored then
  692. WriteInteger(ASection,KeyPrecision,Precision);
  693. WriteInteger(ASection,KeyAlignMent,Ord(AlignMent));
  694. WriteInteger(ASection,KeyDisplayWidth,DisplayWidth);
  695. WriteString(ASection,KeyCustomConstraint,CustomConstraint);
  696. WriteString(ASection,KeyConstraintErrorMessage,ConstraintErrorMessage);
  697. WriteString(ASection,KeyDefaultExpression,DefaultExpression);
  698. WriteString(ASection,KeyDBDefault,DBDefault);
  699. WriteString(ASection,KeyDisplayLabel,DisplayLabel);
  700. WriteString(ASection,KeyFieldName,FieldName);
  701. WriteString(ASection,KeyConstraint,Constraint);
  702. WriteString(ASection,KeyHint,Hint);
  703. WriteBool(ASection,KeyReadOnly,ReadOnly);
  704. WriteBool(ASection,KeyRequired,Required);
  705. WriteBool(ASection,KeyVisible,Visible);
  706. end;
  707. end;
  708. procedure TDDFieldDef.LoadFromIni(Ini: TCustomInifile; ASection: String);
  709. begin
  710. With Ini do
  711. begin
  712. FieldType:=TFieldType(ReadInteger(ASection,KeyFieldType,Ord(Fieldtype)));
  713. If IsSizeStored then
  714. Size:=ReadInteger(ASection,KeySize,0);
  715. If IsPrecisionStored then
  716. Precision:=ReadInteger(ASection,KeyPrecision,0);
  717. Alignment:=TAlignment(ReadInteger(ASection,KeyAlignMent,Ord(AlignMent)));
  718. DisplayWidth:=ReadInteger(ASection,KeyDisplayWidth,DisplayWidth);
  719. CustomConstraint:=ReadString(ASection,KeyCustomConstraint,CustomConstraint);
  720. ConstraintErrorMessage:=ReadString(ASection,KeyConstraintErrorMessage,ConstraintErrorMessage);
  721. DefaultExpression:=ReadString(ASection,KeyDefaultExpression,DefaultExpression);
  722. DBDefault:=ReadString(ASection,KeyDBDefault,DBDefault);
  723. DisplayLabel:=ReadString(ASection,KeyDisplayLabel,DisplayLabel);
  724. FieldName:=ReadString(ASection,KeyFieldName,FieldName);
  725. Constraint:=ReadString(ASection,KeyConstraint,Constraint);
  726. Hint:=ReadString(ASection,KeyHint,Hint);
  727. ReadOnly:=ReadBool(ASection,KeyReadOnly,ReadOnly);
  728. Required:=ReadBool(ASection,KeyRequired,Required);
  729. Visible:=ReadBool(ASection,KeyVisible,Visible);
  730. end;
  731. end;
  732. { ---------------------------------------------------------------------
  733. TDDFieldDefs
  734. ---------------------------------------------------------------------}
  735. procedure TDDFieldDefs.SetTableName(const AValue: String);
  736. begin
  737. FTableName:=AValue;
  738. FSectionPrefix:=AValue;
  739. GlobalSection:=AValue+SFieldSuffix;
  740. end;
  741. function TDDFieldDefs.GetField(Index : Integer): TDDFieldDef;
  742. begin
  743. Result:=TDDFieldDef(Items[Index]);
  744. end;
  745. procedure TDDFieldDefs.SetField(Index : Integer; const AValue: TDDFieldDef);
  746. begin
  747. Items[Index]:=AValue;
  748. end;
  749. constructor TDDFieldDefs.Create(ATableName: String);
  750. begin
  751. Inherited Create(TDDFieldDef);
  752. FPrefix:='Field';
  753. TableName:=ATableName;
  754. end;
  755. function TDDFieldDefs.AddField(AFieldName: String): TDDFieldDef;
  756. Var
  757. I : Integer;
  758. begin
  759. If (AFieldName<>'') and (IndexOfField(AFieldName)<>-1) then
  760. Raise EDataDict.CreateFmt(SErrDuplicateFieldName,[TableName,AFieldName]);
  761. If (AFieldName='') then
  762. begin
  763. I:=0;
  764. Repeat
  765. Inc(I);
  766. AFieldName:=SNewField+IntToStr(i);
  767. Until (IndexOfField(AFieldName)=-1);
  768. end;
  769. Result:=Add as TDDFieldDef;
  770. Result.FieldName:=AFieldName;
  771. end;
  772. function TDDFieldDefs.IndexOfField(AFieldName: String): Integer;
  773. begin
  774. Result:=Count-1;
  775. While (Result>=0) and (CompareText(GetField(Result).FieldName,AFieldName)<>0) do
  776. Dec(Result)
  777. end;
  778. function TDDFieldDefs.FindField(AFieldName: String): TDDFieldDef;
  779. Var
  780. I : integer;
  781. begin
  782. I:=IndexOfField(AFieldName);
  783. If (I=-1) then
  784. Result:=Nil
  785. else
  786. Result:=GetField(I);
  787. end;
  788. function TDDFieldDefs.FieldByName(AFieldName: String): TDDFieldDef;
  789. begin
  790. Result:=FindField(AFieldName);
  791. If Result=Nil then
  792. Raise EDatadict.CreateFmt(SErrFieldNotFound,[TableName,AFieldName]);
  793. end;
  794. { ---------------------------------------------------------------------
  795. TDDTableDef
  796. ---------------------------------------------------------------------}
  797. procedure TDDTableDef.SetTableName(const AValue: String);
  798. begin
  799. FTableName:=AValue;
  800. FFieldDefs.TableName:=AValue;
  801. end;
  802. function TDDTableDef.GetPrimaryKeyName: String;
  803. begin
  804. Result:=Tablename+'_PK';
  805. end;
  806. function TDDTableDef.GetOnProgress: TDDProgressEvent;
  807. begin
  808. Result:=Nil;
  809. If (Collection Is TDDTableDefs) then
  810. Result:=(Collection As TDDTableDefs).OnProgress;
  811. end;
  812. function TDDTableDef.GetSectionName: String;
  813. begin
  814. Result:=FTableName;
  815. end;
  816. procedure TDDTableDef.SetSectionName(const Value: String);
  817. begin
  818. TableName:=Value;
  819. end;
  820. constructor TDDTableDef.Create(ACollection: TCollection);
  821. begin
  822. inherited Create(ACollection);
  823. FFieldDefs:=TDDFieldDefs.Create('NewTable');
  824. FIndexDefs:=TDDIndexDefs.Create('NewTable');
  825. end;
  826. destructor TDDTableDef.Destroy;
  827. begin
  828. FreeAndNil(FFieldDefs);
  829. FreeAndNil(FIndexDefs);
  830. inherited Destroy;
  831. end;
  832. Function TDDTableDef.ImportFromDataset(Dataset: TDataSet; DoClear : Boolean = False; UpdateExisting : Boolean = True) : Integer;
  833. Var
  834. I : Integer;
  835. FD : TDDFieldDef;
  836. F : TField;
  837. FieldExists : Boolean;
  838. begin
  839. if DoClear then
  840. FFieldDefs.Clear;
  841. Result:=0;
  842. For I:=0 to Dataset.Fields.Count-1 do
  843. begin
  844. F:=Dataset.Fields[i];
  845. FD:=FFieldDefs.FindField(F.FieldName);
  846. If (FD=Nil) then
  847. begin
  848. FD:=FFieldDefs.AddField(F.FieldName);
  849. FieldExists := False;
  850. end
  851. else
  852. begin
  853. if not UpdateExisting then FD:=Nil;
  854. FieldExists := True;
  855. end;
  856. if (FD<>Nil) then
  857. begin
  858. Inc(Result);
  859. FD.ImportFromField(F,FieldExists);
  860. end;
  861. end;
  862. end;
  863. procedure TDDTableDef.ApplyToDataset(Dataset: TDataset);
  864. var
  865. I : integer;
  866. FD : TDDFieldDef;
  867. F : TField;
  868. begin
  869. For I:=0 to Dataset.FieldCount-1 do
  870. begin
  871. F:=Dataset.Fields[i];
  872. FD:=FFieldDefs.FieldByName(F.FieldName);
  873. If (FD<>Nil) then
  874. FD.ApplyToField(F);
  875. end;
  876. end;
  877. function TDDTableDef.AddField(AFieldName: String): TDDFieldDef;
  878. begin
  879. Result:=Fields.AddField(AFieldName);
  880. end;
  881. procedure TDDTableDef.SaveToIni(Ini: TCustomInifile; ASection: String);
  882. begin
  883. With Ini do
  884. begin
  885. WriteString(ASection,KeyTableName,TableName);
  886. WriteString(ASection,KeyPrimaryKeyConstraint,FPRimaryKeyName);
  887. end;
  888. If Assigned(OnProgress) then
  889. OnProgress(Self,Format(SSavingFieldsFrom,[TableName]));
  890. FFieldDefs.SaveToIni(Ini,ASection+SFieldSuffix);
  891. FIndexDefs.SaveToIni(Ini,ASection+SIndexSuffix);
  892. end;
  893. procedure TDDTableDef.LoadFromIni(Ini: TCustomInifile; ASection: String);
  894. begin
  895. With Ini do
  896. begin
  897. TableName:=ReadString(ASection,KeyTableName,TableName);
  898. FPrimaryKeyName:=ReadString(ASection,KeyPrimaryKeyConstraint,'');
  899. end;
  900. If Assigned(OnProgress) then
  901. OnProgress(Self,Format(SLoadingFieldsFrom,[TableName]));
  902. FFieldDefs.LoadFromIni(Ini,ASection+SFieldSuffix);
  903. FIndexDefs.LoadFromIni(Ini,ASection+SIndexSuffix);
  904. end;
  905. { ---------------------------------------------------------------------
  906. TDDTableDefs
  907. ---------------------------------------------------------------------}
  908. function TDDTableDefs.GetTable(Index : Integer): TDDTableDef;
  909. begin
  910. Result:=TDDTableDef(Items[Index]);
  911. end;
  912. procedure TDDTableDefs.SetTable(Index : Integer; const AValue: TDDTableDef);
  913. begin
  914. Items[Index]:=AValue;
  915. end;
  916. function TDDTableDefs.AddTable(ATableName: String): TDDTableDef;
  917. Var
  918. I : Integer;
  919. begin
  920. If (ATableName<>'') and (IndexOfTable(ATableName)<>-1) then
  921. Raise EDataDict.CreateFmt(SErrDuplicateTableName,[ATableName]);
  922. If (ATableName='') then
  923. begin
  924. I:=0;
  925. Repeat
  926. Inc(I);
  927. ATAbleName:=SNewTable+IntToStr(i);
  928. Until (IndexOfTable(ATableName)=-1);
  929. end;
  930. Result:=Add as TDDTableDef;
  931. Result.TableName:=ATableName;
  932. end;
  933. function TDDTableDefs.IndexOfTable(ATableName: String): Integer;
  934. begin
  935. Result:=Count-1;
  936. While (Result>=0) and (CompareText(GetTable(Result).TableName,ATableName)<>0) do
  937. Dec(Result)
  938. end;
  939. function TDDTableDefs.FindTable(ATableName: String): TDDTableDef;
  940. Var
  941. I : integer;
  942. begin
  943. I:=IndexOfTable(ATableName);
  944. If (I=-1) then
  945. Result:=Nil
  946. else
  947. Result:=GetTable(I);
  948. end;
  949. function TDDTableDefs.TableByName(ATableName: String): TDDTableDef;
  950. begin
  951. Result:=FindTable(ATableName);
  952. If Result=Nil then
  953. Raise EDatadict.CreateFmt(SErrTableNotFound,[ATableName]);
  954. end;
  955. { ---------------------------------------------------------------------
  956. TDatadictionary
  957. ---------------------------------------------------------------------}
  958. procedure TFPDataDictionary.SetOnProgress(const AValue: TDDProgressEvent);
  959. begin
  960. FOnProgress:=AValue;
  961. FTables.OnProgress:=FOnProgress;
  962. end;
  963. constructor TFPDataDictionary.Create;
  964. begin
  965. FTables:=TDDTableDefs.Create(TDDTableDef);
  966. end;
  967. destructor TFPDataDictionary.Destroy;
  968. begin
  969. FreeAndNil(FTables);
  970. inherited Destroy;
  971. end;
  972. procedure TFPDataDictionary.SaveToFile(AFileName: String; KeepBackup: Boolean = True);
  973. Var
  974. Ini : TMemIniFile;
  975. begin
  976. If (AFileName='') then
  977. AFileName:=FFileName;
  978. if (AFileName='') and (Name<>'') then
  979. AFileName:=Name+DefaultDDExt;
  980. if (AFileName='') then
  981. Raise EDataDict.Create(SErrNoFileName);
  982. If FileExists(AFileName) then
  983. If KeepBackup then
  984. RenameFile(AFileName,AFileName+'.bak')
  985. else
  986. DeleteFile(AFileName);
  987. Ini:=TMemIniFile.Create(AFileName);
  988. try
  989. SaveToIni(Ini,SDataDict);
  990. Ini.UpdateFile;
  991. FFileName:=AFileName;
  992. finally
  993. FreeAndNil(Ini);
  994. end;
  995. end;
  996. procedure TFPDataDictionary.SaveToIni(Ini: TCustomIniFile; ASection: String);
  997. begin
  998. Ini.WriteString(ASection,KeyDataDictName,Name);
  999. FTables.SaveToIni(Ini,SDatadictTables);
  1000. end;
  1001. procedure TFPDataDictionary.LoadFromFile(AFileName: String);
  1002. Var
  1003. Ini : TMemInifile;
  1004. begin
  1005. if (AFileName='') then
  1006. Raise EDataDict.Create(SErrNoFileName);
  1007. Ini:=TMemIniFile.Create(AFileName);
  1008. try
  1009. LoadFromIni(Ini,SDataDict);
  1010. FFileName:=AFileName;
  1011. If (Name='') then
  1012. Name:=ChangeFileExt(ExtractFileName(AFileName),'');
  1013. finally
  1014. FreeAndNil(Ini);
  1015. end;
  1016. end;
  1017. procedure TFPDataDictionary.LoadFromIni(Ini: TCustomIniFile; ASection: String);
  1018. begin
  1019. FDDName:=Ini.ReadString(ASection,KeyDataDictName,'');
  1020. FTables.Clear;
  1021. FTables.LoadFromIni(Ini,SDataDictTables);
  1022. end;
  1023. procedure TFPDataDictionary.ApplyToDataset(ADataset: TDataset);
  1024. begin
  1025. ApplytoDataset(ADataset,FOnApplyDatadictEvent);
  1026. end;
  1027. procedure TFPDataDictionary.ApplyToDataset(ADataset: TDataset;
  1028. OnApply: TOnApplyDataDictEvent);
  1029. Var
  1030. I : Integer;
  1031. F : TField;
  1032. FD : TDDFieldDef;
  1033. FN,TN : String;
  1034. Allow : Boolean;
  1035. begin
  1036. For I:=0 to ADataset.Fields.Count-1 do
  1037. begin
  1038. F:=ADataset.Fields[i];
  1039. FN:=F.Origin;
  1040. If (FN='') then
  1041. FN:=F.FieldName;
  1042. FD:=FindFieldDef(FN,TN);
  1043. Allow:=(FD<>Nil);
  1044. If Assigned(OnApply) then
  1045. OnApply(Self,FD,F,Allow);
  1046. If (FD<>Nil) and Allow then
  1047. FD.ApplyToField(F);
  1048. end;
  1049. end;
  1050. function TFPDataDictionary.CanonicalizeFieldName(const InFN: String; Out TableDef : TDDTableDef; Out FN: String): Boolean;
  1051. Var
  1052. TN : String;
  1053. P : integer;
  1054. begin
  1055. Result:=False;
  1056. FN:=InFN;
  1057. TableDef:=Nil;
  1058. // Improve to check for quotes
  1059. P:=Pos('.',FN);
  1060. If (P<>0) then
  1061. begin
  1062. TN:=Copy(FN,1,P-1);
  1063. Delete(FN,1,P);
  1064. TableDef:=Tables.FindTable(TN);
  1065. end;
  1066. Result:=TableDef<>Nil;
  1067. end;
  1068. Function TFPDataDictionary.CanonicalizeFieldName(Const InFN : String; Out TN,FN : String) : Boolean;
  1069. Var
  1070. TD : TDDTableDef;
  1071. begin
  1072. Result:=CanonicalizeFieldName(InFN,TD,FN);
  1073. If Result then
  1074. TN:=TD.TableName
  1075. else
  1076. TN:='';
  1077. end;
  1078. // To be good, we should make a hashlist with all tables.fields and search that...
  1079. // For now, we cache the last matching table. This should work well for most common cases.
  1080. function TFPDataDictionary.FindFieldDef(FieldName: String; out TableName: String
  1081. ): TDDFieldDef;
  1082. Var
  1083. TD : TDDTableDef;
  1084. FN,TN : String;
  1085. I : Integer;
  1086. begin
  1087. Result:=Nil;
  1088. If CanonicalizeFieldName(FieldName,TD,FN) then
  1089. begin
  1090. Result:=TD.Fields.FieldByName(FN);
  1091. If (Result<>Nil) then
  1092. FLastMatchTableDef:=TD;
  1093. end
  1094. else
  1095. begin
  1096. If (FLastMatchTableDef<>Nil) then
  1097. TD:=FLastMatchTableDef;
  1098. If (TD<>Nil) then
  1099. Result:=TD.Fields.FindField(FN);
  1100. If Result=Nil then
  1101. begin
  1102. // Hard scan of all tables...
  1103. I:=0;
  1104. While (Result=Nil) and (I<Tables.Count) do
  1105. begin
  1106. TD:=Tables[i];
  1107. Result:=TD.Fields.FindField(FN);
  1108. If (Result<>Nil) then
  1109. FLastMatchTableDef:=TD;
  1110. Inc(I);
  1111. end;
  1112. end;
  1113. end;
  1114. If (Result<>Nil) then
  1115. TableName:=FLastMatchTableDef.TableName;
  1116. end;
  1117. function TFPDataDictionary.FindFieldDef(FieldName: String): TDDFieldDef;
  1118. Var
  1119. Dummy : String;
  1120. begin
  1121. Result:=FindFieldDef(FieldName,Dummy);
  1122. end;
  1123. { ---------------------------------------------------------------------
  1124. TFPDDEngine
  1125. ---------------------------------------------------------------------}
  1126. procedure TFPDDEngine.DoProgress(const Msg: String);
  1127. begin
  1128. If Assigned(FOnProgress) then
  1129. FOnProgress(Self,Msg);
  1130. end;
  1131. procedure TFPDDEngine.IndexDefsToDDIndexDefs(IDS: TIndexDefs; DDIDS: TDDindexDefs
  1132. );
  1133. Var
  1134. D : TIndexDef;
  1135. DD : TDDindexDef;
  1136. I : Integer;
  1137. begin
  1138. DDIDS.Clear;
  1139. For I:=0 to IDS.Count-1 do
  1140. begin
  1141. D:=IDS[I];
  1142. DD:=DDIDS.AddDDIndexDef(D.Name);
  1143. DD.Assign(D);
  1144. end;
  1145. end;
  1146. destructor TFPDDEngine.Destroy;
  1147. begin
  1148. Disconnect;
  1149. inherited Destroy;
  1150. end;
  1151. function TFPDDEngine.GetConnectString: String;
  1152. Var
  1153. CB : TGetConnectionEvent;
  1154. begin
  1155. CB:=GetEngineConnectionStringCallBack(Self.ClassName);
  1156. if (CB=Nil) then
  1157. Raise EDataDict.CreateFmt(SerrNoConnectionDialog,[Self.ClassName]);
  1158. Result:='';
  1159. CB(Self,Result);
  1160. end;
  1161. function TFPDDEngine.ImportTables(Tables: TDDTableDefs; List: TStrings; UpdateExisting : Boolean): Integer;
  1162. Var
  1163. I,J : Integer;
  1164. TD : TDDTableDef;
  1165. begin
  1166. Result:=0;
  1167. For I:=0 to List.Count-1 do
  1168. begin
  1169. TD:=Nil;
  1170. j:=Tables.IndexOfTable(List[i]);
  1171. If (J=-1) then
  1172. TD:=Tables.AddTAble(List[i])
  1173. else if UpdateExisting then
  1174. TD:=Tables[J];
  1175. If (TD<>nil) then
  1176. begin
  1177. DoProgress(Format(SDDImportingTable,[TD.TableName]));
  1178. ImportFields(TD);
  1179. Inc(Result);
  1180. end
  1181. end;
  1182. end;
  1183. function TFPDDEngine.CreateSQLEngine: TFPDDSQLEngine;
  1184. begin
  1185. Result:=TFPDDSQLEngine.Create;
  1186. end;
  1187. class function TFPDDEngine.EngineCapabilities: TFPDDEngineCapabilities;
  1188. begin
  1189. Result:=[];
  1190. end;
  1191. procedure TFPDDEngine.CreateTable(Table: TDDTableDef);
  1192. begin
  1193. Raise EDataDict.CreateFmt(SErrCreateTableNotSupported,[DBType]);
  1194. end;
  1195. function TFPDDEngine.ViewTable(Const TableName: String; DatasetOwner: TComponent
  1196. ): TDataset;
  1197. begin
  1198. Raise EDataDict.CreateFmt(SErrViewTableNotSupported,[DBType]);
  1199. end;
  1200. function TFPDDEngine.RunQuery(SQL: String): Integer;
  1201. begin
  1202. Raise EDataDict.CreateFmt(SErrRunQueryNotSupported,[DBType]);
  1203. end;
  1204. function TFPDDEngine.CreateQuery(SQL: String; DatasetOwner : TComponent): TDataset;
  1205. begin
  1206. Raise EDataDict.CreateFmt(SErrOpenQueryNotSupported,[DBType]);
  1207. end;
  1208. procedure TFPDDEngine.SetQueryStatement(SQL: String; AQuery: TDataset);
  1209. begin
  1210. Raise EDataDict.CreateFmt(SErrSetQueryStatementNotSupported,[DBType]);
  1211. end;
  1212. function TFPDDEngine.GetTableIndexDefs(ATableName: String; Defs: TDDIndexDefs
  1213. ): integer;
  1214. begin
  1215. Raise EDataDict.CreateFmt(SErrGetTableIndexDefsNotSupported,[DBType]);
  1216. end;
  1217. { ---------------------------------------------------------------------
  1218. TFPDDSQLEngine
  1219. ---------------------------------------------------------------------}
  1220. { Utility functions }
  1221. constructor TFPDDSQLEngine.Create;
  1222. begin
  1223. FTerminatorChar:=DefaultSQLTerminatorChar;
  1224. FFieldQuoteChar:=DefaultSQLFieldQuoteChar;
  1225. FOptions:=DefaultSQLEngineOptions;
  1226. FMaxLineLength:=DefaultSQLEngineLineLength;
  1227. FIndent:=DefaultSQLEngineIndent;
  1228. end;
  1229. procedure TFPDDSQLEngine.CheckTableDef;
  1230. begin
  1231. If (FTableDef=Nil) then
  1232. Raise EDataDict.Create(SErrMissingTableDef);
  1233. end;
  1234. procedure TFPDDSQLEngine.NoIndent;
  1235. begin
  1236. FNoIndent:=True;
  1237. end;
  1238. procedure TFPDDSQLEngine.ResetLine;
  1239. begin
  1240. FLastLength:=0;
  1241. NoIndent;
  1242. end;
  1243. procedure TFPDDSQLEngine.FixUpStatement(var Res: String);
  1244. begin
  1245. Res:=Trim(Res);
  1246. if (eoAddTerminator in Options) then
  1247. Res:=Res+FTerminatorChar;
  1248. end;
  1249. Procedure TFPDDSQLEngine.AddToStringLN(Var Res : String;S : String);
  1250. begin
  1251. AddToString(Res,S);
  1252. Res:=Res+LineEnding;
  1253. FLastLength:=0;
  1254. end;
  1255. procedure TFPDDSQLEngine.AddToString(Var Res: String; S: String);
  1256. begin
  1257. If (FMaxLineLength>0) and (FLastLength+Length(S)+1>FMaxLineLength) then
  1258. begin
  1259. FLastLength:=0;
  1260. Res:=Res+LineEnding;
  1261. end
  1262. else If (FLastLength<>0) and (S<>'') then
  1263. S:=' '+S;
  1264. If (FLastlength=0) then
  1265. begin
  1266. If not FNoIndent then
  1267. begin
  1268. Res:=Res+StringOfChar(' ',Indent);
  1269. FLastlength:=FlastLength+Indent;
  1270. end;
  1271. end;
  1272. FLastLength:=FLastLength+Length(S);
  1273. FNoIndent:=False;
  1274. Res:=Res+S;
  1275. end;
  1276. procedure TFPDDSQLEngine.AddFieldString(var Res: String; S: String);
  1277. begin
  1278. If eoLineFeedAfterField in FOptions then
  1279. AddToStringLn(Res,S)
  1280. else
  1281. AddToString(Res,S)
  1282. end;
  1283. function TFPDDSQLEngine.CreateAndTerm(FD: TDDFieldDef; UseOldParam: Boolean
  1284. ): string;
  1285. begin
  1286. Result:=FieldNameString(FD)+' = '+FieldParamString(FD,UseOldParam);
  1287. if (eoAndTermsInBrackets in FOptions) then
  1288. Result:='('+Result+')';
  1289. end;
  1290. function TFPDDSQLEngine.CreateWhereSQL(var Res : String;FieldList: TFPDDFieldList; UseOldParam:Boolean): String;
  1291. Var
  1292. i : Integer;
  1293. FD : TDDFieldDef;
  1294. S : String;
  1295. begin
  1296. Result:='';
  1297. If Assigned(FieldList) and (FieldList.Count>0) then
  1298. begin
  1299. For i:=0 to FieldList.Count-1 do
  1300. begin
  1301. FD:=FieldList[i];
  1302. S:=CreateAndTerm(FD,UseOldParam);
  1303. If (I>0) then
  1304. S:=SAnd+' '+S;
  1305. If eoLineFeedAfterAndTerm in Options then
  1306. AddToStringLN(Res,S)
  1307. else
  1308. AddToString(Res,S);
  1309. end;
  1310. end;
  1311. end;
  1312. procedure TFPDDSQLEngine.AddWhereClause(var Res: String;
  1313. FieldList: TFPDDFieldList; UseOldParam: Boolean);
  1314. begin
  1315. If Assigned(FieldList) and (FieldList.Count>0) then
  1316. begin
  1317. NoIndent;
  1318. AddToStringLn(Res,SWhere);
  1319. CreateWhereSQL(Res,FieldList,UseOldParam);
  1320. end;
  1321. end;
  1322. { Functions with engine-specific strings in it. Can be overridden }
  1323. function TFPDDSQLEngine.FieldNameString(FD: TDDFieldDef): string;
  1324. begin
  1325. Result:=FD.FieldName;
  1326. if (eoQuoteFieldNames in FOptions) then
  1327. Result:=FFieldQuoteChar+Result+FFieldQuoteChar;
  1328. end;
  1329. function TFPDDSQLEngine.TableNameString(TD: TDDTableDef): string;
  1330. begin
  1331. Result:=TD.TableName;
  1332. end;
  1333. function TFPDDSQLEngine.FieldParamString(FD: TDDFieldDef; UseOldParam: Boolean
  1334. ): string;
  1335. begin
  1336. Result:=FD.FieldName;
  1337. If UseOldParam then
  1338. Result:=SOLD+Result;
  1339. Result:=':'+Result;
  1340. end;
  1341. function TFPDDSQLEngine.FieldTypeString(FD : TDDFieldDef) : String;
  1342. {
  1343. ftUnknown, ftString, ftSmallint, ftInteger, ftWord,
  1344. ftBoolean, ftFloat, ftCurrency, ftBCD, ftDate, ftTime, ftDateTime,
  1345. ftBytes, ftVarBytes, ftAutoInc, ftBlob, ftMemo, ftGraphic, ftFmtMemo,
  1346. ftParadoxOle, ftDBaseOle, ftTypedBinary, ftCursor, ftFixedChar,
  1347. ftWideString, ftLargeint, ftADT, ftArray, ftReference,
  1348. ftDataSet, ftOraBlob, ftOraClob, ftVariant, ftInterface,
  1349. ftIDispatch, ftGuid, ftTimeStamp, ftFMTBcd}
  1350. begin
  1351. Result:=SQLFieldTypes[fD.FieldType];
  1352. If (Result='') then
  1353. Raise EDataDict.CreateFmt(SErrFieldTypeNotSupported,[GetEnumName(TypeInfo(TFieldType),Ord(FD.FieldType))]);
  1354. case FD.FieldType of
  1355. ftString,
  1356. ftFixedChar,
  1357. ftWideString :
  1358. Result:=Result+Format('(%d)',[FD.Size]);
  1359. ftBCD,
  1360. ftFMTBCD :
  1361. Result:=Result+Format('(%d,%d)',[FD.Size,FD.Precision]);
  1362. end;
  1363. end;
  1364. function TFPDDSQLEngine.FieldDefaultString(FD : TDDFieldDef) : String;
  1365. begin
  1366. Result:=SDefault+' '+FD.DBDefault;
  1367. end;
  1368. function TFPDDSQLEngine.FieldCheckString(FD : TDDFieldDef) : String;
  1369. begin
  1370. Result:=Trim(FD.Constraint);
  1371. If (Result<>'') then
  1372. begin
  1373. If (Result[1]<>'(') or (Result[Length(Result)]<>')') then
  1374. Result:='('+Result+')';
  1375. Result:=SCheck+' '+Result;
  1376. end;
  1377. end;
  1378. function TFPDDSQLEngine.FieldDeclarationString(FD : TDDFieldDef) : String;
  1379. var
  1380. S : String;
  1381. begin
  1382. Result:=FieldNameString(FD)+' '+FieldTypeString(FD);
  1383. If (FD.DBDefault<>'') then
  1384. Result:=Result+' '+FieldDefaultString(FD);
  1385. If FD.Required then
  1386. Result:=Result+' '+SNotNull;
  1387. S:=FieldCheckString(FD);
  1388. If (S<>'') then
  1389. Result:=Result+' '+S;
  1390. end;
  1391. { SQL Creation functions. Can be overridden if needed. }
  1392. function TFPDDSQLEngine.CreateSelectSQL(FieldList, KeyFields: TFPDDFieldList
  1393. ): String;
  1394. Var
  1395. i : Integer;
  1396. FD : TDDFieldDef;
  1397. S : String;
  1398. begin
  1399. CheckTableDef;
  1400. Result:='';
  1401. ResetLine;
  1402. AddToStringLn(Result,SSelect);
  1403. For i:=0 to FieldList.Count-1 do
  1404. begin
  1405. FD:=FieldList[i];
  1406. S:=FieldNameString(FD);
  1407. If (I<FieldList.Count-1) then
  1408. S:=S+',';
  1409. AddFieldString(Result,S);
  1410. end;
  1411. If Not (eoLineFeedAfterField in FOptions) then
  1412. AddToStringLn(Result,'');
  1413. NoIndent;
  1414. AddToStringLn(Result,SFrom);
  1415. AddToStringLn(Result,TableNameString(TableDef));
  1416. AddWhereClause(Result,KeyFields,False);
  1417. FixUpStatement(Result);
  1418. end;
  1419. function TFPDDSQLEngine.CreateInsertSQL(FieldList: TFPDDFieldList): String;
  1420. Var
  1421. i : Integer;
  1422. FD : TDDFieldDef;
  1423. S : String;
  1424. begin
  1425. CheckTableDef;
  1426. Result:='';
  1427. ResetLine;
  1428. AddToString(Result,SInsertInto);
  1429. AddToStringLn(Result,TableNameString(TableDef));
  1430. For i:=0 to FieldList.Count-1 do
  1431. begin
  1432. FD:=FieldList[i];
  1433. S:=FieldNameString(FD);
  1434. If (I=0) then
  1435. S:='('+S;
  1436. If (I<FieldList.Count-1) then
  1437. S:=S+','
  1438. else
  1439. S:=S+')';
  1440. AddFieldString(Result,S);
  1441. end;
  1442. If Not (eoLineFeedAfterField in FOptions) then
  1443. AddToStringLn(Result,'');
  1444. NoIndent;
  1445. AddToStringLn(Result,SValues);
  1446. For i:=0 to FieldList.Count-1 do
  1447. begin
  1448. FD:=FieldList[i];
  1449. S:=FieldParamString(FD,False);
  1450. If (I=0) then
  1451. S:='('+S;
  1452. If (I<FieldList.Count-1) then
  1453. S:=S+','
  1454. else
  1455. S:=S+')';
  1456. AddFieldString(Result,S);
  1457. end;
  1458. FixUpStatement(Result);
  1459. end;
  1460. function TFPDDSQLEngine.CreateUpdateSQL(FieldList, KeyFields: TFPDDFieldList
  1461. ): String;
  1462. Var
  1463. i : Integer;
  1464. FD : TDDFieldDef;
  1465. S : String;
  1466. begin
  1467. CheckTableDef;
  1468. ResetLine;
  1469. Result:='';
  1470. AddToString(Result,SUPDATE);
  1471. AddToStringLN(Result,TableNameString(TableDef));
  1472. NoIndent;
  1473. AddToStringLN(Result,SSET);
  1474. If Assigned(FieldList) and (FieldList.Count>0) then
  1475. begin
  1476. For i:=0 to FieldList.Count-1 do
  1477. begin
  1478. FD:=FieldList[i];
  1479. S:=FieldNameString(FD)+' = '+FieldParamString(FD,False);
  1480. If (I<FieldList.Count-1) then
  1481. S:=S+',';
  1482. AddFieldString(Result,S);
  1483. end;
  1484. end;
  1485. AddWhereClause(Result,KeyFields,eoUseOldInWhereParams in Options);
  1486. FixUpStatement(Result);
  1487. end;
  1488. function TFPDDSQLEngine.CreateDeleteSQL(KeyFields: TFPDDFieldList): String;
  1489. begin
  1490. CheckTableDef;
  1491. ResetLine;
  1492. Result:='';
  1493. AddToStringLN(Result,SDeleteFrom);
  1494. AddToStringLN(Result,TableNameString(TableDef));
  1495. AddWhereClause(Result,KeyFields,eoUseOldInWhereParams in Options);
  1496. FixUpStatement(Result);
  1497. end;
  1498. function TFPDDSQLEngine.CreateCreateSQL(Fields, KeyFields: TFPDDFieldList
  1499. ): String;
  1500. Var
  1501. S : String;
  1502. I : integer;
  1503. begin
  1504. CheckTableDef;
  1505. Result:='';
  1506. ResetLine;
  1507. AddToStringLn(Result,SCreateTable+' '+TableNameString(TableDef)+' (');
  1508. For I:=0 to Fields.Count-1 do
  1509. begin
  1510. S:=FieldDeclarationString(Fields[i]);
  1511. If (I<Fields.Count-1) or (Assigned(KeyFields) and (KeyFields.Count<>0)) then
  1512. S:=S+',';
  1513. AddToStringLn(Result,S);
  1514. end;
  1515. If (Assigned(KeyFields) and (KeyFields.Count<>0)) then
  1516. begin
  1517. S:=SCONSTRAINT+' '+TableDef.PrimaryKeyConstraintName+' '+SPrimaryKey+' (';
  1518. For I:=0 to KeyFields.Count-1 do
  1519. begin
  1520. S:=S+FieldNameString(KeyFields[i]);
  1521. If I<KeyFields.Count-1 then
  1522. S:=S+','
  1523. else
  1524. S:=S+')'
  1525. end;
  1526. AddToStringLn(Result,S);
  1527. end;
  1528. NoIndent;
  1529. AddToStringLn(Result,')');
  1530. FixUpStatement(Result);
  1531. end;
  1532. function TFPDDSQLEngine.CreateCreateSQL(KeyFields: TFPDDFieldList): String;
  1533. Var
  1534. Fl : TFPDDFieldList;
  1535. begin
  1536. CheckTableDef;
  1537. FL:=TFPDDfieldList.CreateFromTableDef(TableDef);
  1538. try
  1539. Result:=CreateCreateSQL(FL,KeyFields);
  1540. finally
  1541. FL.Free;
  1542. end;
  1543. end;
  1544. { TStrings versions of SQL creation statements. }
  1545. procedure TFPDDSQLEngine.CreateSelectSQLStrings(FieldList,KeyFields: TFPDDFieldList; SQL: TStrings);
  1546. begin
  1547. SQL.Text:=CreateSelectSQL(FieldList,KeyFields);
  1548. end;
  1549. procedure TFPDDSQLEngine.CreateInsertSQLStrings(FieldList: TFPDDFieldList; SQL: TStrings);
  1550. begin
  1551. SQL.Text:=CreateInsertSQL(FieldList);
  1552. end;
  1553. procedure TFPDDSQLEngine.CreateUpdateSQLStrings(FieldList, KeyFields: TFPDDFieldList;
  1554. SQL: TStrings);
  1555. begin
  1556. SQL.Text:=CreateUpdateSQL(FieldList,KeyFields);
  1557. end;
  1558. procedure TFPDDSQLEngine.CreateDeleteSQLStrings(KeyFields: TFPDDFieldList;
  1559. SQL: TStrings);
  1560. begin
  1561. SQL.Text:=CreateDeleteSQL(KeyFields);
  1562. end;
  1563. procedure TFPDDSQLEngine.CreateCreateSQLStrings(Fields,
  1564. KeyFields: TFPDDFieldList; SQL: TStrings);
  1565. begin
  1566. SQL.Text:=CreateCreateSQL(Fields,KeyFields);
  1567. end;
  1568. procedure TFPDDSQLEngine.CreateCreateSQLStrings(KeyFields: TFPDDFieldList;
  1569. SQL: TStrings);
  1570. begin
  1571. SQL.Text:=CreateCreateSQL(KeyFields);
  1572. end;
  1573. { ---------------------------------------------------------------------
  1574. TDDFieldList
  1575. ---------------------------------------------------------------------}
  1576. function TFPDDFieldList.GetFieldDef(Index : Integer): TDDFieldDef;
  1577. begin
  1578. Result:=TDDFieldDef(Items[Index]);
  1579. end;
  1580. procedure TFPDDFieldList.SetFieldDef(Index : Integer; const AValue: TDDFieldDef);
  1581. begin
  1582. Items[Index]:=AValue;
  1583. end;
  1584. constructor TFPDDFieldList.CreateFromTableDef(TD: TDDTableDef);
  1585. begin
  1586. CreateFromFieldDefs(TD.Fields);
  1587. end;
  1588. constructor TFPDDFieldList.CreateFromFieldDefs(FD: TDDFieldDefs);
  1589. Var
  1590. I : Integer;
  1591. begin
  1592. Inherited Create;
  1593. Capacity:=FD.Count;
  1594. For I:=0 to FD.Count-1 do
  1595. Add(FD[i]);
  1596. end;
  1597. { TDDIndexDef }
  1598. function TDDIndexDef.GetSectionName: String;
  1599. begin
  1600. Result:=IndexName;
  1601. end;
  1602. procedure TDDIndexDef.SetSectionName(const Value: String);
  1603. begin
  1604. IndexName:=Value;
  1605. end;
  1606. procedure TDDIndexDef.Assign(ASource: TPersistent);
  1607. Var
  1608. DD : TDDIndexDef;
  1609. D : TIndexDef;
  1610. begin
  1611. If ASource is TDDIndexDef then
  1612. begin
  1613. DD:=ASource as TDDIndexDef;
  1614. IndexName:=DD.IndexName;
  1615. Expression:=DD.Expression;
  1616. Fields:=DD.Expression;
  1617. CaseInsFields:=DD.CaseInsFields;
  1618. DescFields:=DD.DescFields;
  1619. Options:=DD.Options;
  1620. Source:=DD.Source;
  1621. end
  1622. else if ASource is TIndexDef then
  1623. begin
  1624. D:=ASource as TIndexDef;
  1625. IndexName:=D.Name;
  1626. Expression:=D.Expression;
  1627. Fields:=D.Fields;
  1628. CaseInsFields:=D.CaseInsFields;
  1629. DescFields:=D.DescFields;
  1630. Options:=D.Options;
  1631. Source:=D.Source;
  1632. end
  1633. else
  1634. inherited Assign(ASource);
  1635. end;
  1636. { TDDIndexDefs }
  1637. function TDDIndexDefs.GetIndex(Index : Integer): TDDIndexDef;
  1638. begin
  1639. Result:=Items[Index] as TDDIndexDef;
  1640. end;
  1641. procedure TDDIndexDefs.SetIndex(Index : Integer; const AValue: TDDIndexDef);
  1642. begin
  1643. Items[Index]:=AValue;
  1644. end;
  1645. procedure TDDIndexDefs.SetTableName(const AValue: String);
  1646. begin
  1647. FTableName:=AValue;
  1648. FSectionPrefix:=AValue;
  1649. GlobalSection:=AValue+SIndexSuffix;
  1650. end;
  1651. constructor TDDIndexDefs.Create(ATableName: String);
  1652. begin
  1653. FPrefix:='Index';
  1654. TableName:=ATableName;
  1655. Inherited Create(TDDIndexDef);
  1656. end;
  1657. function TDDIndexDefs.AddDDIndexDef(AName: String): TDDIndexDef;
  1658. begin
  1659. Result:=Add as TDDIndexDef;
  1660. Result.IndexName:=AName;
  1661. end;
  1662. initialization
  1663. finalization
  1664. if assigned(DDEngines) then FreeAndNil(DDEngines);
  1665. end.