incompatible property * for type *

hu_huiqin 2011-05-01 10:48:52
如何查询PB中一个对象所拥有的属性,避免产生这类问题:incompatible property postion for type hsb_1

这类问题我遇到好几次了,想要能看到一个控件所拥有的属性,不知做不做得到?
为了避免我在别的方面犯错导致产生问题,浪费大家时间。我把窗口的timer事件代码贴这里,便于大家参考
if direct=1 //表示向右拉滚动条
then
hsb_1.position=hsb_1.position+1 //1
else
hsb_1.positon=hsb_1.position - 1 //2
end if
if hsb_1.position>hsb_1.maxposition then
hsb_1.position=hsb_1.maxpositon //3
direct= -1
end if
if hsb_1.position<hsb_1.minposition then
hsb_1.position=hsb_1.minpositon //4这几个地方是指出incompatible的地方
direct= 1
end if
hsb_1.triggerevent("moved")
...全文
1328 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
Samoon 2011-05-25
  • 打赏
  • 举报
回复
无语..............position maxposition minposition
hsb_1.positon=hsb_1.position - 1 //2
hsb_1.position=hsb_1.maxpositon //3
hsb_1.position=hsb_1.minpositon //4这几个地方是指出incompatible的地方

麻烦下次用ctrl+ H来对比一下
hu_huiqin 2011-05-15
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 samoon 的回复:]
老大,你拼写错误。少了个i---- ition. 浪费表情阿,害我还开个工程来试。加分 加分
[/Quote]
我没有少i啊
Samoon 2011-05-10
  • 打赏
  • 举报
回复
老大,你拼写错误。少了个i---- ition. 浪费表情阿,害我还开个工程来试。加分 加分
hu_huiqin 2011-05-08
  • 打赏
  • 举报
回复
大家好,我看过了。hscrollbar里确实有position ,minposition and maxposition 属性, 现在更是不明白他为什么给我报错:imcompatible了
yyoinge 2011-05-04
  • 打赏
  • 举报
回复
在菜单 Tools → Browser... 中打开 Browser 界面,在System页面中列出所有系统对象,单击相应的系统对象,在右边会列出 Properties、Events、Functinos 等信息,展开相应的信息即可看到
Samoon 2011-05-03
  • 打赏
  • 举报
回复
多用F10 熟悉各种控件的成员函数。或者直接看控件的成员列表
yejihui9527 2011-05-03
  • 打赏
  • 举报
回复
hsb_1这种控件没有maxpositon和minposition属性 貌似
hu_huiqin 2011-05-02
  • 打赏
  • 举报
回复
我勾上了,但还是不行。还是告诉我position .maxposition .minposition 都是对于hab_1类型incompatible
wag_enu 2011-05-02
  • 打赏
  • 举报
回复
打开一个窗口对象,选择菜单:Design -> Options

选择AutoScript 标签,勾选里面的所有选项,特别是最后两项,
可以打开编写代码时的自动提醒功能。
****************************** * 编 译 错 误 信 息 * ******************************* '''';'''' not allowed before ''''ELSE'''' ElSE前不允许有“;” '''''''' clause not allowed in OLE automation section 在OLE自动区段不允许“”子句 '''''''' is not a type identifier 不是类型标识符 '''''''' not previously declared as a PROPERTY 前面没有说明PROPERTY ''''GOTO '''' leads into or out of TRY statement GOTO 进入或超出TRY语句的范围 clause expected, but found 要求子句,但出现 16-Bit fixup encountered in object file '''''''' 在对象文件遇到16位修复 486/487 instructions not enabled 不能用486/487指令 Abstract methods must be virtual or dynamic 抽象方法必须为虚拟的或动态的 Array type required 需要数组类型 Assignment to FOR-Loop variable '''''''' 给FOR循环变量赋值 Bad argument type in variable type array constructor 在变量类型数组结构中不正确的参数类型 Bad file format '''''''' 错误的文件格式 Bad file format: 错误的文件格式 Bad global symbol definition: '''''''' in object file '''''''' 对象文件''''''''中错误的全局符号定义'''''''' Bad unit format: 错误的单元格式 BREAK or CONTINUE outside of loop BREAK或CONTINUE超出循环 Cannot add or subtract relocatable symbols 不能增加或减少可重置的符号 Cannot assign to a read-only property 不能指定只读属性 Cannot BREAK, CONTINUE or EXIT out of a FINALLY clause 超出FINALLY子句的范围,不能使用BREAK,CONTINUE或EXIT语句 Cannot initialize local variables 不能初始化局部变量 Cannot initialize multiple variables 不能初始化多个变量 Cannot initialize thread local variables 不能初始化线程局部变量 Cannot override a static method 不能覆盖静态方法 Cannot read a write-only property 不能读取只写属性 Case label outside of range of case expression CASE标号超出了CASE表达式的范围 Circular unit reference to 对单元循环引用 Class already has a default property 类已具有默认的属性 Class does not have a default property 类没有默认的属性 Class or object types only allowed in type section 在类型区段只允许有类或对象类型 Class type required 需要类类型 Close error on 文件关闭错误 Compile terminated by user 用户中止编译 Constant expected 要求常量 Constant expression expected 要求常量表达式 Constant expression violates subrange bounds 常量表达式超出子界范围 Constant object cannot be passed as var parameter 常量对象不能作为变量参数传递 Constant or type identifier expected 要求常量或类型标识符 Constants cannot be used as open array arguments 常量不能用作打开数组参数 Constructing instance of '''''''' containing abstract methods 构造的实体包含抽象的方法 Could not compile used unit '''''''' 不能用单元编译 Could not create output file 不能建立输出文件 Could not load RLINK32.DLL 不能加载RLINK32.DLL Data type too large: exceeds 2 GB 数据类型太大:超过2GB Declaration of differs from previous declaration 的说明与先前的说明不同 Default property must be an array property 默认的属性必须为数组属性 Default values must be of ordinal, pointer or small set type 默认的值必须为序数、指针或小集类型 Destination cannot be assigned to 目标不能指定 Destination is inaccessible 目标不能存取 Dispid '''''''' already used by '''''''' DISPID标识号已被使用 Dispid clause only allowed in OLE automation section DISPID子句只能在OLE自动区段中使用 Division by zero 除数为零 Duplicate case label CASE标号重复 Duplicate tag value 重复的标志值 Dynamic method or message handler not allowed here 这里不允许有动态方法或信息处理程序 Dynamic methods and message handlers not allowed in OLE automation section在OLE自动区段不允许有动态方法或消息处理程序 Element 0 inaccessible - use ''''Length'''' or ''''SetLength'''' 元素0不能存取-使用LENGTH或SETLENGTH Error in numeric constant 数值常量错误 EXCEPT or FINALLY expected 要求EXCEPT或FINALLY EXPORTS allowed only at global scope EXPORTS只允许在全局范围使用 Expression has no value 表达式没有值 Expression too complicated 表达式太复杂 Field definition not allowed in OLE automation section 在OLE自动区段中不允许域定义 Field definition not allowed after methods or properties 在方法或属性后不允许域定义 Field or method identifier expected 要求域或方法标识符 File not found: 文件没有找到 File type not allowed here 这儿不允许文件类型 For loop control variable must be simple local variable FOR循环控制变量必须为简单局部变量 For loop control variable must have ordinal type FOR循环控制变量必须为序数类型 FOR or WHILE loop executes zero times - deleted FOR或WHILE循环执行零次-删除 FOR-Loop variable '''''''' cannot be passed as var parameter FOR循环变量不能作为参数传递 FOR-Loop variable '''''''' may be undefined after loop 在循环后的FOR循环变量是不确定的 Function needs result type 函数需要结果类型 Identifier redeclared: '''''''' 标识符重复说明 Illegal character in input file: '''''''' ($) 在输入文件中的非法字符'''''''' Illegal message method index 非法的消息方法指针 Illegal reference to symbol '''''''' in object file '''''''' 在对象文件中对符号的非法引用 Illegal type in OLE automation section: '''''''' 在OLE自动区段中的非法类型 Illegal type in Read/Readln statement 在Read/Readln语句中的非法类型 Illegal type in Write/Writeln statement 在Write/Writeln语句中的非法类型 Inaccessible value 不可存取的值 Incompatible types: '''''''' and '''''''' 不兼容的类型和 Incompatible types: 不兼容的类型 Inline assembler stack overflow 内联汇编溢出 Inline assembler syntax error 内联汇编语法错误 Instance variable '''''''' inaccessible here 实体变量在这里不能存取
Drag and Drop Component Suite Version 4.1 Field test 5, released 16-dec-2001 ?1997-2001 Angus Johnson & Anders Melander http://www.melander.dk/delphi/dragdrop/ ------------------------------------------- Table of Contents: ------------------------------------------- 1. Supported platforms 2. Installation 3. Getting started 4. Known problems 5. Support and feedback 6. Bug reports 7. Upgrades and bug fixes 8. Missing in this release 9. New in version 4.x 10. TODO 11. Licence, Copyright and Disclaimer 12. Release history ------------------------------------------- 1. Supported platforms: ------------------------------------------- This release supports Delphi 4-6 and C++ Builder 4-5. Earlier versions of Delphi and C++ Builder will not be supported. If you need Delphi 3 or C++ Builder 3 support you will have to revert to version 3.7 of the Drag and Drop Component Suite. The library has been tested on NT4 service pack 5 and Windows 2000. Windows 95, 98, ME and XP should be supported, but has not been tested. Linux and Kylix are not supported. There are *NO* plans to port the library to Kylix. The drag and drop protocols available on Linux are too much of a mess at this time. ------------------------------------------- 2. Installation: ------------------------------------------- 1) Before you do anything else, read the "Known problems" section of this document. 2) Install the source into a directory of your choice. The files are installed into three directories: DragDrop DragDrop\Components DragDrop\Demo 3) Install and compile the appropriate design time package. The design time packages are located in the Components directory. Each version of Delphi and C++ Builder has its own package; DragDropD6.dpk for Delphi 6, DragDropD5.dpk for Delphi 5, DragDropC5.bpk for C++ Builder 5, etc. 4) Add the Drag and Drop Component Suite components directory to your library path. 5) Load the demo project group: demo\dragdrop_delphi.bpg for Delphi 5 and 6 demo\dragdrop_bcb4.bpg for C++ Builder 4 demo\dragdrop_bcb5.bpg for C++ Builder 5 The project group contains all the demo applications. 6) If your version of Delphi does not support text format DFM files (e.g. Delphi 4 doesn't), you will have to use the convert.exe utility supplied with Delphi to convert all the demo form files to binary format. A batch file, convert_forms_to delphi_4_format.bat, is supplied in the demo directory which automates the conversion process. The C++ Builder demo forms are distributed in binary format. 7) If upgrading from a previous version of the Drag and Drop Component Suite, please read the document "upgrading_to_v4.txt" before you begin working on your existing projects. Note about "Property does not exist" errors: Since all demos were developed with the latest version of Delphi, most of the demo forms probably contains references to properties that doesn't exist in earlier versions of Delphi and C++ Builder. Because of this you will get fatal run-time errors (e.g. "Error reading blahblahblah: Property does not exist.") if you attemt to run the demos without fixing this problem. Luckily it is very easy to make the forms work again; Just open the forms in the IDE, then select "Ignore All" when the IDE complains that this or that property doesn't exist and finally save the forms. ------------------------------------------- 3. Getting started: ------------------------------------------- It is recommended that you start by running each of the demo applications and then look through the demo source. Each demo application is supplied with a readme.txt file which briefly describes what the demo does and what features it uses. The demos should be run in the order in which they are listed in the supplied project group. Even if you have used previous versions of the Drag and Drop Component Suite it would be a good idea to have a quick look at the demos. The library has been completely rewritten and a lot of new features has been added. ------------------------------------------- 4. Known problems: ------------------------------------------- * The Shell Extension components does not support C++ Builder 4. For some strange reason the components causes a link error. * There appear to be sporadic problems compiling with C++ Builder 5. Several user have reported that they occasionally get one or more of the following compiler errors: [C++ Error] DragDropFile.hpp(178): E2450 Undefined structure '_FILEDESCRIPTORW' [C++ Error] DropSource.hpp(135): E2076 Overloadable operator expected I have not been able to reproduce these errors, but I believe the following work around will fix the problem: In the project options of *all* projects which uses these components, add the following conditional define: NO_WIN32_LEAN_AND_MEAN The define *must* be made in the project options. It is not sufficient to #define it in the source. If you manage to compile with C++ Builder (any version), I would very much like to know about it. * Delphi's and C++ Builder's HWND and THandle types are not compatible. For this reason it might be nescessary to cast C++ Builder's HWND values to Delphi's THandle type when a HWND is passed to a function. E.g.: if (DragDetectPlus(THandle(MyControl->Handle), Point(X, Y))) { ... } * Virtual File Stream formats can only be pasted from the clipboard with live data (i.e. FlushClipboard/OleFlushClipboard hasn't been called on the data source). This problem affects TFileContentsStreamOnDemandClipboardFormat and the VirtualFileStream demo. This is believed to be a bug in the Windows clipboard and a work around hasn't been found yet. * Asynchronous targets appears to be broken in the current release. * When TDropFileTarget.GetDataOnEnter is set to True, the component doesn't work with WinZip. Although the file names are received correctly by TDropFileTarget, WinZip doesn't extract the files and the files thus can't be copied/moved. This is caused by a quirk in WinZip; Apparently WinZip doesn't like IDataObject.GetData to be called before IDropTarget.Drop is called. ------------------------------------------- 5. Support and feedback: ------------------------------------------- Since these components are freeware they are also unsupported. You are welcome to ask for help via email, but I cannot guarantee that I will have time to help you or even reply to your mail. If you absolytely can't live without my help, you can alway try bribing me. You can also try asking for help in the Delphi newsgroups. Since the Drag and Drop Component Suite is in widespread use, there's a good chance another user can help you. I recommend the following newsgroups for issues regarding this library (or COM based Drag/Drop in general): borland.public.delphi.winapi borland.public.delphi.thirdparty-tools borland.public.delphi.oleautomation borland.public.cppbuilder.winapi borland.public.cppbuilder.thirdparty-tools Please choose the most appropiate newsgroup for your question. Do not cross post to them all. Before posting to the newsgroups, I suggest you try to search for an answer on the Google (DejaNews) search engine: http://groups.google.com Chances are that your question has been asked and answered before. If you have suggestions for improvements please mail them to me: anders@melander.dk Please include the words "Drag Drop" in the subject of any email regarding these components. ------------------------------------------- 6. Bug reports: ------------------------------------------- Bugs can either be reported at my home page (http://www.melander.dk/) or mailed directly to me: anders@melander.dk. When reporting a bug, please provide the following information: * The exact version of the Drag and Drop Component Suite you are using. * The exact version of Delphi or C++ Builder you are using. * The name and exact version of your operating system (e.g. NT4 SP5). * The exact version of the Internet Explorer installed on your system. If you can provide me with a minimal application which reproduces the problem, I can almost guarantee that I will be able to fix the problem in very short time. Please supply only the source files (pas, dfm, dpr, dof, res, etc.) and mail them as a single zip file. If I need a compiled version I will ask for it. If you feel you need to send me a screen shot, please send it in GIF or PNG format. If you mail a bug report to me, please include the words "Drag Drop" in the subject of your email. ------------------------------------------- 7. Upgrades and bug fixes: ------------------------------------------- Upgrades can be downloaded from my home page: http://www.melander.dk/delphi/dragdrop/ Bug fixes will also be posted to the above page. If you have registered for update notification via the installation program, you will receive email notification when a new release is available. You will not be notified of bug fixes. You can use the installation program to check for and download new releases and to check for known bugs. Note: If a new release is made available and you are not notified even though you registered for notification, you probably mistyped your email address during installation; About 10% of all registrations supply an invalid email address. ------------------------------------------- 8. Missing in this release: ------------------------------------------- * On-line help has not been updated and included in the kit due to late changes in the Delphi 6 help system and lack of time. If time permits, I will update the help and include it in a future release. ------------------------------------------- 9. New in version 4.x: ------------------------------------------- * Completely redesigned and rewritten. Previous versions of the Drag and Drop Component Suite used a very monolithic design and flat class hierachy which made it a bit cumbersome to extend the existing components or implement new ones. Version 4 is a complete rewrite and redesign, but still maintains compatibility with previous versions. The new V4 design basically separates the library into three layers: 1) Clipboard format I/O. 2) Data format conversion and storage. 3) COM Drag/Drop implementation and VCL component interface. The clipboard format layer is responsible for reading and writing data in different formats to and from an IDataObject interface. For each different clipboard format version 4 implements a specialized class which knows exactly how to interpret the clipboard format. For example the CF_TEXT (plain text) clipboard format is handled by the TTextClipboardFormat class and the CF_FILE (file names) clipboard format is handled by the TFileClipboardFormat class. The data format layer is primarily used to render the different clipboard formats to and from native Delphi data types. For example the TTextDataFormat class represents all text based clipboard formats (e.g. TTextClipboardFormat) as a string while the TFileDataFormat class represents a list of file names (e.g. TFileClipboardFormat) as a string list. The conversion between different data- and clipboard formats is handled by the same Assign/AssignTo mechanism as the VCLs TPersistent employes. This makes it possible to extend existing data formats with support for new clipboard formats without modification to the existing classes. The drag/drop component layer has several tasks; It implements the actual COM drag/drop functionality (i.e. it implements the IDropSource, IDropTarget and IDataObject interfaces (along with several other related interfaces)), it surfaces the data provided by the data format layer as component properties and it handles the interaction between the whole drag/drop framework and the users code. The suite provides a multitude of different components. Most are specialized for different drag/drop tasks (e.g. the TDropFileTarget and TDropFilesSource components for drag/drop of files), but some are either more generic, handling multiple unrelated formats, or simply helper components which are used to extend the existing components or build new ones. * Support for Delphi 6. Version 4.0 was primarily developed on Delphi 6 and then ported back to previous versions of Delphi and C++ Builder. * Support for Windows 2000 inter application drag images. On Windows platforms which supports it, drag images are now displayed when dragging between applications. Currently only Windows 2000 supports this feature. On platforms which doesn't support the feature, drag images are only displayed whithin the source application. * Support for Windows 2000 asynchronous data transfers. Asynchronous data tranfers allows the drop source and targets to perform slow transfers or to transfer large amounts of data without blocking the user interface while the data is being transfered. For platforms other than Windows 2000, the new TDropSourceThread class can be used to provide similar (but more limited) asynchronous data transfer capabilities. * Support for optimized and non-optimized move. When performing drag-move operations, it is now possible to specify if the target (optimized move) or the source (non-optimized move) is responsible for deleting the source files. * Support for delete-on-paste. When data is cut to the clipboard, it is now possible to defer the deletion of the source data until the target actually pastes the data. The source is notified by an event when the target pastes the data. * Extended clipboard support. All formats and components (both source and target) now support clipboard operations (copy/cut/paste) and the VCL clipboard object. * Support for shell drop handlers. The new TDropHandler component can be used to write drop handler shell extensions. A drop handler is a shell extension which is executed when a user drags and drops one or more files on a file associated wth your application. * Support for shell drag drop handlers. The new TDragDropHandler component can be used to write drag drop handler shell extensions. A drag drop handler is a shell extension which can extend the popup menu which is displayed when a user drag and drops files with the right mouse button. * Support for shell context menu handlers. The new TDropContextMenu component can be used to write context menu handler shell extensions. A context menu handler is a shell extension which can extend the popup menu which is displayed when a user right-clicks a file in the shell. * Drop sources can receive data from drop targets. It is now possible for drop targets to write data back to the drop source. This is used to support optimized-move, delete-on-paste and inter application drag images. * Automatic re-registration of targets when the target window handle is recreated. In previous versions, target controls would loose their ability to accept drops when their window handles were recreated by the VCL (e.g. when changing the border style or docking a form). This is no longer a problem. * Support for run-time definition of custom data formats. You can now add support for new clipboard formats without custom components. * Support for design-time extension of existing source and target components. Using the new TDataFormatAdapter component it is now possible to mix and match data formats and source and target components at design time. E.g. the TDropFileTarget component can be extended with URL support. * It is now possible to completely customize the target auto-scroll feature. Auto scroling can now be completely customized via the OnDragEnter, OnDragOver, OnGetDropEffect and OnScroll events and the public NoScrollZone and published AutoScroll properties. * Multiple target controls per drop target component. In previous versions you had to use one drop target component per target control. With version 4, each drop target component can handle any number of target controls. * It is now possible to specify the target control at design time. A published Target property has been added to the drop target components. * Includes 20 components: - TDropFileSource and TDropFileTarget Used for drag and drop of files. Supports recycle bin and PIDLs. - TDropTextSource and TDropTextTarget Used for drag and drop of text. - TDropBMPSource and TDropBMPTarget Used for drag and drop of bitmaps. - TDropPIDLSource and TDropPIDLTarget Used for drag and drop of PIDLs in native format. - TDropURLSource and TDropURLTarget Used for drag and drop of internet shortcuts. - TDropDummyTarget Used to provide drag/drop cursor feedback for controls which aren't registered as drop targets. - TDropComboTarget (new) Swiss-army-knife target. Accepts text, files, bitmaps, meta files, URLs and file contents. - TDropMetaFileTarget (new) Target which can accept meta files and enhanced meta files. - TDropImageTarget (new) Target which can accept bitmaps, DIBs, meta files and enhanced meta files. - TDragDropHandler (new) Used to implement Drag Drop Handler shell extensions. - TDropHandler (new) Used to implement Shell Drop Handler shell extensions. - TDragDropContext (new) Used to implement Shell Context Menu Handler shell extensions. - TDataFormatAdapter (new) Extends the standard source and target components with support for extra data formats. An alternative to TDropComboTarget. - TDropEmptySource and TDropEmptyTarget (new) Target and source components which doesn't support any formats, but can be extended with TDataFormatAdapter components. * Supports 27 standard clipboard formats: Text formats: - CF_TEXT (plain text) - CF_UNICODETEXT (Unicode text) - CF_OEMTEXT (Text in the OEM characterset) - CF_LOCALE (Locale specification) - 'Rich Text Format' (RTF text) - 'CSV' (Tabular spreadsheet text) File formats: - CF_HDROP (list of file names) - CF_FILEGROUPDESCRIPTOR, CF_FILEGROUPDESCRIPTORW and CF_FILECONTENTS (list of files and their attributes and content). - 'Shell IDList Array' (PIDLs) - 'FileName' and 'FileNameW' (single filename, used for 16 bit compatibility). - 'FileNameMap' and 'FileNameMapW' (used to rename files, usually when dragging from the recycle bin) Image formats: - CF_BITMAP (Windows bitmap) - CF_DIB (Device Independant Bitmap) - CF_METAFILEPICT (Windows MetaFile) - CF_ENHMETAFILE (Enhanced Metafile) - CF_PALETTE (Bitmap palette) Internet formats: - 'UniformResourceLocator' and 'UniformResourceLocatorW' (Internet shortcut) - 'Netscape Bookmark' (Netscape bookmark/URL) - 'Netscape Image Format' (Netscape image/URL) - '+//ISBN 1-887687-00-9::versit::PDI//vCard' (V-Card) - 'HTML Format' (HTML text) - 'Internet Message (rfc822/rfc1522)' (E-mail message in RFC822 format) Misc. formats: - CF_PREFERREDDROPEFFECT and CF_PASTESUCCEEDED (mostly used by clipboard) - CF_PERFORMEDDROPEFFECT and CF_LOGICALPERFORMEDDROPEFFECT (mostly used for optimized-move) - 'InShellDragLoop' (used by Windows shell) - 'TargetCLSID' (Mostly used when dragging to recycle-bin) * New source events: - OnGetData: Fired when the target requests data. - OnSetData: Fired when the target writes data back to the source. - OnPaste: Fired when the target pastes data which the source has placed on the clipboard. - OnAfterDrop: Fired after the drag/drop operation has completed. * New target events: - OnScroll: Fires when the target component is about to perform auto-scroll on the target control. - OnAcceptFormat: Fires when the target component needs to determine if it will accept a given data format. Only surfaced in the TDropComboTarget component. * 8 new demo applications, 19 in total. ------------------------------------------- 10. TODO (may or may not be implemented): ------------------------------------------- * Async target demo (with and without IAsyncOperation support). * Scrap file demo. * Native Outlook message format. * Structured storage support (IStorage encapsulation). ------------------------------------------- 11. Licence, Copyright and Disclaimer: ------------------------------------------- The Drag and Drop Component Suite is Copyright ?1997-2001 Angus Johnson and Anders Melander. All rights reserved. The software is copyrighted as noted above. It may be freely copied, modified, and redistributed, provided that the copyright notice(s) is preserved on all copies. The Drag and Drop Component Suite is freeware and we would like it to remain so. This means that it may not be bundled with commercial libraries or sold as shareware. You are welcome to use it in commercial and shareware applications providing you do not charge for the functionality provided by the Drag and Drop Component Suite. There is no warranty or other guarantee of fitness for this software, it is provided solely "as is". You are welcome to use the source to make your own modified components, and such modified components may be distributed by you or others if you include credits to the original components, and do not charge anything for your modified components. ------------------------------------------- 12. Version 4 release history: ------------------------------------------- 16-dec-2001 * Ported to C++ Builder 4. * Released for test as v4.1 FT5. 12-dec-2001 * Fixed C++ Builder name clash between TDropComboTarget.GetMetaFile and the GetMetaFile #define in wingdi.h 1-dec-2001 * The IAsyncOperation interface is now also declared as IAsyncOperation2 and all references to IAsyncOperation has been replaced with IAsyncOperation2. This was done to work around a bug in C++ Builder. Thanks to Jonathan Arnold for all his help with getting the components to work with C++ Builder. Without Jonathan's help version 4.1 would prabably have shipped witout C++ Builder support and certainly without any C++ Builder demos. * Demo applications for C++ Builder. The C++ Builder demos were contributed by Jonathan Arnold. 27-nov-2001 * TCustomDropTarget.Droptypes property renamed to DropTypes (notice the case). Thanks to Krystian Brazulewicz for spotting this. 24-nov-2001 * The GetURLFromString function in the DragDropInternet unit has been made public due to user request. 21-nov-2001 * Modified MakeHTML function to comply with Microsoft's description of the CF_HTML clipboard format. * Added MakeTextFromHTML function to convert CF_HTML data to plain HTML. Provides the reverse functionality of MakeHTML. * Added HTML support to TTextDataFormat class and TDropTextSource and TDropTextTarget components. * Fixed C++ Builder 5 problem with IAsyncOperation. * Released for test as v4.1 FT4. 10-nov-2001 * Added NetscapeDemo demo application. Demonstrates how to receive messages dropped from Netscape. This demo was sponsored by ThoughtShare Communications Inc. * Released for test as v4.1 FT3. 23-oct-2001 * Conversion priority of TURLDataFormat has been changed to give the File Group Descritor formats priority over the Internet Shortcut format. This resolves a problem where dropping an URL on the desktop would cause the desktop to assume that an Active Desktop item was to be created instead of an Internet Shortcut. Thanks to Allen Martin for reporting this problem. By luck this modification also happens to work around a bug in Mozilla and Netscape 6; Mozilla incorrectly supplies the UniformResourceLocator clipboard format in unicode format instead of ANSI format. Thanks to Florian Kusche for reporting this problem. * Added support for TFileGroupDescritorWClipboardFormat to TURLDataFormat. * Added declaration of FD_PROGRESSUI to DragDropFormats. * Added TURLWClipboardFormat which implements the "UniformResourceLocatorW" (a.k.a. CFSTR_INETURLW) clipboard format. Basically a Unicode version of CFSTR_SHELLURL/CFSTR_INETURL. The TURLWClipboardFormat class isn't used anywhere yet but will probably be supported by TURLDataFormat (and thus TDropURLTarget/TDropURLSource) in a later release. * Added experimental Shell Drag Image support. This relies on undodumented shell32.dll functions and probably won't be fully support before v4.2 (if ever). See InitShellDragImage in DropSource.pas. Thanks to Jim Kueneman for bringning these functions to my attention. 13-oct-2001 * TCustomDropSource.Destroy and TCustomDropMultiSource.Destroy changed to call FlushClipboard instead of EmptyClipboard. This means that clipboard contents will be preserved when the source application/component is terminated. * Added clipboard support to VirtualFileStream demo. * Modified VirtualFileStream demo to work around clipboard quirk with IStream medium. * Modified TCustomSimpleClipboardFormat to disable TYMED_ISTORAGE support by default. At present TYMED_ISTORAGE is only supported for drop targets and enabling it by default in TCustomSimpleClipboardFormat.Create caused a lot of clipboard operations (e.g. copy/paste of text) to fail. Thanks to Michael J Marshall for bringing this problem to my attention. * Modified TCustomSimpleClipboardFormat to read from the the TYMED_ISTREAM medium in small (1Mb) chunks and via a global memory buffer. This has resultet in a huge performance gain (several orders of magnitude) when transferring large amounts of data via the TYMED_ISTREAM medium. 3-oct-2001 * Fixed bug in TCustomDropSource.SetImageIndex. Thanks to Maxim Abramovich for spotting this. * Added missing default property values to TCustomDropSource. Thanks to Maxim Abramovich for spotting this. * DragDrop.pas and DragDropContext.pas updated for Delphi 4. * Reimplemented utility to convert DFM form files from Delphi 5/6 test format to Delphi 4/5 binary format. * Improved unregistration of Shell Extensions. Shell extension now completely (and safely) remove their registry entries when unregistered. * Deprecated support for C++ Builder 3. * Released for test as v4.1 FT2. 25-sep-2001 * Rewritten ContextMenuHandlerShellExt demo. The demo is now actually a quite useful utility which can be used to register and unregister ActiveX controls, COM servers and type libraries. It includes the same functionality as Borland's TRegSvr utility. 20-sep-2001 * Added support for cascading menus, ownerdraw and menu bitmaps to TDropContextMenu component. * Modified TFileContentsStreamOnDemandClipboardFormat to handle invalid parameter value (FormatEtcIn.lindex) when data is copied to clipboard. This works around an apparent bug in the Windows clipboard. Thanks to Steve Moss for reporting this problem. * Modified TEnumFormatEtc class to not enumerate empty clipboard formats. Thanks to Steve Moss for this improvement. 1-sep-2001 * Introduced TCustomDropTarget.AutoRegister property. The AutoRegister property is used to control if drop target controls should be automatically unregistered and reregistered when their window handle is recreated by the VCL. If AutoRegister is True, which is the default, then automatic reregistration will be performed. This property was introduced because the hidden child control, which is used to monitor the drop target control's window handle, can have unwanted side effects on the drop target control (e.g. TToolBar). * Deprecated support for Delphi 3. 22-jun-2001 * Redesigned TTextDataFormat to handle RTF, Unicode, CSV and OEM text without conversion. Moved TTextDataFormat class to DragDropText unit. Added support for TLocaleClipboardFormat. * Surfaced new text formats as properties in TDropTextSource and TDropTextTarget. Previous versions of the Text source and target components represented all supported text formats via the Text property. In order to enable users to handle the different text formats independantly, the text source and target components now has individual properties for ANSI, OEM, Unicode and RTF text formats. The text target component can automatically synthesize some of the formats from the others (e.g. OEM text from ANSI text), but applications which previously relied on all formats being represented by the Text property will have to be modified to handle the new properties. * Added work around for problem where TToolBar as a drop target would display the invisible target proxy window. * Fixed wide string bug in WriteFilesToZeroList. Thanks to Werner Lehmann for spotting this. 15-jun-2001 * Added work-around for Outlook Express IDataObject.QueryGetData quirk. 3-jun-2001 * Ported to C++ Builder 4 and 5. * Added missing DragDropDesign.pas unit to design time packages. * First attempt at C++ Builder 3 port.... failed. * Improved handling of oversized File Group Descriptor data. * Added support for IStorage medium to TFileContentsStreamClipboardFormat. This allows the TDropComboTarget component to accept messages dropped from Microsoft Outlook. This work was sponsored by ThoughtShare Communications Inc. 23-may-2001 * Ported to Delphi 4. * First attempt at C++ Builder 5 port.... failed. 18-may-2001 * Released as version 4.0. Note: Version 4.0 was released exclusively on the Delphi 6 Companion CD. * ContextMenuDemo and DropHandlerDemo application has been partially rewritten and renamed. ContextMenuDemo is now named ContextMenuHandlerShellExt. DropHandlerDemo is now named DropHandlerShellExt. * TDropContextMenu component has been rewitten. The TDropContextMenu now implements a context menu handler shell extension. In previous releases it implemented a drag drop handler shell extension. * The DragDropHandler.pas unit which implements the TDropHandler component has been renamed to DropHandler.pas. * Added new TDragDropHandler component. The new component, which lives in the DragDropHandler unit, is used to implement drag drop handler shell extensions. * Added DragDropHandlerShellExt demo application. * Removed misc incomplete demos from kit. * Fixed minor problem in VirtualFileStream demo which caused drops from the VirtualFile demo not to transfer content correctly. 11-may-2001 * Converted all demo forms to text DFM format. This has been nescessary to maintain compatibility between all supported versions of Delphi. * Fixed a bug in GetPIDLsFromFilenames which caused drag-link of files (dtLink with TDropFileSource) not to work. * Added readme.txt files to some demo applications. * Added missing tlb and C++ Builder files to install kit. * Released as FT4. 6-may-2001 * Added missing dfm files to install kit. * Tested with Delphi 5. Fixed Delphi 5 compatibility error in main.dfm of DragDropDemo. * Removed misc compiler warnings. * The AsyncTransferTarget and OleObjectDemo demos were incomplete and has been removed from the kit for the V4.0 release. The demos will be included in a future release. * Released as FT3. 3-may-2001 * Added missing dpr and bpg files to install kit. * Updated readme.txt with regard to lack of C++ Builder demos. * Released as FT2. 29-apr-2001 * Cleaned up for release. * Released as FT1. 23-feb-2001 * Modified TCustomDropTarget.FindTarget to handle overlapping targets (e.g. different targets at the same position but on different pages of a page control or notebook). Thanks to Roger Moe for spotting this problem. 13-feb-2001 * Renamed AsyncTransfer2 demo to AsyncTransferSource. * Added AsyncTransferTarget demo. * Replaced TChart in AsyncTransfer2 demo with homegrown pie-chart-thing. * Modified all IStream based target formats to support incremental transfer. * URW533 problem has finally been fixed. The cause of the problem, which is a bug in Delphi, was found by Stefan Hoffmeister. * Fixed free notification for TDropContextmenu and TDataFormatAdapter. 27-dec-2000 * Moved TVirtualFileStreamDataFormat and TFileContentsStreamOnDemandClipboardFormat classes from VirtualFileStream demo to DragDropFormats unit. * Added TClipboardFormat.DataFormat and TClipboardFormats.DataFormat property. * Added TDropEmptySource and TDropEmptyTarget components. These are basically do-nothing components for use with TDataFormatAdapter. * Rewritten AsyncTransfer2 demo. The demo now uses TDropEmptySource, TDataFormatAdapter and TVirtualFileStreamDataFormat to transfer 10Mb of data with progress feedback. * Rewritten VirtualFileStream demo. The demo now uses TDropEmptySource, TDropEmptyTarget, TDataFormatAdapter and TVirtualFileStreamDataFormat. * Fixed memory leak in TVirtualFileStreamDataFormat. This leak only affected the old VirtualFileStream demo. * Added support for full File Descriptor attribute set to TVirtualFileStreamDataFormat. It is now possible to specify file attributes such as file size and last modified time in addition to the filename. I plan to add similar features to the other classes which uses FileDescriptors (e.g. TDropFileSource and TDropFileTarget). 21-dec-2000 * Ported to Delphi 4. * Added workaround for design bug in either Explorer or the clipboard. Explorer and the clipboard's requirements to the cursor position of an IStream object are incompatible. Explorer requires the cursor to be at the beginning of stream and the clipboard requires the cursor to be at the end of stream. 15-dec-2000 * Fixed URW533 problem. I'll leave the description of the workaround in here for now in case the problem resurfaces. 11-dec-2000 * Fixed bug in filename to PIDL conversion (GetPIDLsFromFilenames) which affected TDropFileTarget. Thanks to Poul Halgaard J鴕gensen for reporting this. 4-dec-2000 * Added THTMLDataFormat. * Fixed a a few small bugs which affected clipboard operations. * Added {$ALIGN ON} to dragdrop.inc. Apparently COM drag/drop requires some structures to be word alligned. This change fixes problems where some of the demos would suddenly stop working. * The URW533 problem has resurfaced. See the "Known problems" section below. 13-nov-2000 * TCopyPasteDataFormat has been renamed to TFeedbackDataFormat. * Added support for the Windows 2000 "TargetCLSID" format with the TTargetCLSIDClipboardFormat class and the TCustomDropSource.TargetCLSID property. * Added support for the "Logical Performed DropEffect" format with the TLogicalPerformedDropEffectClipboardFormat class. The class is used internally by TCustomDropSource. 30-oct-2000 * Added ContextMenu demo and TDropContextMenu component. Demonstrates how to customize the context menu which is displayed when a file is dragged with the right mouse button and dropped in the shell. * Added TCustomDataFormat.GetData. With the introduction of the GetData method, Data Format classes can now be used stand-alone to extract data from an IDataObject. 20-oct-2000 * Added VirtualFileStream demo. Demonstrates how to use the "File Contents" and "File Group Descritor" clipboard formats to drag and drop virtual files (files which doesn't exist physically) and transfer the data on-demand via a stream. 14-oct-2000 * Added special drop target registration of TCustomRichEdit controls. TCustomRichEdit needs special attention because it implements its own drop target handling which prevents it to work with these components. TCustomDropTarget now disables a rich edit control's built in drag/drop handling when the control is registered as a drop target. * Added work around for Windows bug where IDropTarget.DragOver is called regardless that the drop has been rejected in IDropTarget.DragEnter. 12-oct-2000 * Fixed bug that caused docking to interfere with drop targets. Thanks to G. Bradley MacDonald for bringing the problem to my attention. 30-sep-2000 * The DataFormats property has been made public in the TCustomDropMultiTarget class. * Added VirtualFile demo. Demonstrates how to use the TFileContentsClipboardFormat and TFileGroupDescritorClipboardFormat formats to drag and drop a virtual file (a file which doesn't exist physically). 28-sep-2000 * Improved drop source detection of optimized move. When an optimized move is performed by a drop target, the drop source's Execute method will now return drDropMove. Previously drCancel was returned. The OnAfterDrop event must still be used to determine if a move operation were optimized or not. * Modified TCustomDropTarget.GetPreferredDropEffect to get data from the current IDataObject instead of from the VCL global clipboard. 18-sep-2000 * Fixed bug in DropComboTarget caused by the 17-sep-2000 TStreams modification. 17-sep-2000 * Added AsyncTransfer2 demo to demonstrate use of TDropSourceThread. * Renamed TStreams class to TStreamList. 29-aug-2000 * Added TDropSourceThread. TDropSourceThread is an alternative to Windows 2000 asynchronous data transfers but also works on other platforms than Windows 2000. TDropSourceThread is based on code contributed by E. J. Molendijk. 24-aug-2000 * Added support for Windows 2000 asynchronous data transfers. Added IAsyncOperation implementation to TCustomDropSource. Added TCustomDropSource.AllowAsyncTransfer and AsyncTransfer properties. 5-aug-2000 * Added work around for URW533 compiler bug. * Fixed D4 and D5 packages and updated a few demos. Obsolete DropMultiTarget were still referenced a few places. * Documented work around for C++ Builder 5 compiler error. See the Known Problems section later in this document for more information. 2-aug-2000 * The package files provided in the kit is now design-time only packages. In previous versions, the packages could be used both at design- and run-time. The change was nescessary because the package now contains design-time code. * Added possible work around for suspected C++ Builder bug. The bug manifests itself as a "Overloadable operator expected" compile time error. See the "Known problems" section of this document. * Rewrote CustomFormat1 demo. * Added CustomFormat2 demo. * TDataDirection members has been renamed from ddGet and ddSet to ddRead and ddWrite. * All File Group Descritor and File Contents clipboard formats has been moved from the DragDropFile unit to the DragDropFormats unit. * File Contents support has been added to TTextDataFormat. The support is currently only enabled for drop sources. * Renamed TDropMultiTarget component to TDropComboTarget. Note: This will break applications which uses the TDropMultiTarget component. You can use the following technique to port application from previous releases: 1) Install the new components. 2) Repeat step 3-8 for all units which uses the TDropMultiTarget component. 3) Make a backup of the unit (both pas and dfm file) just in case... 4) Open the unit in the IDE. 5) In the .pas file, replace all occurances of "TDropMultiTarget" with "TDropComboTarget". 6) View the form as text. 7) Replace all occurances of "TDropMultiTarget" with "TDropComboTarget". 8) Save the unit. * Renamed a lot of demo files and directories. * Added work around for yet another bug in TStreamAdapter. * Added TCustomStringClipboardFormat as new base class for TCustomTextClipboardFormat. This changes the class hierachy a bit for classes which previously descended from TCustomTextClipboardFormat: All formats which needs zero termination now descend from TCustomTextClipboardFormat and the rest descend from TCustomStringClipboardFormat. Added TrimZeroes property. Fixed zero termination bug in TCustomTextClipboardFormat and generally improved handling of zero terminated strings. Disabled zero trim in TCustomStringClipboardFormat and enabled it in TCustomTextClipboardFormat. 23-jul-2000 * Improved handling of long file names in DropHandler demo. Added work around for ParamStr bug. * Added TDataFormatAdapter component and adapter demo. TDataFormatAdapter is used to extend the existing source and target components with additional data format support without modifying them. It can be considered an dynamic alternative to the current TDropMultiTarget component. 17-jul-2000 * TDropHandler component and DropHandler demo fully functional. 14-jul-2000 * Tested with C++ Builder 5. * Fixed sporadic integer overflow bug in DragDetectPlus function. * Added shell drop handler support with TDropHandler component. This is a work in progress and is not yet functional. 1-jul-2000 * Tested with Delphi 4. * Support for Windows 2000 inter application drag images. * TRawClipboardFormat and TRawDataFormat classes for support of arbitrary unknown clipboard formats. The classes are used internally in the TCustomDropSource.SetData method to support W2K drag images.
SakEmail components Copyright ?1997 - 2003 Sergio A. Kessler web: http://groups.yahoo.com/group/sakemail/To subscribe to the mailing list of sakemail, just go tohttp://groups.yahoo.com/group/sakemail/History:0.9 - First released version0.9.1b -Fixed when a mail server reply on the connection with more than one line0.9.2b - I forget to return a value in functions retrieveHeader/Message =) and fixed it. Some minor bugs that I don‘t remember fixed.- Added MIME-compliant base64 support (not for use by now). Added examples.0.9.2.1b- Fixed a bug when send a mail and the first line disappear (thanks to Arun)- Now, you could do MySMTP.MsgTo := ‘a@doma.com; b@domb.com;c@domc.com‘; the spaces before/after semicolon doesn‘t matter (I hope ;)).0.9.3b- Many changes, I added a SakMsg component that make send binary attachments a snap. But have one problem, if you send as attach a file > 20 Kb, it doesn‘t work (I don‘t know why, maybe a problem of sockets). Developed with a version 2.0b of WSockets and D3.0.9.3.1b- Changed the POP.login to a function that return the number of new msgs.- Added the event OnRetrieveProgress on the SakPOP, and fixed the example, sorry =)- Minor changes to the code.1.0- Developed with WSockets 1.2 POP.Login now return a boolean depending id the user is authorized, and POP.Init return the number of new msgs.1.01- Fixed a bug with a bounced mail.1.02- Minor bugs fixed (some variants of boundary)14/10/971.1.0- Warning: WSockets1.2 have some bugs that result in bad attachments. So I decided to use the sockets of Delphi 3 founded in D3 c/s D3.01 pro and D3.01 c/s. Now all seems to work fine and much more smooth. And of course the interface of SakEmail hasn‘t changed.26/10/971.2.0- Added the Reply-To field to TSakMsg comp. Now you must use ‘,‘ when you want to send the msg. to multiple recipients, i.e.: ‘a@doma.com, b@domb.com,c@domc.com‘ This change is done for better compatibility with other emails clients.- Better formatting of the field Date of TSakMsg. Some changes to the code.17/11/971.2.1- Now, all searches are made in case-insensitive, it could prevent some unexpected responses (no one reported, but...). Some changes to the code (again).20/11/971.2.2- Some bugs fixed. (Thanks to Serge Wagener from .lu)24/11/971.2.3- Added the field ‘MIME-Version: 1.0‘. It seems that is necessary :)25/11/971.3.0- Added compatibility with SCO and VAX servers. Fixed a minor bug with the boundary.- Change the generator of the message id.- Added the field MessageId and InReplyTo to the TSakMsg component.- Added the field In-Reply-To that is added to the message generated when it is <> ‘‘.30/11/971.3.1- Almost rewrote the parsing code. Now is more easy for you if you want hack/modify the code.- Better treatment of emails with html inside.15/12/971.4- Added support for UUCoded attachments.- Added a small delay when sending the email, seems that some servers can‘t deglut the info too fast, causing problems with sockets buffers and leading to crash the client machine, I don‘t know if is a Borland bug or Microsoft bug. (thanks to Don Higgins).19/12/971.4.1- Fixed a bug that send double ‘<‘ and ‘>‘ (ie. <com>>) when the full user name is used. Check the new SMTP demo. Thanks to Serge Wagener for locate this bug, track it down and send me the fix.2/2/981.5.0- Added the Canceled property to TSakPOP and to TSakSMTP. Due to this addition now RetrieveAllMessages is a function that return the number of msgs. retrieved and SendMessage is a boolean function (maybe someone has pressed the cancel btn).- Fixed a bug when the subject field is too large.9/2/981.5.1- Fixed a bug with a message within a message (recursive msgs).18/2/981.5.2- Fixed a bug what happens when after the field ‘To:‘ appear a blank line(Thanks to Osvaldo Fillia). Fixed a bug when sending email to more than two address (the separator is still ‘,‘).9/3/981.6.0- Sometimes the filenames of an attachment contain invalid chars making very dificult to open a TSaveDialog (you have noted this ?), now SakEmail deletes the invalid chars.- Applied a patch from Matjaz Bravc, that resolve the problem of localized dates, letting you choose (in design time) if you want localized dates (NOT recommended) or standards dates (english) via the LocalizedDates boolean property in the TSakSMTP comp. Thanks also to Serge Dosyukov for sending me a fix.- Also I applied another patch of Gregor Duchalski that cure a bug with PChar when this unit is used under NT. - It seems that some machines need more delay when sendig a msg (see previous posting 19/12/97), thanks to Matjaz Bravc.- I discover a bug in the transparency code, it is fixed now. Did you see the benefits of Open Source Software ? :)26/3/981.6.1- Added a FUNCFileName private variable to manage the complete path of the attached file. I receive problems reports with this, it work now ?.- Reduced the line sleep to 30 (tell me if this value doesn‘t work for you).27/4/981.7.0- Fixed a memory leak, thanks to Don Higgins.- Moved the string esErrorInFormatOfMsg to a property of SakPOP.- Because some people need to use IP addresses instead of Host names, I‘ve added a new property IPAddress to SakPOP and SakSMTP. If both are filled, then the Host name will be used, thanks to Roger F. Reghin for reporting this. The side effect for this is that YOUR app must check if the host is a host name or a IP address, in my app I remove the periods and try to convert the result to a float (long integers don‘t work, but float accept chars ‘e‘) if it doesn‘t work I assume that is a host name (someone has a better and simple idea ?).- Added the property FileStream to the class TAtachedFile and the procedure SaveToStream, this was done by Brian Sheperd- The address separator (in the TO: field) is ‘,‘ and ‘;‘ now (before it was ‘,‘ only).1.7.1- Roger F. Reghin has sended me a pair of nice patches that resolve in a good behavior when the destination address is something like "Roger Reghin" com> and some servers says that they couldn‘t relay that mail, etc. Also Roger has made the IPAddress property obsolete (do not use it, use Host instead), SakEmail will resolve the host properly no matter if it is a host name or a IP address. So in the next version I will remove the IPAddress property. Thank you, Roger.1.8.0- Well, it seems that I made a mistake, I investigated the previous behavior and it is a fault of the SMTP (RFC 821), so I fixed it.- The IPAddress property has been removed, use Host. Goeran Strehl (asem) has sended me a patch that fix a memory leak and one problem with the object inspector and the Text property of a SakMsg. Dmitry Bondarenko say that some servers do not send the msg size after the RETR command, so he fix that issuing a LIST n command first (work nicely).- Added the property CC (Carbon Copy) to the SakMsg object.1.8.1- Added the property ReturnPath to the SakMsg comp. Minor changes to the scanning code for the filename of attachments.1.8.2- Fixed a bug with the filename of attachments (thanks to Taufer Pavel Ing.).- Added the function IsIPAddress from hou yg (the actual code don‘t work if the server is 265.net :) Fixed a minor bug with html pages like attachments. Some fucking email server return a bounded message declaring the boundary like ‘boundary = ‘ and not ‘boundary=‘ wich is clear in the RFC, fixed.1.8.3- A obscure bug was found by HuangYeJun from china, in the RetrieveHeaders function if the retrieved text was larger than 1024 bytes and the crlf.crlf fall in the middle of two chunks, the function is blocked. I don‘t use this function, btw.1.8.3.1- Just cleaned up a bit the FindUUAtachs function. Not bug or enhancements release. Serge Wagener put me to work >:|1.8.4- Dmitry Bondarenko (again) has found a bug in wich I do not respect the RFC, wich say that replys from the SMTP server could be multi-line, and the previous version just manage as far as two lines. He also send me a nice patch, so the bug is fixed.- Craig Manley added a ExtraHeaders property, please, use with care, it‘s just not valid to put inside it whatever thing.- The CC header was not being added to the headers that were being sent, so Craig fixed it.- Warning: I‘ve put try/except in the TSakPOP.Connect and TSMTP.Connect function around the line FSocket.Open, so you will need to write something like: myPOP.Connect; if POPError then ... in your code, the old way was: try myPOP.Connect; except ..... end; If you are strongly opossed to this change, drop me a line and tell me why (I‘m in doubts).1.8.5- Greg Nixon added the priority property. The default priority for each msg created will be prNormal, so you don‘t need to change your code any bit.1.8.6- Ulf Sturegren has added D4 compatibility, not many changes to the source (one letter), but he found the error.- Hou yg has sent to me a revisited IsIPAddress function, so I put the newer function in, infortunely my reply to him doesn‘t want to go.1.8.7- Ok, I discovered a weird bug, some old emailers (navigator 2) does not format the message in multipart mode if people send an attach, without writing any text and with no MIME settings. Fixed. This could be serious, I recommend upgrading.1.8.8- A small fix with the CC field. Some stupid mail servers put tabs in some fields (CC:, TO:) when they want to make a new line, the correct is to put at least a space in the beginning of the line, added a little code to "fix" that.1.8.9- Some ‘moderns‘ pop3 servers doesn‘t support the LAST command, so I‘ve added a little code to cope with this and added a boolean property ServerSupportLastCmd. See TSakPOP.Init for more details. Reported by Jan Najvarek.1.9.0- Kaufman Alex has added two properties to the SakMsg object, the ContentType and the Headers property, that should be self explaining (I modified a little the code he sended me, btw).1.9.1- I rewrote and greatly simplified the code that deal with the multiple address in the TO: field and remove some possible bugs in it.1.9.2- Alex discovered and fix a bug when a file attached is not enclosed between quotes, resulting in the filename without the first and last character.1.9.3- Better detection of the boundary in multipart messages. Fixed a bug when the attached file is empty.1.9.4- Chris G黱ther send me *lots* of memory leaks fixes, very good job, Chris. - Some weird PGP messages are now processed well.- Yang Qiandong from china fixed a compiler hint and a warning.- Modified TSakSMTP.FReceiveTextFromSocket as suggested by Greg Nixon.- Dmitry Bondarenko send me a patch that fixes some issues with the LAST command (that some servers don‘t implement) and other patch that fixes a problem when servers add spare words in the tail of the answer.- Some minor changes suggested by Matthew Vincent.- Support for _big_ attachments files (me).- Make the code more modular and simple (still is not very modular).1.10.0- Move some stuff to a sak_util unit.- Support for quoted-printable msgs, thanks to Chris G黱ther.- Fix the BCC field.- New property sakMsg.ContentTransferEncoding.2.0.0- Major reestructure of the files and the source code.- Simplifyied sakPOP3.pas a _lot_- Support encapsulated messages (message/rfc822).- Nested multipart messages are processed fine.- Attachs with quoted-printable are processed fine.- Many bugs fixes.2.0.1- A fiasco, sorry.2.0.2- Fixed a bug in the sak_CleanUpAddress.- Do the rigth job if the ContentType is ‘plain/text‘ and the encoding is base64.- Redone sak_ExtractAddress and sak_ExtractAlias.- New ‘Sender‘ property in SakMsg (normally not used, so do not use it, unless you know what you are doing) ‘Thanks‘ to Alex Kaufman for this.2.0.3- A *severe* bug with multiple addresses was fixed.2.0.4- Fixed bogus Message-number (Message-id is the correct) Thanks to Peter Honan- Added SizeInBytes property to the SakMsg component. (petition of Alex Kaufman)- Fixed a minor bug in TSakPOP.RetrieveHeaders. Fix from Alex.- Added RetrieveMessageOnlyHeaders and - RetrieveAllMessagesOnlyHeaders.2.0.5- Fix when the mail server reply is like (two cr).- Fix function IsIpAddress.- Both fixes by Alessandro Rossi.2.0.6- Fix a bug in the sak_Base64Decode function when the data to decode is null (I found it in the hard way).- Andy Charalambous make it sure you can send more than one email without disconnecting and connecting again.- And Chris ‘Memory Hunter‘ G黱ther killed some memory leaks (again).2.2.0- the f* sleep line that was bothering us for years is gone, gone, gone. Thanks to Syed Ahmed.- a getUIDL method of SakPOP. Thanks to Alex Kaufman.- a UIDL property on SakMsg. (me)- a SakPOP.GetUIDLsOnRetrieve boolean property (default false) (me)- change some ‘Exception.Create()‘ to ‘raise Exception.Create()‘ Thanks to Anton Saburov.- change SakPOP.Init from function to procedure (me)- new SakPOP.NewMsgsCount property (me)- changed SakPOP.Password to SakPOP.UserPassword (me)- changed SakPOP.ErrorInFormatOfMsg to SakPOP.StrErrorInFormatOfMsg- OnLookup event on SakPOP and SakSMTP. Thanks to Syed Ahmed.- OnConnecting event on SakPOP and SakSMTP (me).- OnReceiveTextFromSocket event on SakPOP and SakSMTP (me). (mostly for debug)- OnSendTextToSocket event on SakPOP and SakSMTP (me). (mostly for debug)- Headers are retrieved without the mail body (ugly bug, fix from Alex Kaufman)2.4.0- I‘ve revamped TSakMsg, many funcionality from SakPOP was moved to SakMsg, where it belongs.- Now SakMsg has a RawMail property wich you may find useful, now you can do: SakMsg1.RawMail.LoadFromFile(‘(uidl).mail‘); SakMsg1.ParseMsg; or SakMsg1.RawMail.LoadFromStream( myStream); SakMsg1.ParseMsg; or SakMsg1.RawMail.SaveToFile( ‘(uidl).mail‘); etc, etc...- Added a property TSakMsg.ClearRawMailAfterParse for memory saving.- the return of the f* sleep line (it causes freezes on winsock 1.1 systems like win95, win98 has winsock 2 so there is no problem if you remove the line)- lost of the DecodeProgess events :( (sorry, I don‘t know how to fit this events on the new SakMsg)2.6.0- the sleep() line is dead, it will never come back. Sending an email is a pleasure now.- SakMsg has a TextEncoding (8Bit, Base64) property, I think this will be useful to people with others charset than iso-8859-1- the base64 routines have been rewritten, they are more OO and faster (they are now in SakMIME.pas).- cosmetic changes all over the place.2.6.1- simplifyed ParseMsg2 a lot, it work better now.- speed up the search for uucoded attachs (the previous search was very dumb)- fixed bug Msg.SizeInBytes always 0- added a couple of Application.ProcessMessages to make the app more responsive.2.6.2- moved some functions from sak_utils to SakMIME.- make const parameters all over the place.- fix the bug that introduces a final crlf in quoted-printable attachs.- fix a division by zero if attached file is 0 bytes long, fixed by Peter Kollanyi.2.6.3- fix a rare bug when the header of a email (more probably a encapsulated one) has first line/s in blank. Easy and innocuous bug.2.6.4- fix the bug that insert the attachs of type text/* on the body of the email.- change the Smtp.SendMessage for Smtp.SendTheMessage to avoid a BCBuilder problem. Both problems reported by Andreas Franzen. SendMessage is still there, but it‘s now deprecated, I will remove it in the future.2.6.5- moved the ParseMsg activation from SakPOP to SakMsg (where it belong), this means that after setting the RawMail property of SakMsg, this does a ParseMsg automatically. before: SakMsg1.RawMail := ... SakMsg1.ParseMsg; now: SakMsg1.RawMail := ... hope I‘m not breaking too much code out there ... :)- some changes in the way attachments are processed (now the html part is separated correctly and images within the html are recognized)- RetrieveMessage() and RetrieveMessageOnlyHeaders() now take an additional parameter, a TSakMsg var, so people can change some parameters before parsing, see the source in SakPOP3.pas (the old way is still supported, but they will be removed in the future)- bug fixes that I do not remember.3.0.0- moved code around.- removed deprecated functions (I told you about this)- new SakAttFile unit.- Base64Encode( AttFile), Base64Decode( AttFile), UUDecode( AttFile) has been moved to the TAtachedFile object, so you can do AttFile.Base64Encode, AttFile.Base64Decode, etc- SakSMTP have lost EncodeStart, EncodeProgess and EncodeEnd events as a consequence of the previous change.- SakPOP.Canceled and SakSMTP.Canceled properties have been made read-only and SakPOP.Cancel and SakSMTP.Cancel procedures (or methods) have been added.- add a SakMsg.FillRawMail method that will fill the RawMail property with a rfc822 message based on the properties of SakMsg.- changed SakSMTP.Quit & SakPOP.Quit to Disconnect- deleted TAttachedFile.FileStream (redundant), use BodyBin- removed the function sak_getTempFileName (as it should no be trusted) use function sak_GetTempPath- the new SakIMAP component !, this make a pleasure to work with incoming emails (as you can have folders, etc). Note: the IMAP component has only been tested with the Uni. of Washington server, but it should work with any *STANDARD COMPLIANT* server. Anyways, the code of this component is very simple, so if you have problems, a look in the source code can enligthen you.3.0.1- fixed a brown paper type of bug.3.0.2- support the case where attachs do not come from files (Lars Karlslund)- minor bugfix in UUDecode function (Lars Karlslund)- if the SakMsg.Username is empty, do a VRFY command at the smtp server to try to get the full user name (sergio)- function TSakIMAP.GetFolderList (Peter Nagel)- function TSakIMAP.GetHierarchyDelim (Peter Nagel)- frustrated intent (ie. commented out) to remove memory leaks in POP, SMTP & IMAP destroy functions (Ronald Moesbergen)3.0.3- actually create (and free) the FolderList in sakIMAP (Neculau Andrei)- try to send the FQDM to the HELO command in SMTP (sergio)- commented out the VRFY command in SakSMTP, and cut the from address in the From field (in SakMsg), so if the username is empty, the SMTP server rewrite the from address in a complete way, with username & full address (sergio)- fix a minor bug in TBase64DecodingStream.Write function (Lars Karlslund)3.4.0- many, many improvements to the IMAP component by Peter Honan (I applied the patch with minor modifications, mainly to respect delphi coding standard, taking out the overloading, the selectFolder function was overcomplicated, etc)- FAQ updated (me)3.4.1- minimize the chance for two temporal messages stored on disk to collide (can be hit in previous versions if you run multiple instances of retrieveMessage at the same time)- FAQ updated.3.4.2- a new sak_CleanUpAddresses() implementation, by Knut Baardsen- better handling for temporal messages, suggested by Andrew- many improvements (including ACL -Access Control List) to the IMAP component by James Chaplin3.4.3- reverted to the old sak_CleanUpAddresses() implementation Knut‘s one is almost rigth, but don‘t let us use addresses without domains- add Headers.Clear before filling headers, by "Antonio Carlos Ribeiro Faria" com.br>3.5.0- add TSakMsg.LoadFromTextFile from Oak Chantosa- big jumbo mambo patch from James Chaplin first patch: 1) Operation timeout - OperationTimeout timeout for non-responding receive operations. 2) Forced abend - ForceAbend method that will disconnect and reset state. 3) Optional folder lists - AvFolderList and AvSUBFolderList provide alternatives to FolderList and SUBFolderList that ensure the lists do not contain inacessible folders ( flagged by the server ). 4) Folder name fix - Provided a function to "fix" folder names before submission. Currently it fixes names containing spaces. second patch: 1) Capability - Ask for server capabilities/extensions. 2) Noop - Basic noop command - updates message counts as well - preferred alternative to status. 3) Status - Explicit status command - generally useful for status of a non-selected mailbox. 4) Fetch - Retrieve message data. 5) FetchBody - Retrieve the body of the message. 6) ExamineFolder - A read-only select command. 7) CloseSelectedFolder - Close the currently selected folder. 8) Idle - RFC2177 extension - not implemented on very many servers. 9) Search - Search based on RFC2066 criteria. 10) UIDSearch - Search based on RFC2066 criteria - results are in UID form. 11) UIDStoreFlags - Store message flags based on UID. 12) UIDFetch - Fetch message data by UID. 13) UIDCopyMessageToFolder - Copy a message by UID. 14) Authenticate - Basic framework. Only plain authentication extension implemented. 15) CloseOnError - A new property that allows the user to turn off the default behaviour of disconnecting from the server when an IMAP error is received 16) Namespace - RFC2342 Namespace query command. 17) ListFullHierarchy - Property which allows a switch between "*" ( default ) or "%" as the wilcard for default folder/list methods. 18) List - Explicit list command in case it is needed. third patch: 1) fix problem with imapd 2001a, reported by Holger Mauermann. 2) remove all warnings.3.5.1- revert change to the base64 encoding routine.3.5.2- changes from James Chaplin: 1) TSakIMAP will now properly process non-numeric UIDs for messages ( there was a sak_StrWord2Int transform being used before - which always produced a 0 value for non-numeric UIDs ). 2) TSakIMAP.RetrieveMessageExt ( private method ) was modified to provide a retrieval by either MsgID or UID. 3) TSakIMAP.RetrieveMessageByUID was modified to use the slightly more efficient TSakIMAP.RetrieveMessageExt(UID) method specified in 2) above. I also made an update to the SakMIME.pas unit. The changes that were implemented are: 1) sak_Base64Encode - a basic Base64 encoder. String input and string output with the option for CRLF splitting. 2) sak_Base64Decode - a basic Base64 decoder. String input and string output with a control for CRLF interpretation. 3) sak_Base64Verify - a very basic Base64 string verifier.3.5.3- robustify and code cleanups by Paul Vernon.3.5.4- access violation fix by Paul Vernon.3.5.5- go back to good old trusty 3.5.23.5.6- this time, all the cleanup & fixes from Paul Vernon seems to work well.3.6.0- Paul Vernon latest minor fixes- added basic SMTP authentication, by Delfi and Antonio Carlos Ribeiro Faria3.6.1- fix a mayor bug when sending to many addresses (by sergio)3.7.0- add full support for html mails, by Paul Vernon. (The TAttachedFile now has an extra boolean property called embedded. This property lets you use the syntax in your HTML mails)- fix a weird typo for BCC fields- add Content-ID, by alejandro Castro- fix "_" characters in subject, regression fix.- cleanups all around, by Paul Vernon.- SMTP example updated to cope with html emails.**warning** from this version, the html part of mails will not be stored as attachments by default, if you want this behavior, you just do something like: aSakMsg := TSakMsg.Create( self); aSakMsg.HTMLAsAttachment := true; ...3.7.1- fix TSakMsg.PopulateList (Jalin)3.7.2 (codenamed "melissa")- fixed a bug when the Populatelist procedure got re-written in sakMsg. It wasn‘t populating the SendTo field if there was only one e-mail address... (Paul Vernon)3.7.3 - Congratulations to Sergio on the addition to his family. This release was made by Paul Vernon who has temporarily taken over the release functions for the SakMail components whilst Sergio spends time AFK!- The 3.7.2 bug fix added blank entries to the address lists. The PopulateList procedure has been re-written again to hopefully cope with any type of e-mail address formatting.- The SMTP example noted in 3.7.0 actually shipped with this release!3.7.4- Bugfix for detecting UUEncoded mails correctly. Previous versions processed MIME mails with the value ‘begin xyz‘ if it appeared at the beginning of a line as a UUEncoded mail when they should not have.- POP and SMTP connect procedures are now functions. Existing code is unaffected. However, you can now use the following code if (sakPOP.Connect) then begin end;- POP gracefully quits if it receives an error now by calling Disconnect correctly.3.7.5- Further code to improve identification of UUEncoded mails. Essentially looking for the end as well as the beginning to ensure that it is correct.- Code optimisation of certain UUEncoded mail id functions.- Fix to ensure that the body of a mail that is UUEncoded is not lost.- MIME-Version string introduced into TsakMsg component to help with UUEncoded mail identification.- SizeInBytes property altered to read private variable using a function. If the private variable is 0, the function reads the length of the FRawMail.Text property.- Fix to make sure that the filename is not overwritten by a blank value when parsing mail-headers.3.7.6- Fixed list index out of bounds error.- Added POP3 RSET call TSakPOP.Reset.3.7.7- Altered SizeInBytes and Octets values to return server-side size when d/l headers only and use actual size once the entire message is downloaded.- Fixed a bug in GetBasicHeaders where To and CC fields could be mishandled if the mail headers were formed in a particular way.4.0.0 beta- All methods are now wrapped in classes. sak_util is now included for backwards compatibility only.- Several changes to make sakMail thread safe including the introduction of Mutexes which are cross process safe. Critical sections were an option however, although mutexes are a little slower, they are much more effective when you aren‘t sure how the code is going to be deployed...- Made several changes to the way connections are tracked, now making better use of the underlying Delphi components own properties and functions.- Several bug fixes included from solutions posted on mailing lists. Including change to datetime function to respect local time separator. There are more including one that Adem re-raised.- Removed almost all pointers as per Adems suggestion. Makes for neater code.- Hopefully backwards compatibility is kept. This is one of the objectives of the excersice although, internally, the components no longer use any of the non-object based methods. Also some of the non-object based methods actually have been re-written to create an object use the instance of the original method and then destroy the object again. This introduces a minor overhead however, because the objects are discreet, the trade is for much better memory usage and greater thread safety.- Introduced an include file to define compiler directives. Currently there are two directives. One defines whether to use the VCL or not, the other defines whether or not to use the FastStrings components. - With the intoduction of the Include file, this allows the development of code that is optional for users. One of these such changed is the use of the FastStrings base64 decoder. If you install the FastStrings components and turn on the compiler directive, you should have no functional changes however, the base64 decoder routines should have a much higher performance rating. Tests clock in at over 2000% faster attachment decoding on a P4 1.8GHz machine. (1.2Mb file 1686mS native sak Base64 Decoder, 79mS using FastStrings!)- This version is being released as a beta as the changes are pretty drastic. If the code is deemed to be stable and backwards compatible then it will be re-released as v4.0.1 with no changes.4.0.1 beta- Fixed an issue where Range Checking highlighted that the Attachment b64 decode routine raise a Range Error if the line that was to be decoded was empty. i.e. ‘‘.- Introduced a compiler directive to turn off range checking in the sakMIME procedure TBase64DecodingStream.Write to make sure that it runs correctly as Range Checking causes issues in this function.4.0.2 beta- Changed MailDateToDateTime function to the one provided by DengZhaoHui with a few modifications as even though it has better date processing than the original it caused EConvertErrors with some non-rfc dates.- Added the compiler directive to allow the inclusion of MD5 components from the DCPCrypt suite of encryption components. This allows the components to do APOP and SMTP AUTH functions as specified in RFCs 2095, 2104, 2449 and 2554. {UseDCP} ***** NOTE: These functions are experimental as although they are RFC compliant, they have not been tested against a secure mail server yet... *****- Using EurekaLog during load testing of the POP mail component, found and fixed several AV‘s in sakMSG, sakMIME and sakPOP. Mainly simple mistakes that required re-ordering of code or more checks before trying to manipulate data.- Altered the sockets code to be more stable with some servers. The previous implementation was totally incompatible with SendMail NT v3.0.2.- Fix added to compensate for incorrect operation of Connected property in some versions of Delphi.- Altered GetMultiLineFieldBody as per Adems suggestion. Also took some of Adems code and added it to GetFieldValueFromLine as the escape characters can appear in single line headers as well as multi-line ones.- TClientSocket is deprecated in Delphi 7. This may be the next large change in the sakEmail components. - Updated distribution to include more RFC‘s regarding the message format, POP and IMAP and hashing functions for CRAM mechanisms.- Fixed the handling of redirected mails as created by Eudora.- Force PopulateList to clear the list before populating it again.- Created a Delphi 6 package file.4.0.3 - Fixed AUTHSMTP buffer initialisation error. (Dmitry G. Kozhinov and Gabi Slonto)- Improved identification of servers that do not support the UIDL command. A small overhead is intorduced on servers that do support the command and have several mails to download but the feature allows better interaction with those servers that do not support UIDL.- Priority is now reported correctly when an e-mail is being decoded rather than only being used when sending an e-mail.4.0.4- Fixed an issue with a malformed header in a mail sent from MS Word through an Exchange server- Added a couple of try...finally blocks to the sakIMAP component.- Altered the sakIMAP components connected function to mirror the more accurate sakPOP method.- Consolidated all compiler directives into sakDef.inc- Added versioning compiler directives to allow the compilation of sakemail under Delphi 4.- General tidying of code. 4.0.5- Created a Delphi 7 package- Added properties to the IMAP component to allow read access to the LocalAddr and LocalHost socket properties.- Bugfix to sakMsg PopulateList function where a comma separated list did not contain any spaces- Access violation in sakPOP component due to incorrect use of free,freeandnil and compiler directives4.0.6- Added several features to the IMAP components.- Tidied up SMTP authentication routines (Improved use of MD5 for authentication using DCP components)- Included capability to send messages without an SMTP server (using Indy DNS components for MX lookups)- Bugfix in message parsing to stop a recursion loop due to a malformed mail.4.0.7- Memory leaks found by Amos and Paul regarding the sakMsg and sakPOP units respectively.- Bug fixes to attachment save code including stripping out invalid .. sequences from filenames- Improved the GetConnectedState method to check against the RemoteHost value on the Socket.- Updated POP example to be more responsive when downloading mail. Fixed a memory leak.Don‘t forget to subscribe to the mailing list (see the web pages at http://groups.yahoo.com/group/sakemail/)
WAK Productions Presents: TRegware Shareware Security Component for Delphi Version 4.02 Copyright ?003 - WAK Productions ------------------------------------------------ Programmed by Winston Kotzan Email: wak@wakproductions.com Website URL: http://www.wakproductions.com/ This program helps developers of shareware include a timebomb/registration for their program. The end-user will enter a License ID and a serial number (like Winzip). If their registration information is correct, then the program becomes registered. TRegware hides data in the Windows registry to check if program was registered. If you have any difficulties using this component, suggestions, or compliments about this component, I would be glad to hear them! Please send an Email to wak@wakproductions.com. The more user responses received, the more TRegware can be improved to keep it the best shareware security component for Delphi developers! IF YOU HAVE A TECHNICAL QUESTION, PLEASE READ FAQ.TXT BEFORE SENDING AN EMAIL. THANK YOU! Release Notes ------------- Version 4.00 - NOTE THAT THE TREGWARE 4.00 ALGORITHM IS INCOMPATIBLE WITH PREVIOUS VERSIONS - New and revised demo programs included in distribution package Major revisions: - New feature allows an expiration date to be included in the registration code. This would help prevent the illegal spread of codes over a period of time. If a user enters a registration code beyond the expieration date, TRegware will not accept the code. - Now uses completely different, more secure algorithm. The registration code now consists of a combination of several code generating algorithms to make it harder for crackers to create keygens. - The TRegware class can no longer generate its own registration codes. To create registration codes use the TRegCodeGenerator class. (See demo program) - Now has option to use an expiration date in code. Check the documentation for more information. - Class name has been changed from TRegwareII to TRegware4 because of incompatibilities with past versions. - The TRegware class no longer has the ability to generate registration codes. The program now uses the function named E89CE8E0 to verify codes. Minor revisions: - Removed hard drive serial number related LicenseSource options. It was unreliable under Windows XP. - If the registry data is corrupted or unrecognized TRegware sets itself unregistered Version 3.20: - A set of compiler-time options are now available in the unit reg_opts.pas It is suggested to configure this file for each of your programs for greater security. Please read the comments in reg_opts.pas for further description. - Added Email property to contain user's email address. See DoRegistration() function documentation for details. - Licensing options (LicenseType, LicenseSource properties) have been moved to a special class, TLicenseOptions. They will now appear under the LicenseOptions property. LicenseOptions are only available in the professional edition. Version 3 of TRegware includes many features to improve its flexibility and security. In particular, TRegware has been modified to operate on Windows 2000 and XP systems. New features in version 3.0: - FSeed is now encrypted to protect from hackers. To turn this option off, remove the '$DEFINE HIDE_SEED' line from regware2.pas. Having this option on may cause TRegware to not recognize already existing registrations from previous versions. (Only available in source code edition) - Windows 2000 / XP registry is now supported. Information is stored under HKEY_CLASSES_ROOT for 2000/XP systems. - New ban-list features allows you to ban certain users from using the next version of your software - Added 1 second-delay for registration attempts to prevent cracking by brute-force. This option does not have a property to disable it so that it is a little more difficult to patch. - Added spaghetti code in CalculateCode() for the purpose of confusing hackers - Option to use system-generated license id (uses Windows system ID or hard drive serial #) - Option to set site-licenses and single-user licenses. New features in version 2.0: -Detects if the user attempted to deceive the timebomb by setting their computer's clock backwards. In this case, the component will signal an OnClockChange event and report that the program has expired. When the user decides to put his clock back within the remaining 'x' days of his evaluation period, the timebomb will continue to operate. -TRegware now comes packaged with a Perl file (regware200.pl) so that registration codes can be generated on a UNIX-based web server. You can use the Perl script if you would like to give registration codes to customers via a CGI program. Bug reports? Suggestions? Comments? Email to: wak@wakproductions.com or visit website http://www.wakproductions.com/
Contents Overview 1 Lesson 1: Concepts – Locks and Lock Manager 3 Lesson 2: Concepts – Batch and Transaction 31 Lesson 3: Concepts – Locks and Applications 51 Lesson 4: Information Collection and Analysis 63 Lesson 5: Concepts – Formulating and Implementing Resolution 81 Module 4: Troubleshooting Locking and Blocking Overview At the end of this module, you will be able to:  Discuss how lock manager uses lock mode, lock resources, and lock compatibility to achieve transaction isolation.  Describe the various transaction types and how transactions differ from batches.  Describe how to troubleshoot blocking and locking issues.  Analyze the output of blocking scripts and Microsoft® SQL Server™ Profiler to troubleshoot locking and blocking issues.  Formulate hypothesis to resolve locking and blocking issues. Lesson 1: Concepts – Locks and Lock Manager This lesson outlines some of the common causes that contribute to the perception of a slow server. What You Will Learn After completing this lesson, you will be able to:  Describe locking architecture used by SQL Server.  Identify the various lock modes used by SQL Server.  Discuss lock compatibility and concurrent access.  Identify different types of lock resources.  Discuss dynamic locking and lock escalation.  Differentiate locks, latches, and other SQL Server internal “locking” mechanism such as spinlocks and other synchronization objects. Recommended Reading  Chapter 14 “Locking”, Inside SQL Server 2000 by Kalen Delaney  SOX000821700049 – SQL 7.0 How to interpret lock resource Ids  SOX000925700237 – TITLE: Lock escalation in SQL 7.0  SOX001109700040 – INF: Queries with PREFETCH in the plan hold lock until the end of transaction Locking Concepts Delivery Tip Prior to delivering this material, test the class to see if they fully understand the different isolation levels. If the class is not confident in their understanding, review appendix A04_Locking and its accompanying PowerPoint® file. Transactions in SQL Server provide the ACID properties: Atomicity A transaction either commits or aborts. If a transaction commits, all of its effects remain. If it aborts, all of its effects are undone. It is an “all or nothing” operation. Consistency An application should maintain the consistency of a database. For example, if you defer constraint checking, it is your responsibility to ensure that the database is consistent. Isolation Concurrent transactions are isolated from the updates of other incomplete transactions. These updates do not constitute a consistent state. This property is often called serializability. For example, a second transaction traversing the doubly linked list mentioned above would see the list before or after the insert, but it will see only complete changes. Durability After a transaction commits, its effects will persist even if there are system failures. Consistency and isolation are the most important in describing SQL Server’s locking model. It is up to the application to define what consistency means, and isolation in some form is needed to achieve consistent results. SQL Server uses locking to achieve isolation. Definition of Dependency: A set of transactions can run concurrently if their outputs are disjoint from the union of one another’s input and output sets. For example, if T1 writes some object that is in T2’s input or output set, there is a dependency between T1 and T2. Bad Dependencies These include lost updates, dirty reads, non-repeatable reads, and phantoms. ANSI SQL Isolation Levels An isolation level determines the degree to which data is isolated for use by one process and guarded against interference from other processes. Prior to SQL Server 7.0, REPEATABLE READ and SERIALIZABLE isolation levels were synonymous. There was no way to prevent non-repeatable reads while not preventing phantoms. By default, SQL Server 2000 operates at an isolation level of READ COMMITTED. To make use of either more or less strict isolation levels in applications, locking can be customized for an entire session by setting the isolation level of the session with the SET TRANSACTION ISOLATION LEVEL statement. To determine the transaction isolation level currently set, use the DBCC USEROPTIONS statement, for example: USE pubs GO SET TRANSACTION ISOLATION LEVEL REPEATABLE READ GO DBCC USEROPTIONS GO Multigranular Locking Multigranular Locking In our example, if one transaction (T1) holds an exclusive lock at the table level, and another transaction (T2) holds an exclusive lock at the row level, each of the transactions believe they have exclusive access to the resource. In this scenario, since T1 believes it locks the entire table, it might inadvertently make changes to the same row that T2 thought it has locked exclusively. In a multigranular locking environment, there must be a way to effectively overcome this scenario. Intent lock is the answer to this problem. Intent Lock Intent Lock is the term used to mean placing a marker in a higher-level lock queue. The type of intent lock can also be called the multigranular lock mode. An intent lock indicates that SQL Server wants to acquire a shared (S) lock or exclusive (X) lock on some of the resources lower down in the hierarchy. For example, a shared intent lock placed at the table level means that a transaction intends on placing shared (S) locks on pages or rows within that table. Setting an intent lock at the table level prevents another transaction from subsequently acquiring an exclusive (X) lock on the table containing that page. Intent locks improve performance because SQL Server examines intent locks only at the table level to determine whether a transaction can safely acquire a lock on that table. This removes the requirement to examine every row or page lock on the table to determine whether a transaction can lock the entire table. Lock Mode The code shown in the slide represents how the lock mode is stored internally. You can see these codes by querying the master.dbo.spt_values table: SELECT * FROM master.dbo.spt_values WHERE type = N'L' However, the req_mode column of master.dbo.syslockinfo has lock mode code that is one less than the code values shown here. For example, value of req_mode = 3 represents the Shared lock mode rather than the Schema Modification lock mode. Lock Compatibility These locks can apply at any coarser level of granularity. If a row is locked, SQL Server will apply intent locks at both the page and the table level. If a page is locked, SQL Server will apply an intent lock at the table level. SIX locks imply that we have shared access to a resource and we have also placed X locks at a lower level in the hierarchy. SQL Server never asks for SIX locks directly, they are always the result of a conversion. For example, suppose a transaction scanned a page using an S lock and then subsequently decided to perform a row level update. The row would obtain an X lock, but now the page would require an IX lock. The resultant mode on the page would be SIX. Another type of table lock is a schema stability lock (Sch-S) and is compatible with all table locks except the schema modification lock (Sch-M). The schema modification lock (Sch-M) is incompatible with all table locks. Locking Resources Delivery Tip Note the differences between Key and Key Range locks. Key Range locks will be covered in a couple of slides. SQL Server can lock these resources: Item Description DB A database. File A database file Index An entire index of a table. Table An entire table, including all data and indexes. Extent A contiguous group of data pages or index pages. Page An 8-KB data page or index page. Key Row lock within an index. Key-range A key-range. Used to lock ranges between records in a table to prevent phantom insertions or deletions into a set of records. Ensures serializable transactions. RID A Row Identifier. Used to individually lock a single row within a table. Application A lock resource defined by an application. The lock manager knows nothing about the resource format. It simply compares the 'strings' representing the lock resources to determine whether it has found a match. If a match is found, it knows that resource is already locked. Some of the resources have “sub-resources.” The followings are sub-resources displayed by the sp_lock output: Database Lock Sub-Resources: Full Database Lock (default) [BULK-OP-DB] – Bulk Operation Lock for Database [BULK-OP-LOG] – Bulk Operation Lock for Log Table Lock Sub-Resources: Full Table Lock (default) [UPD-STATS] – Update statistics Lock [COMPILE] – Compile Lock Index Lock sub-Resources: Full Index Lock (default) [INDEX_ID] – Index ID Lock [INDEX_NAME] – Index Name Lock [BULK_ALLOC] – Bulk Allocation Lock [DEFRAG] – Defragmentation Lock For more information, see also… SOX000821700049 SQL 7.0 How to interpret lock resource Ids Lock Resource Block The resource type has the following resource block format: Resource Type (Code) Content DB (2) Data 1: sub-resource; Data 2: 0; Data 3: 0 File (3) Data 1: File ID; Data 2: 0; Data 3: 0 Index (4) Data 1: Object ID; Data 2: sub-resource; Data 3: Index ID Table (5) Data 1: Object ID; Data 2: sub-resource; Data 3: 0. Page (6) Data 1: Page Number; Data 3: 0. Key (7) Data 1: Object ID; Data 2: Index ID; Data 3: Hashed Key Extent (8) Data 1: Extent ID; Data 3: 0. RID (9) Data 1: RID; Data 3: 0. Application (10) Data 1: Application resource name The rsc_bin column of master..syslockinfo contains the resource block in hexadecimal format. For an example of how to decode value from this column using the information above, let us assume we have the following value: 0x000705001F83D775010002014F0BEC4E With byte swapping within each field, this can be decoded as: Byte 0: Flag – 0x00 Byte 1: Resource Type – 0x07 (Key) Byte 2-3: DBID – 0x0005 Byte 4-7: ObjectID – 0x 75D7831F (1977058079) Byte 8-9: IndexID – 0x0001 Byte 10-16: Hash Key value – 0x 02014F0BEC4E For more information about how to decode this value, see also… Inside SQL Server 2000, pages 803 and 806. Key Range Locking Key Range Locking To support SERIALIZABLE transaction semantics, SQL Server needs to lock sets of rows specified by a predicate, such as WHERE salary BETWEEN 30000 AND 50000 SQL Server needs to lock data that does not exist! If no rows satisfy the WHERE condition the first time the range is scanned, no rows should be returned on any subsequent scans. Key range locks are similar to row locks on index keys (whether clustered or not). The locks are placed on individual keys rather than at the node level. The hash value consists of all the key components and the locator. So, for a nonclustered index over a heap, where columns c1 and c2 where indexed, the hash would contain contributions from c1, c2 and the RID. A key range lock applied to a particular key means that all keys between the value locked and the next value would be locked for all data modification. Key range locks can lock a slightly larger range than that implied by the WHERE clause. Suppose the following select was executed in a transaction with isolation level SERIALIZABLE: SELECT * FROM members WHERE first_name between ‘Al’ and ‘Carl’ If 'Al', 'Bob', and 'Dave' are index keys in the table, the first two of these would acquire key range locks. Although this would prevent anyone from inserting either 'Alex' or 'Ben', it would also prevent someone from inserting 'Dan', which is not within the range of the WHERE clause. Prior to SQL Server 7.0, page locking was used to prevent phantoms by locking the entire set of pages on which the phantom would exist. This can be too conservative. Key Range locking lets SQL Server lock only a much more restrictive area of the table. Impact Key-range locking ensures that these scenarios are SERIALIZABLE:  Range scan query  Singleton fetch of nonexistent row  Delete operation  Insert operation However, the following conditions must be satisfied before key-range locking can occur:  The transaction-isolation level must be set to SERIALIZABLE.  The operation performed on the data must use an index range access. Range locking is activated only when query processing (such as the optimizer) chooses an index path to access the data. Key Range Lock Mode Again, the req_mode column of master.dbo.syslockinfo has lock mode code that is one less than the code values shown here. Dynamic Locking When modifying individual rows, SQL Server typically would take row locks to maximize concurrency (for example, OLTP, order-entry application). When scanning larger volumes of data, it would be more appropriate to take page or table locks to minimize the cost of acquiring locks (for example, DSS, data warehouse, reporting). Locking Decision The decision about which unit to lock is made dynamically, taking many factors into account, including other activity on the system. For example, if there are multiple transactions currently accessing a table, SQL Server will tend to favor row locking more so than it otherwise would. It may mean the difference between scanning the table now and paying a bit more in locking cost, or having to wait to acquire a more coarse lock. A preliminary locking decision is made during query optimization, but that decision can be adjusted when the query is actually executed. Lock Escalation When the lock count for the transaction exceeds and is a multiple of ESCALATION_THRESHOLD (1250), the Lock Manager attempts to escalate. For example, when a transaction acquired 1250 locks, lock manager will try to escalate. The number of locks held may continue to increase after the escalation attempt (for example, because new tables are accessed, or the previous lock escalation attempts failed due to incompatible locks held by another spid). If the lock count for this transaction reaches 2500 (1250 * 2), Lock Manager will attempt escalation again. The Lock Manager looks at the lock memory it is using and if it is more than 40 percent of SQL Server’s allocated buffer pool memory, it tries to find a scan (SDES) where no escalation has already been performed. It then repeats the search operation until all scans have been escalated or until the memory used drops under the MEMORY_LOAD_ESCALATION_THRESHOLD (40%) value. If lock escalation is not possible or fails to significantly reduce lock memory footprint, SQL Server can continue to acquire locks until the total lock memory reaches 60 percent of the buffer pool (MAX_LOCK_RESOURCE_MEMORY_PERCENTAGE=60). Lock escalation may be also done when a single scan (SDES) holds more than LOCK_ESCALATION_THRESHOLD (765) locks. There is no lock escalation on temporary tables or system tables. Trace Flag 1211 disables lock escalation. Important Do not relay this to the customer without careful consideration. Lock escalation is a necessary feature, not something to be avoided completely. Trace flags are global and disabling lock escalation could lead to out of memory situations, extremely poor performing queries, or other problems. Lock escalation tracing can be seen using the Profiler or with the general locking trace flag, -T1200. However, Trace Flag 1200 shows all lock activity so it should not be usable on a production system. For more information, see also… SOX000925700237 “TITLE: SQL 7.0 Lock escalation in SQL 7.0” Lock Timeout Application Lock Timeout An application can set lock timeout for a session with the SET option: SET LOCK_TIMEOUT N where N is a number of milliseconds. A value of -1 means that there will be no timeout, which is equivalent to the version 6.5 behavior. A value of 0 means that there will be no waiting; if a process finds a resource locked, it will generate error message 1222 and continue with the next statement. The current value of LOCK_TIMEOUT is stored in the global variable @@lock_timeout. Note After a lock timeout any transaction containing the statement, is rolled back or canceled by SQL Server 2000 (bug#352640 was filed). This behavior is different from that of SQL Server 7.0. With SQL Server 7.0, the application must have an error handler that can trap error 1222 and if an application does not trap the error, it can proceed unaware that an individual statement within a transaction has been canceled, and errors can occur because statements later in the transaction may depend on the statement that was never executed. Bug#352640 is fixed in hotfix build 8.00.266 whereby a lock timeout will only Internal Lock Timeout At time, internal operations within SQL Server will attempt to acquire locks via lock manager. Typically, these lock requests are issued with “no waiting.” For example, the ghost record processing might try to clean up rows on a particular page, and before it can do that, it needs to lock the page. Thus, the ghost record manager will request a page lock with no wait so that if it cannot lock the page, it will just move on to other pages; it can always come back to this page later. If you look at SQL Profiler Lock: Timeout events, internal lock timeout typically have a duration value of zero. Lock Duration Lock Mode and Transaction Isolation Level For REPEATABLE READ transaction isolation level, update locks are held until data is read and processed, unless promoted to exclusive locks. "Data is processed" means that we have decided whether the row in question matched the search criteria; if not then the update lock is released, otherwise, we get an exclusive lock and make the modification. Consider the following query: use northwind go dbcc traceon(3604, 1200, 1211) -- turn on lock tracing -- and disable escalation go set transaction isolation level repeatable read begin tran update dbo.[order details] set discount = convert (real, discount) where discount = 0.0 exec sp_lock Update locks are promoted to exclusive locks when there is a match; otherwise, the update lock is released. The sp_lock output verifies that the SPID does not hold any update locks or shared locks at the end of the query. Lock escalation is turned off so that exclusive table lock is not held at the end. Warning Do not use trace flag 1200 in a production environment because it produces a lot of output and slows down the server. Trace flag 1211 should not be used unless you have done extensive study to make sure it helps with performance. These trace flags are used here for illustration and learning purposes only. Lock Ownership Most of the locking discussion in this lesson relates to locks owned by “transactions.” In addition to transaction, cursor and session can be owners of locks and they both affect how long locks are held. For every row that is fetched, when SCROLL_LOCKS option is used, regardless of the state of a transaction, a cursor lock is held until the next row is fetched or when the cursor is closed. Locks owned by session are outside the scope of a transaction. The duration of these locks are bounded by the connection and the process will continue to hold these locks until the process disconnects. A typical lock owned by session is the database (DB) lock. Locking – Read Committed Scan Under read committed isolation level, when database pages are scanned, shared locks are held when the page is read and processed. The shared locks are released “behind” the scan and allow other transactions to update rows. It is important to note that the shared lock currently acquired will not be released until shared lock for the next page is successfully acquired (this is commonly know as “crabbing”). If the same pages are scanned again, rows may be modified or deleted by other transactions. Locking – Repeatable Read Scan Under repeatable read isolation level, when database pages are scanned, shared locks are held when the page is read and processed. SQL Server continues to hold these shared locks, thus preventing other transactions to update rows. If the same pages are scanned again, previously scanned rows will not change but new rows may be added by other transactions. Locking – Serializable Read Scan Under serializable read isolation level, when database pages are scanned, shared locks are held not only on rows but also on scanned key range. SQL Server continues to hold these shared locks until the end of transaction. Because key range locks are held, not only will this prevent other transactions from modifying the rows, no new rows can be inserted. Prefetch and Isolation Level Prefetch and Locking Behavior The prefetch feature is available for use with SQL Server 7.0 and SQL Server 2000. When searching for data using a nonclustered index, the index is searched for a particular value. When that value is found, the index points to the disk address. The traditional approach would be to immediately issue an I/O for that row, given the disk address. The result is one synchronous I/O per row and, at most, one disk at a time working to evaluate the query. This does not take advantage of striped disk sets. The prefetch feature takes a different approach. It continues looking for more record pointers in the nonclustered index. When it has collected a number of them, it provides the storage engine with prefetch hints. These hints tell the storage engine that the query processor will need these particular records soon. The storage engine can now issue several I/Os simultaneously, taking advantage of striped disk sets to execute multiple operations simultaneously. For example, if the engine is scanning a nonclustered index to determine which rows qualify but will eventually need to visit the data page as well to access columns that are not in the index, it may decide to submit asynchronous page read requests for a group of qualifying rows. The prefetch data pages are then revisited later to avoid waiting for each individual page read to complete in a serial fashion. This data access path requires that a lock be held between the prefetch request and the row lookup to stabilize the row on the page so it is not to be moved by a page split or clustered key update. For our example, the isolation level of the query is escalated to REPEATABLE READ, overriding the transaction isolation level. With SQL Server 7.0 and SQL Server 2000, portions of a transaction can execute at a different transaction isolation level than the entire transaction itself. This is implemented as lock classes. Lock classes are used to control lock lifetime when portions of a transaction need to execute at a stricter isolation level than the underlying transaction. Unfortunately, in SQL Server 7.0 and SQL Server 2000, the lock class is created at the topmost operator of the query and hence released only at the end of the query. Currently there is no support to release the lock (lock class) after the row has been discarded or fetched by the filter or join operator. This is because isolation level can be set at the query level via a lock class, but no lower. Because of this, locks acquired during the query will not be released until the query completes. If prefetch is occurring you may see a single SPID that holds hundreds of Shared KEY or PAG locks even though the connection’s isolation level is READ COMMITTED. Isolation level can be determined from DBCC PSS output. For details about this behavior see “SOX001109700040 INF: Queries with PREFETCH in the plan hold lock until the end of transaction”. Other Locking Mechanism Lock manager does not manage latches and spinlocks. Latches Latches are internal mechanisms used to protect pages while doing operations such as placing a row physically on a page, compressing space on a page, or retrieving rows from a page. Latches can roughly be divided into I/O latches and non-I/O latches. If you see a high number of non-I/O related latches, SQL Server is usually doing a large number of hash or sort operations in tempdb. You can monitor latch activities via DBCC SQLPERF(‘WAITSTATS’) command. Spinlock A spinlock is an internal data structure that is used to protect vital information that is shared within SQL Server. On a multi-processor machine, when SQL Server tries to access a particular resource protected by a spinlock, it must first acquire the spinlock. If it fails, it executes a loop that will check to see if the lock is available and if not, decrements a counter. If the counter reaches zero, it yields the processor to another thread and goes into a “sleep” (wait) state for a pre-determined amount of time. When it wakes, hopefully, the lock is free and available. If not, the loop starts again and it is terminated only when the lock is acquired. The reason for implementing a spinlock is that it is probably less costly to “spin” for a short time rather than yielding the processor. Yielding the processor will force an expensive context switch where:  The old thread’s state must be saved  The new thread’s state must be reloaded  The data stored in the L1 and L2 cache are useless to the processor On a single-processor computer, the loop is not useful because no other thread can be running and thus, no one can release the spinlock for the currently executing thread to acquire. In this situation, the thread yields the processor immediately. Lesson 2: Concepts – Batch and Transaction This lesson outlines some of the common causes that contribute to the perception of a slow server. What You Will Learn After completing this lesson, you will be able to:  Review batch processing and error checking.  Review explicit, implicit and autocommit transactions and transaction nesting level.  Discuss how commit and rollback transaction done in stored procedure and trigger affects transaction nesting level.  Discuss various transaction isolation level and their impact on locking.  Discuss the difference between aborting a statement, a transaction, and a batch.  Describe how @@error, @@transcount, and @@rowcount can be used for error checking and handling. Recommended Reading  Charter 12 “Transactions and Triggers”, Inside SQL Server 2000 by Kalen Delaney Batch Definition SQL Profiler Statements and Batches To help further your understanding of what is a batch and what is a statement, you can use SQL Profiler to study the definition of batch and statement.  Try This: Using SQL Profiler to Analyze Batch 1. Log on to a server with Query Analyzer 2. Startup the SQL Profiler against the same server 3. Start a trace using the “StandardSQLProfiler” template 4. Execute the following using Query Analyzer: SELECT @@VERSION SELECT @@SPID The ‘SQL:BatchCompleted’ event is captured by the trace. It shows both the statements as a single batch. 5. Now execute the following using Query Analyzer {call sp_who()} What shows up? The ‘RPC:Completed’ with the sp_who information. RPC is simply another entry point to the SQL Server to call stored procedures with native data types. This allows one to avoid parsing. The ‘RPC:Completed’ event should be considered the same as a batch for the purposes of this discussion. Stop the current trace and start a new trace using the “SQLProfilerTSQL_SPs” template. Issue the same command as outlines in step 5 above. Looking at the output, not only can you see the batch markers but each statement as executed within the batch. Autocommit, Explicit, and Implicit Transaction Autocommit Transaction Mode (Default) Autocommit mode is the default transaction management mode of SQL Server. Every Transact-SQL statement, whether it is a standalone statement or part of a batch, is committed or rolled back when it completes. If a statement completes successfully, it is committed; if it encounters any error, it is rolled back. A SQL Server connection operates in autocommit mode whenever this default mode has not been overridden by either explicit or implicit transactions. Autocommit mode is also the default mode for ADO, OLE DB, ODBC, and DB-Library. A SQL Server connection operates in autocommit mode until a BEGIN TRANSACTION statement starts an explicit transaction, or implicit transaction mode is set on. When the explicit transaction is committed or rolled back, or when implicit transaction mode is turned off, SQL Server returns to autocommit mode. Explicit Transaction Mode An explicit transaction is a transaction that starts with a BEGIN TRANSACTION statement. An explicit transaction can contain one or more statements and must be terminated by either a COMMIT TRANSACTION or a ROLLBACK TRANSACTION statement. Implicit Transaction Mode SQL Server can automatically or, more precisely, implicitly start a transaction for you if a SET IMPLICIT_TRANSACTIONS ON statement is run or if the implicit transaction option is turned on globally by running sp_configure ‘user options’ 2. (Actually, the bit mask 0x2 must be turned on for the user option so you might have to perform an ‘OR’ operation with the existing user option value.) See SQL Server 2000 Books Online on how to turn on implicit transaction under ODBC and OLE DB (acdata.chm::/ac_8_md_06_2g6r.htm). Transaction Nesting Explicit transactions can be nested. Committing inner transactions is ignored by SQL Server other than to decrements @@TRANCOUNT. The transaction is either committed or rolled back based on the action taken at the end of the outermost transaction. If the outer transaction is committed, the inner nested transactions are also committed. If the outer transaction is rolled back, then all inner transactions are also rolled back, regardless of whether the inner transactions were individually committed. Each call to COMMIT TRANSACTION applies to the last executed BEGIN TRANSACTION. If the BEGIN TRANSACTION statements are nested, then a COMMIT statement applies only to the last nested transaction, which is the innermost transaction. Even if a COMMIT TRANSACTION transaction_name statement within a nested transaction refers to the transaction name of the outer transaction, the commit applies only to the innermost transaction. If a ROLLBACK TRANSACTION statement without a transaction_name parameter is executed at any level of a set of nested transaction, it rolls back all the nested transactions, including the outermost transaction. The @@TRANCOUNT function records the current transaction nesting level. Each BEGIN TRANSACTION statement increments @@TRANCOUNT by one. Each COMMIT TRANSACTION statement decrements @@TRANCOUNT by one. A ROLLBACK TRANSACTION statement that does not have a transaction name rolls back all nested transactions and decrements @@TRANCOUNT to 0. A ROLLBACK TRANSACTION that uses the transaction name of the outermost transaction in a set of nested transactions rolls back all the nested transactions and decrements @@TRANCOUNT to 0. When you are unsure if you are already in a transaction, SELECT @@TRANCOUNT to determine whether it is 1 or more. If @@TRANCOUNT is 0 you are not in a transaction. You can also find the transaction nesting level by checking the sysprocess.open_tran column. See SQL Server 2000 Books Online topic “Nesting Transactions” (acdata.chm::/ac_8_md_06_66nq.htm) for more information. Statement, Transaction, and Batch Abort One batch can have many statements and one transaction can have multiple statements, also. One transaction can span multiple batches and one batch can have multiple transactions. Statement Abort Currently executing statement is aborted. This can be a bit confusing when you start talking about statements in a trigger or stored procedure. Let us look closely at the following trigger: CREATE TRIGGER TRG8134 ON TBL8134 AFTER INSERT AS BEGIN SELECT 1/0 SELECT 'Next command in trigger' END To fire the INSERT trigger, the batch could be as simple as ‘INSERT INTO TBL8134 VALUES(1)’. However, the trigger contains two statements that must be executed as part of the batch to satisfy the clients insert request. When the ‘SELECT 1/0’ causes the divide by zero error, a statement abort is issued for the ‘SELECT 1/0’ statement. Batch and Transaction Abort On SQL Server 2000 (and SQL Server 7.0) whenever a non-informational error is encountered in a trigger, the statement abort is promoted to a batch and transactional abort. Thus, in the example the statement abort for ‘select 1/0’ promotion results in an entire batch abort. No further statements in the trigger or batch will be executed and a rollback is issued. On SQL Server 6.5, the statement aborts immediately and results in a transaction abort. However, the rest of the statements within the trigger are executed. This trigger could return ‘Next command in trigger’ as a result set. Once the trigger completes the batch abort promotion takes effect. Conversely, submitting a similar set of statements in a standalone batch can result in different behavior. SELECT 1/0 SELECT 'Next command in batch' Not considering the set option possibilities, a divide by zero error generally results in a statement abort. Since it is not in a trigger, the promotion to a batch abort is avoided and subsequent SELECT statement can execute. The programmer should add an “if @@ERROR” check immediately after the ‘select 1/0’ to T-SQL execution to control the flow correctly. Aborting and Set Options ARITHABORT If SET ARITHABORT is ON, these error conditions cause the query or batch to terminate. If the errors occur in a transaction, the transaction is rolled back. If SET ARITHABORT is OFF and one of these errors occurs, a warning message is displayed, and NULL is assigned to the result of the arithmetic operation. When an INSERT, DELETE, or UPDATE statement encounters an arithmetic error (overflow, divide-by-zero, or a domain error) during expression evaluation when SET ARITHABORT is OFF, SQL Server inserts or updates a NULL value. If the target column is not nullable, the insert or update action fails and the user receives an error. XACT_ABORT When SET XACT_ABORT is ON, if a Transact-SQL statement raises a run-time error, the entire transaction is terminated and rolled back. When OFF, only the Transact-SQL statement that raised the error is rolled back and the transaction continues processing. Compile errors, such as syntax errors, are not affected by SET XACT_ABORT. For example: CREATE TABLE t1 (a int PRIMARY KEY) CREATE TABLE t2 (a int REFERENCES t1(a)) GO INSERT INTO t1 VALUES (1) INSERT INTO t1 VALUES (3) INSERT INTO t1 VALUES (4) INSERT INTO t1 VALUES (6) GO SET XACT_ABORT OFF GO BEGIN TRAN INSERT INTO t2 VALUES (1) INSERT INTO t2 VALUES (2) /* Foreign key error */ INSERT INTO t2 VALUES (3) COMMIT TRAN SELECT 'Continue running batch 1...' GO SET XACT_ABORT ON GO BEGIN TRAN INSERT INTO t2 VALUES (4) INSERT INTO t2 VALUES (5) /* Foreign key error */ INSERT INTO t2 VALUES (6) COMMIT TRAN SELECT 'Continue running batch 2...' GO /* Select shows only keys 1 and 3 added. Key 2 insert failed and was rolled back, but XACT_ABORT was OFF and rest of transaction succeeded. Key 5 insert error with XACT_ABORT ON caused all of the second transaction to roll back. Also note that 'Continue running batch 2...' is not Returned to indicate that the batch is aborted. */ SELECT * FROM t2 GO DROP TABLE t2 DROP TABLE t1 GO Compile and Run-time Errors Compile Errors Compile errors are encountered during syntax checks, security checks, and other general operations to prepare the batch for execution. These errors can prevent the optimization of the query and thus lead to immediate abort. The statement is not run and the batch is aborted. The transaction state is generally left untouched. For example, assume there are four statements in a particular batch. If the third statement has a syntax error, none of the statements in the batch is executed. Optimization Errors Optimization errors would include rare situations where the statement encounters a problem when attempting to build an optimal execution plan. Example: “too many tables referenced in the query” error is reported because a “work table” was added to the plan. Runtime Errors Runtime errors are those that are encountered during the execution of the query. Consider the following batch: SELECT * FROM pubs.dbo.titles UPDATE pubs.dbo.authors SET au_lname = au_lname SELECT * FROM foo UPDATE pubs.dbo.authors SET au_lname = au_lname If you run the above statements in a batch, the first two statements will be executed, the third statement will fail because table foo does not exist, and the batch will terminate. Deferred Name Resolution is the feature that allows this batch to start executing before resolving the object foo. This feature allows SQL Server to delay object resolution and place a “placeholder” in the query’s execution. The object referenced by the placeholder is resolved until the query is executed. In our example, the execution of the statement “SELECT * FROM foo” will trigger another compile process to resolve the name again. This time, error message 208 is returned. Error: 208, Level 16, State 1, Line 1 Invalid object name 'foo'. Message 208 can be encountered as a runtime or compile error depending on whether the Deferred Name Resolution feature is available. In SQL Server 6.5 this would be considered a compile error and on SQL Server 2000 (and SQL Server7.0) as a runtime error due to Deferred Name Resolution. In the following example, if a trigger referenced authors2, the error is detected as SQL Server attempts to execute the trigger. However, under SQL Server 6.5 the create trigger statement fails because authors2 does not exist at compile time. When errors are encountered in a trigger, generally, the statement, batch, and transaction are aborted. You should be able to observe this by running the following script in pubs database: Create table tblTest(iID int) go create trigger trgInsert on tblTest for INSERT as begin select * from authors select * from authors2 select * from titles end go begin tran select 'Before' insert into tblTest values(1) select 'After' go select @@TRANCOUNT go When run in a batch, the statement and the batch are aborted but the transaction remains active. The follow script illustrates this: begin tran select 'Before' select * from authors2 select 'After' go select @@TRANCOUNT go One other factor in a compile versus runtime error is implicit data type conversions. If you were to run the following statements on SQL Server 6.5 and SQL Server 2000 (and SQL Server 7.0): create table tblData(dtData datetime) go select 1 insert into tblData values(12/13/99) go On SQL Server 6.5, you get an error before execution of the batch begins so no statements are executed and the batch is aborted. Error: 206, Level 16, State 2, Line 2 Operand type clash: int is incompatible with datetime On SQL Server 2000, you get the default value (1900-01-01 00:00:00.000) inserted into the table. SQL Server 2000 implicit data type conversion treats this as integer division. The integer division of 12/13/99 is 0, so the default date and time value is inserted, no error returned. To correct the problem on either version is to wrap the date string with quotes. See Bug #56118 (sqlbug_70) for more details about this situation. Another example of a runtime error is a 605 message. Error: 605 Attempt to fetch logical page %S_PGID in database '%.*ls' belongs to object '%.*ls', not to object '%.*ls'. A 605 error is always a runtime error. However, depending on the transaction isolation level, (e.g. using the NOLOCK lock hint), established by the SPID the handling of the error can vary. Specifically, a 605 error is considered an ACCESS error. Errors associated with buffer and page access are found in the 600 series of errors. When the error is encountered, the isolation level of the SPID is examined to determine proper handling based on information or fatal error level. Transaction Error Checking Not all errors cause transactions to automatically rollback. Although it is difficult to determine exactly which errors will rollback transactions and which errors will not, the main idea here is that programmers must perform error checking and handle errors appropriately. Error Handling Raiserror Details Raiserror seems to be a source of confusion but is really rather simple. Raiserror with severity levels of 20 or higher will terminate the connection. Of course, when the connection is terminated a full rollback of any open transaction will immediately be instantiated by the SQL Server (except distributed transaction with DTC involved). Severity levels lower than 20 will simply result in the error message being returned to the client. They do not affect the transaction scope of the connection. Consider the following batch: use pubs begin tran update authors set au_lname = 'smith' raiserror ('This is bad', 19, 1) with log select @@trancount With severity set at 19, the 'select @@trancount' will be executed after the raiserror statement and will return a value of 1. If severity is changed to 20, then the select statement will not run and the connection is broken. Important Error handling must occur not only in T-SQL batches and stored procedures, but also in application program code. Transactions and Triggers (1 of 2) Basic behavior assumes the implicit transactions setting is set to OFF. This behavior makes it possible to identify business logic errors in a trigger, raise an error, rollback the action, and add an audit table entry. Logically, the insert to the audit table cannot take place before the ROLLBACK action and you would not want to build in the audit table insert into every applications error handler that violated the business rule of the trigger. For more information, see also… SQL Server 2000 Books Online topic “Rollbacks in stored procedure and triggers“ (acdata.chm::/ac_8_md_06_4qcz.htm) IMPLICIT_TRANSACTIONS ON Behavior The behavior of firing other triggers on the same table can be tricky. Say you added a trigger that checks the CODE field. Read only versions of the rows contain the code ‘RO’ and read/write versions use ‘RW.’ Whenever someone tries to delete a row with a code ‘RO’ the trigger issues the rollback and logs an audit table entry. However, you also have a second trigger that is responsible for cascading delete operations. One client could issue the delete without implicit transactions on and only the current trigger would execute and then terminate the batch. However, a second client with implicit transactions on could issue the same delete and the secondary trigger would fire. You end up with a situation in which the cascading delete operations can take place (are committed) but the initial row remains in the table because of the rollback operation. None of the delete operations should be allowed but because the transaction scope was restarted because of the implicit transactions setting, they did. Transactions and Triggers (2 of 2) It is extremely difficult to determine the execution state of a trigger when using explicit rollback statements in combination with implicit transactions. The RETURN statement is not allowed to return a value. The only way I have found to set the @@ERROR is using a ‘raiserror’ as the last execution statement in the last trigger to execute. If you modify the example, this following RAISERROR statement will set @@ERROR to 50000: CREATE TRIGGER trgTest on tblTest for INSERT AS BEGIN ROLLBACK INSERT INTO tblAudit VALUES (1) RAISERROR('This is bad', 14,1) END However, this value does not carry over to a secondary trigger for the same table. If you raise an error at the end of the first trigger and then look at @@ERROR in the secondary trigger the @@ERROR remains 0. Carrying Forward an Active/Open Transaction It is possible to exit from a trigger and carry forward an open transaction by issuing a BEGIN TRAN or by setting implicit transaction on and doing INSERT, UPDATE, or DELETE. Warning It is never recommended that a trigger call BEGIN TRANSACTION. By doing this you increment the transaction count. Invalid code logic, not calling commit transaction, can lead to a situation where the transaction count remains elevated upon exit of the trigger. Transaction Count The behavior is better explained by understanding how the server works. It does not matter whether you are in a transaction, when a modification takes place the transaction count is incremented. So, in the simplest form, during the processing of an insert the transaction count is 1. On completion of the insert, the server will commit (and thus decrement the transaction count). If the commit identifies the transaction count has returned to 0, the actual commit processing is completed. Issuing a commit when the transaction count is greater than 1 simply decrements the nested transaction counter. Thus, when we enter a trigger, the transaction count is 1. At the completion of the trigger, the transaction count will be 0 due to the commit issued at the end of the modification statement (insert). In our example, if the connection was already in a transaction and called the second INSERT, since implicit transaction is ON, the transaction count in the trigger will be 2 as long as the ROLLBACK is not executed. At the end of the insert, the commit is again issued to decrement the transaction reference count to 1. However, the value does not return to 0 so the transaction remains open/active. Subsequent triggers are only fired if the transaction count at the end of the trigger remains greater than or equal to 1. The key to continuation of secondary triggers and the batch is the transaction count at the end of a trigger execution. If the trigger that performs a rollback has done an explicit begin transaction or uses implicit transactions, subsequent triggers and the batch will continue. If the transaction count is not 1 or greater, subsequent triggers and the batch will not execute. Warning Forcing the transaction count after issuing a rollback is dangerous because you can easily loose track of your transaction nesting level. When performing an explicit rollback in a trigger, you should immediately issue a return statement to maintain consistent behavior between a connection with and without implicit transaction settings. This will force the trigger(s) and batch to terminate immediately. One of the methods of dealing with this issue is to run ‘SET IMPLICIT_TRANSACTIONS OFF’ as the first statement of any trigger. Other methods may entails checking @@TRANCOUNT at the end of the trigger and continue to COMMIT the transaction as long as @@TRANCOUNT is greater than 1. Examples The following examples are based on this table: create table tbl50000Insert (iID int NOT NULL) go Note If more than one trigger is used, to guarantee the trigger firing sequence, the sp_settriggerorder command should be used. This command is omitted in these examples to simplify the complexity of the statements. First Example In the first example, the second trigger was never fired and the batch, starting with the insert statement, was aborted. Thus, the print statement was never issued. print('Trigger issues rollback - cancels batch') go create trigger trg50000Insert on tbl50000Insert for INSERT as begin select 'Inserted', * from inserted rollback tran select 'End of trigger', @@TRANCOUNT as 'TRANCOUNT' end go create trigger trg50000Insert2 on tbl50000Insert for INSERT as begin select 'In Trigger2' select 'Trigger 2 Inserted', * from inserted end go insert into tbl50000Insert values(1) print('---------------------- In same batch') select * from tbl50000Insert go -- Cleanup drop trigger trg50000Insert drop trigger trg50000Insert2 go delete from tbl50000Insert Second Example The next example shows that since a new transaction is started, the second trigger will be fired and the print statement in the batch will be executed. Note that the insert is rolled back. print('Trigger issues rollback - increases tran count to continue batch') go create trigger trg50000Insert on tbl50000Insert for INSERT as begin select 'Inserted', * from inserted rollback tran begin tran end go create trigger trg50000Insert2 on tbl50000Insert for INSERT as begin select 'In Trigger2' select 'Trigger 2 Inserted', * from inserted end go insert into tbl50000Insert values(2) print('---------------------- In same batch') select * from tbl50000Insert go -- Cleanup drop trigger trg50000Insert drop trigger trg50000Insert2 go delete from tbl50000Insert Third Example In the third example, the raiserror statement is used to set the @@ERROR value and the BEGIN TRAN statement is used in the trigger to allow the batch to continue to run. print('Trigger issues rollback - uses raiserror to set @@ERROR') go create trigger trg50000Insert on tbl50000Insert for INSERT as begin select 'Inserted', * from inserted rollback tran begin tran -- Increase @@trancount to allow -- batch to continue select @@trancount as ‘Trancount’ raiserror('This is from the trigger', 14,1) end go insert into tbl50000Insert values(3) select @@ERROR as 'ERROR', @@TRANCOUNT as 'Trancount' go -- Cleanup drop trigger trg50000Insert go delete from tbl50000Insert Fourth Example For the fourth example, a second trigger is added to illustrate the fact that @@ERROR value set in the first trigger will not be seen in the second trigger nor will it show up in the batch after the second trigger is fired. print('Trigger issues rollback - uses raiserror to set @@ERROR, not seen in second trigger and cleared in batch') go create trigger trg50000Insert on tbl50000Insert for INSERT as begin select 'Inserted', * from inserted rollback begin tran -- Increase @@trancount to -- allow batch to continue select @@TRANCOUNT as 'Trancount' raiserror('This is from the trigger', 14,1) end go create trigger trg50000Insert2 on tbl50000Insert for INSERT as begin select @@ERROR as 'ERROR', @@TRANCOUNT as 'Trancount' end go insert into tbl50000Insert values(4) select @@ERROR as 'ERROR', @@TRANCOUNT as 'Trancount' go -- Cleanup drop trigger trg50000Insert drop trigger trg50000Insert2 go delete from tbl50000Insert Lesson 3: Concepts – Locks and Applications This lesson outlines some of the common causes that contribute to the perception of a slow server. What You Will Learn After completing this lesson, you will be able to:  Explain how lock hints are used and their impact.  Discuss the effect on locking when an application uses Microsoft Transaction Server.  Identify the different kinds of deadlocks including distributed deadlock. Recommended Reading  Charter 14 “Locking”, Inside SQL Server 2000 by Kalen Delaney  Charter 16 “Query Tuning”, Inside SQL Server 2000 by Kalen Delaney Q239753 – Deadlock Situation Not Detected by SQL Server Q288752 – Blocked SPID Not Participating in Deadlock May Incorrectly be Chosen as victim Locking Hints UPDLOCK If update locks are used instead of shared locks while reading a table, the locks are held until the end of the statement or transaction. UPDLOCK has the advantage of allowing you to read data (without blocking other readers) and update it later with the assurance that the data has not changed since you last read it. READPAST READPAST is an optimizer hint for use with SELECT statements. When this hint is used, SQL Server will read past locked rows. For example, assume table T1 contains a single integer column with the values of 1, 2, 3, 4, and 5. If transaction A changes the value of 3 to 8 but has not yet committed, a SELECT * FROM T1 (READPAST) yields values 1, 2, 4, 5. Tip READPAST only applies to transactions operating at READ COMMITTED isolation and only reads past row-level locks. This lock hint can be used to implement a work queue on a SQL Server table. For example, assume there are many external work requests being thrown into a table and they should be serviced in approximate insertion order but they do not have to be completely FIFO. If you have 4 worker threads consuming work items from the queue they could each pick up a record using read past locking and then delete the entry from the queue and commit when they're done. If they fail, they could rollback, leaving the entry on the queue for the next worker thread to pick up. Caution The READPAST hint is not compatible with HOLDLOCK.  Try This: Using Locking Hints 1. Open a Query Window and connect to the pubs database. 2. Execute the following statements (--Conn 1 is optional to help you keep track of each connection): BEGIN TRANSACTION -- Conn 1 UPDATE titles SET price = price * 0.9 WHERE title_id = 'BU1032' 3. Open a second connection and execute the following statements: SELECT @@lock_timeout -- Conn 2 GO SELECT * FROM titles SELECT * FROM authors 4. Open a third connection and execute the following statements: SET LOCK_TIMEOUT 0 -- Conn 3 SELECT * FROM titles SELECT * FROM authors 5. Open a fourth connection and execute the following statement: SELECT * FROM titles (READPAST) -- Conn 4 WHERE title_ID < 'C' SELECT * FROM authors How many records were returned? 3 6. Open a fifth connection and execute the following statement: SELECT * FROM titles (NOLOCK) -- Conn 5 WHERE title_ID 0 the lock manager also checks for deadlocks every time a SPID gets blocked. So a single deadlock will trigger 20 seconds of more immediate deadlock detection, but if no additional deadlocks occur in that 20 seconds, the lock manager no longer checks for deadlocks at each block and detection again only happens every 5 seconds. Although normally not needed, you may use trace flag -T1205 to trace the deadlock detection process. Note Please note the distinction between application lock and other locks’ deadlock detection. For application lock, we do not rollback the transaction of the deadlock victim but simply return a -3 to sp_getapplock, which the application needs to handle itself. Deadlock Resolution How is a deadlock resolved? SQL Server picks one of the connections as a deadlock victim. The victim is chosen based on either which is the least expensive transaction (calculated using the number and size of the log records) to roll back or in which process “SET DEADLOCK_PRIORITY LOW” is specified. The victim’s transaction is rolled back, held locks are released, and SQL Server sends error 1205 to the victim’s client application to notify it that it was chosen as a victim. The other process can then obtain access to the resource it was waiting on and continue. Error 1205: Your transaction (process ID #%d) was deadlocked with another process and has been chosen as the deadlock victim. Rerun your transaction. Symptoms of deadlocking Error 1205 usually is not written to the SQL Server errorlog. Unfortunately, you cannot use sp_altermessage to cause 1205 to be written to the errorlog. If the client application does not capture and display error 1205, some of the symptoms of deadlock occurring are:  Clients complain of mysteriously canceled queries when using certain features of an application.  May be accompanied by excessive blocking. Lock contention increases the chances that a deadlock will occur. Triggers and Deadlock Triggers promote the deadlock priority of the SPID for the life of the trigger execution when the DEADLOCK PRIORITY is not set to low. When a statement in a trigger causes a deadlock to occur, the SPID executing the trigger is given preferential treatment and will not become the victim. Warning Bug 235794 is filed against SQL Server 2000 where a blocked SPID that is not a participant of a deadlock may incorrectly be chosen as a deadlock victim if the SPID is blocked by one of the deadlock participants and the SPID has the least amount of transaction logging. See KB article Q288752: “Blocked Spid Not Participating in Deadlock May Incorrectly be Chosen as victim” for more information. Distributed Deadlock – Scenario 1 Distributed Deadlocks The term distributed deadlock is ambiguous. There are many types of distributed deadlocks. Scenario 1 Client application opens connection A, begins a transaction, acquires some locks, opens connection B, connection B gets blocked by A but the application is designed to not commit A’s transaction until B completes. Note SQL Server has no way of knowing that connection A is somehow dependent on B – they are two distinct connections with two distinct transactions. This situation is discussed in scenario #4 in “Q224453 INF: Understanding and Resolving SQL Server 7.0 Blocking Problems”. Distributed Deadlock – Scenario 2 Scenario 2 Distributed deadlock involving bound connections. Two connections can be bound into a single transaction context with sp_getbindtoken/sp_bindsession or via DTC. Spid 60 enlists in a transaction with spid 61. A third spid 62 is blocked by spid 60, but spid 61 is blocked by spid 62. Because they are doing work in the same transaction, spid 60 cannot commit until spid 61 finishes his work, but spid 61 is blocked by 62 who is blocked by 60. This scenario is described in article “Q239753 - Deadlock Situation Not Detected by SQL Server.” Note SQL Server 6.5 and 7.0 do not detect this deadlock. The SQL Server 2000 deadlock detection algorithm has been enhanced to detect this type of distributed deadlock. The diagram in the slide illustrates this situation. Resources locked by a spid are below that spid (in a box). Arrows indicate blocking and are drawn from the blocked spid to the resource that the spid requires. A circle represents a transaction; spids in the same transaction are shown in the same circle. Distributed Deadlock – Scenario 3 Scenario 3 Distributed deadlock involving linked servers or server-to-server RPC. Spid 60 on Server 1 executes a stored procedure on Server 2 via linked server. This stored procedure does a loopback linked server query against a table on Server 1, and this connection is blocked by a lock held by Spid 60. Note No version of SQL Server is currently designed to detect this distributed deadlock. Lesson 4: Information Collection and Analysis This lesson outlines some of the common causes that contribute to the perception of a slow server. What You Will Learn After completing this lesson, you will be able to:  Identify specific information needed for troubleshooting issues.  Locate and collect information needed for troubleshooting issues.  Analyze output of DBCC Inputbuffer, DBCC PSS, and DBCC Page commands.  Review information collected from master.dbo.sysprocesses table.  Review information collected from master.dbo.syslockinfo table.  Review output of sp_who, sp_who2, sp_lock.  Analyze Profiler log for query usage pattern.  Review output of trace flags to help troubleshoot deadlocks. Recommended Reading Q244455 - INF: Definition of Sysprocesses Waittype and Lastwaittype Fields Q244456 - INF: Description of DBCC PSS Command for SQL Server 7.0 Q271509 - INF: How to Monitor SQL Server 2000 Blocking Q251004 - How to Monitor SQL Server 7.0 Blocking Q224453 - Understanding and Resolving SQL Server 7.0 Blocking Problem Q282749 – BUG: Deadlock information reported with SQL Server 2000 Profiler Locking and Blocking  Try This: Examine Blocked Processes 1. Open a Query Window and connect to the pubs database. Execute the following statements: BEGIN TRAN -- connection 1 UPDATE titles SET price = price + 1 2. Open another connection and execute the following statement: SELECT * FROM titles-- connection 2 3. Open a third connection and execute sp_who; note the process id (spid) of the blocked process. (Connection 3) 4. In the same connection, execute the following: SELECT spid, cmd, waittype FROM master..sysprocesses WHERE waittype 0 -- connection 3 5. Do not close any of the connections! What was the wait type of the blocked process?  Try This: Look at locks held Assumes all your connections are still open from the previous exercise. • Execute sp_lock -- Connection 3 What locks is the process from the previous example holding? Make sure you run ROLLBACK TRAN in Connection 1 to clean up your transaction. Collecting Information See Module 2 for more about how to gather this information using various tools. Recognizing Blocking Problems How to Recognize Blocking Problems  Users complain about poor performance at a certain time of day, or after a certain number of users connect.  SELECT * FROM sysprocesses or sp_who2 shows non-zero values in the blocked or BlkBy column.  More severe blocking incidents will have long blocking chains or large sysprocesses.waittime values for blocked spids.  Possibl

609

社区成员

发帖
与我相关
我的任务
社区描述
PowerBuilder DataWindow
社区管理员
  • DataWindow社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧