Btrieve ® Winter Developer’s Journal (Jan-March 1994) Vol. II No. 1

THE INDEPENDENT SOURCE OF NEWS AND INFORMATION FOR BTRIEVE DEVELOPERS AND USERS

When we began working on the idea of creating In March of 1993, an article called Inside Btrieve Files BTRIEVE DEVELOPER’S JOURNAL last year, we never was published in Dr. Dobb’s Journal by Doug Reilly. In his realized what a large void we would fill by publishing infor- original article, Doug explored the internal structure of Btrieve mation written specifically for people who develop and use files to demonstrate various methods of Btrieve data recovery. Btrieve applications. Since the distribution of our free premier We are pleased that we have been given the opportunity to issue to our list of over 32,000 active Btrieve developers, we show you more of what we have discovered about Btrieve files have had a large number of positive comments about our and possible data recovery methods. actively promoting Btrieve. We also received many subscrip- I can’t begin to tell you how excited we are about what’s tions, including yours, for which I am very grateful. We cannot going on with Btrieve for 1994… There is a lot of information continue to promote Btrieve without your continued support. and activity about Btrieve that you will not find anywhere else With BTRIEVE DEVELOPER’S JOURNAL, we are but in BTRIEVE DEVELOPER’S JOURNAL. We know that working hard to strike an even balance between articles of a you will not want to miss it! technical nature and those articles that focus on products with Btrieve support. We want to present information to those of you who are technically oriented and also to users of Btrieve applications who are interested in products that will allow them to make better use of the information stored in their Scott A. Smith Btrieve applications. Publisher This issue of BTRIEVE DEVELOPER’S JOURNAL focuses on one of the most asked questions with respect to Btrieve products: “What report writer should I use to access IN THIS ISSUE my Btrieve data.” Our Report Writer Roundup section takes a look at seven commercial report writers that can make orga- Btrieve Announcement… nized sense out of information in Btrieve files. From those Novell has announced plans to spin off their database products into a new company that are Windows applications to those which are character- headed by Doug and Nancy Woodward called Btrieve Technologies, Inc. Read all about how this will affect the future of Btrieve, and YOU as a Btrieve user...... Page 3 based DOS applications, you will be able to choose the best tool available to manipulate your Btrieve data. Btrieve News... We begin our technical analysis of Btrieve with Doug Doug Woodward reports on the Btrieve Developer’s Kit for Windows version 6.1 and the status of BTRIEVE.EXE... Plus more product news from Reilly’s Inside Btrieve column that explores Btrieve file com- the Btrieve marketplace...... Page 2 pression. How does compression work and how is it activated in various Btrieve environments? What are the pitfalls of com- Report Writer Roundup... pression? How does compression affect Btrieve’s perfor- We take a look at seven commercial report writers that make organized sense out of information in Btrieve files ...... Page 5 mance, reliability, and error recovery? BTRIEVE DEVELOPER’S JOURNAL Editor, Steve Inside Btrieve... Mook, begins a new column called Data Types: Ins and Outs Doug Reilly explores Btrieve file compression ...... Page 19 that explores how to decode data stored in Btrieve files using Data Types: Ins and Outs... the different data types that Btrieve applications may use. Steve Mook explains how to decode data stored in Btrieve files Steve also explores the new features of Btrieve version 6.1 in using different Btrieve data types...... Page 11 his special feature, What’s New in Btrieve. DDF’s Explained... In my DDF’s Explained special feature, I explain every- Scott Smith details the structure of the files that make up the thing that we know about the structure of the much asked Btrieve Data Dictionary File set...... Page 16 about, and little known, Btrieve Data Dictionary Files. You What’s New in Btrieve... will know the structure of the files that make up the standard Steve Mook takes a close look at what is new in Btrieve version 6.1...... Page 20 DDF set, how to read and create them yourself, and about the Btrieve Recovery Techniques... new extended DDF set that has been created to support addi- We make the first detailed analysis of the internal structure of tional non-standard Btrieve data types and field comments. Btrieve files to explore various methods of data recovery ...... Page 23 NEWS FROM NOVELL AUSTIN... According to Doug Woodward, Novell’s Vice President of Advanced Technology for Database Products, they are getting good results for the latest round of beta testing on the new local DLL for Windows, WBTRCALL.DLL, that will support Btrieve version 6.x files. Look for the product to be released in the early to mid portion of the second quarter of 1994. On the EXE front, Doug said that the new EXE version of Btrieve that will support the 6.x format is currently in Alpha testing at Novell. Apparently, the new EXE will be making a mid-year debut after the testing cycle is complete. Doug also hinted that we should be ready to see a lot of new positive activity for the Btrieve product line in 1994. Low-end Windows Accounting tool ships... There is a new arrival in the crowded accounting software field: Zebra Express from the product’s namesake, Zebra Express, Inc. of Tampa, Florida. In addition to being Btrieve-based, Zebra Express was written in 2.0, and includes general ledger, accounts receivable, and six other modules. The package sells for $399.95. Zebra Express may be reached at (813) 888-7500. HP prepares to ship its PA-RISC server with support for PIN and Btrieve... HP will release in the first quarter of 1994 a network super-server that is based on its PA-RISC microprocessor and that will support Novell’s Processor Independent NetWare (PIN) network operating system. The server and operating system will provide an alternative to ’s platforms. The server is code-named “Piranha” and will be released with a version of PIN. The “Piranha” will support about 1,000 users and prices will start at less than $10,000 for a 100-MHz version with 32 MB of memory and 2 GB of storage. More than 50 Novell NLMs, including Btrieve, should be available for HP’s PIN server when it ships. HP can be reached at (800) 637-7740. Platinum Software Announces Platinum for Windows... Platinum Software Corporation has unveiled the Windows version of its Platinum line called “Platinum for Windows.” The accounting package, which is set for release during the second quarter of 1994, is intended for users who require a strong LAN-based system and a Windows front end without the SQL database option that comes with the company’s client/server “SeQueL To Platinum” series. Prices will range from $1,500 to $15,000. Platinum for Windows continues Platinum’s traditional use of Btrieve as its record manager. Platinum of Atlanta, Georgia may be reached at (404) 392-4237. New Forms Generation Software Supports Btrieve... WordPerfect Corporation’s InForms is a versatile forms generation package which features a variety of options for creating on-line or printed forms and for linking these forms to a number of popular databases, including Btrieve. Controls such as action buttons, radio buttons and drop-down lists are included for on-line forms. InForms version 1.0 is priced at $495. WordPerfect of Orem, Utah may be reached at (801) 225-5000. NLM’s Backup Open Btrieve Files... Emeritus Technologies and Cheyenne Software have improved their backup NLM’s for NetWare servers. Emeritus Technologies has released version 4.2 of TapeWare/LAN-NLM, its backup-and-restore software. In addition to several new features, this version supports Btrieve 6.0 open-file database backup and NetWare 4.x Directory Service support. List prices range from $299 to $1,299. Contact Emeritus Technologies, Inc. at (800) 228-9236. The Btrieve Database Agent Option for ARCserve by Cheyenne Software ensures data integrity by utilizing Btrieve’s continuous mode operations. Price ranges from $495 to $4995. Reach Cheyenne at (516) 484-5110.

Btrieve Developer’s Journal Btrieve Numbers: Btrieve Developer’s Journal (ISSN 1071-7463) is published BDJ Phone: 615-860-3500 quarterly by SMITHWARE, Inc. BDJ FAX: 615-665-2383 Subscriptions: $49/year inside the United States. $79/year BDJ CompuServe Account: 73173,2731 outside the United States. Payment is acceptable via check or Novell Developer Support: 800-638-9273 money order, MasterCard, Visa, or American Express, or by 801-429-5588 Purchase Order for approved accounts. Send payment informa- tion to Btrieve Developer’s Journal Subscriptions Post Office Novell Support FAX: 512-794-1775 Box 50002, Nashville, TN 37205 FAX: (615) 665-2383. Novell CompuServe Account: 76701,171 MCI Mail: 590-5654 Back Issues: Back issues of Btrieve Developer’s Journal are Address: You may address news items, new product announcements, tips, advice, available for $20.00 per issue. Contact Cindi Gourley at comments, or any other correspondence to: Btrieve Developer’s Journal, Post (615) 860-3500 for more information. Office Box 50002, 713 Lynnwood Blvd., Nashville, TN 37205. Postmaster: First class postage paid at Nashville, TN Send address changes to: Staff: Publisher: Scott Smith Btrieve Developer’s Journal Circulation Control Post Office Box 50002, Editor: Steve Mook Nashville, TN 37205. Contributor: Doug Reilly Copyright 1994, SMITHWARE, Inc. All rights reserved. Graphic Design: Tania Owen Novell, Btrieve, NetWare, and XQL are registered trademarks, and NetWare SQL, Administration: Cindi Gourley NetWare Btrieve, and Xtrieve Plus are trademarks of Novell, Inc. Editorial Director: Rans Coyote Btrieve Developer’s Journal is published by SMITHWARE, Inc. and is not affiliated with Novell, Inc.

2 Novell to Transfer Btrieve Product Line to Btrieve Technologies, Inc.

On January 26, 1994, Novell announced the signing of a memorandum depend on a close relationship with the Btrieve developer community for direc- of understanding with Btrieve Technologies, Inc. to transfer its database software tion on product enhancements and support requirements.” product line to the newly-formed Austin, Texas based company. The company plans to expand and enhance its product line, with a strate- Novell will continue to ship and bundle the Btrieve NLM as part of gic emphasis on high performance, high availability, multi-platform and cross- NetWare and future Novell products and will retain a 15 percent ownership platform support, scalability, and remote database support. Harris stated that interest in the new company. Btrieve Technologies is a privately held company Btrieve Technologies will be first and foremost a marketing company whose founded last year by former Novell employees including the original developers strategy will be to enhance and develop those products that serve an identified of Btrieve. The two companies expect to reach a final agreement within the next customer need. eight weeks. Key database personnel from Novell are expected to join the new Btrieve Technologies plans to solicit continual feedback from its customer company following execution of the definitive agreement. base to ensure that its current products address customer needs and that future According to Richard W. King, Executive Vice President and General products will meet their requirements. Manager of Novell’s NetWare Systems Group, “Deciding how to support cus- Technical support services for all of Novell’s current database products will tomer needs, maintaining our focus on Novell’s core business and creating also be transferred to Btrieve Technologies once the agreement is finalized. strong partnerships are the primary forces shaping growth at Novell. This part- Other plans include the development of an Authorized Reseller Program that it nership will complement our other partnerships with leading computer industry hopes will ensure continuous communication, technical support, product evalua- database vendors. The Btrieve Technologies group has the vision, experience and tion and availability, training and lead referral. specialized focus to support customer and industry partners that rely on the Btrieve Technologies may be contacted at (800) 933-2023 or by FAX Btrieve standard.” at (512) 794-1711. The company is located at 5918 West Courtyard Drive In a simultaneous announcement from Btrieve Technologies, company offi- #344 Austin, TX 78730 cials stated that the agreement would pave the way to build, enhance, and extend the database product line in new directions and on new platforms. “With Editors note: With this issue, Btrieve Developer’s Journal has included a letter of introduction our vision, creativity, and customer commitment, the true beneficiaries will be from Ron Harris, President and CEO of Btrieve Technologies, Inc. Also enclosed is a list of ques- tions that Btrieve Technologies would like for you to answer in order to help them formulate their the hundreds of thousands of professional developers and end users who plans for the future of Btrieve. Please send us your responses as soon as possible so that you can depend on Btrieve and NetWare SQL for their data and information manage- be a part of this exciting opportunity to help shape the future of Btrieve. ment needs,” said Nancy Woodward, Chairman of Btrieve Technologies. Look forward to the next issue of Btrieve Developer’s Journal which will pre- Ron Harris, Btrieve Technologies’ President and CEO, added, “Broadening sent an interview with Ron Harris and Nancy Woodward about many aspects the product line and accelerating its development will be our top priority. We will of Btrieve Technologies, Inc.

The Illustrated the ins and outs of Btrieve and challenge your knowledge and programming skills. Add the optional Tutorial Disk, Guide to Btrieve which includes example programs in machine-readable for Maximum Database Growth Potential form and Btrieve function executor to directly interact with Master Btrieve, Novell’s super powerful database Btrieve as you learn. engine, with The Illustrated Guide to Btrieve. This compre- You will learn: hensive guidebook uses detailed illustrations and coding • Where Btrieve came from and how it fits in with other Novell examples to help you understand the real power, flexibility, developers’ products and high performance of Btrieve. • How Btrieve can be accessed from virtually any programming language The Illustrated Guide to Btrieve tells the whole story of • All about NetWare Btrieve, Btrieve for DOS, Windows, and OS/2 Btrieve. You will understand why over 40,000 software • How files are organized developers have chosen Btrieve as their database engine • How Btrieve is most efficiently used in network computing and why Novell ships Btrieve with every copy of NetWare. • The fundamentals of indexing Each Btrieve operation is highlighted in detail giving • Advanced file access techniques you all the information necessary to begin developing high • How to develop true multi-user applications • How to use extended operations to gain optimal network performance performance database programs. Example programs in C, • Server-based Btrieve programming with NLM’s (NetWare COBOL, BASIC and Pascal are all included. Whether you are Loadable Module) a programmer already using Btrieve, a software developer Order The Illustrated Guide to Btrieve for Only considering Btrieve, or a computer aficionado wishing to $29.95 and the Tutorial Disk for only $19.95 learn more about distributed database technology, The Illustrated Guide to Btrieve has something for you. MIDI AMERICA Orders: (404) 419-8407 Detailed workbook-style exercises guide you through 2124 Lindley Lane Kennesaw, GA 30144

3 a guide, but not the final word on these products. Since virtual- ly all products reviewed in this article offer a trial period with a money back guarantee, we suggest that you choose one or more products that appear to have the options that you require, and give each a try. Report Writer We hope that you find the information presented here helpful in choosing which report writers to review for your Roundup… own application. Please let us know about your experiences with generating reports with these products, or with any other products that we may not know about. We need this type of continued feedback from you so that we can improve our Introduction insight into applications available for the Btrieve user and Perhaps one of the most asked questions from users of developer. Btrieve application is, “How can I use the Btrieve data that I have accumulated?” We have found that there are several good Crystal Reports Professional Edition Version 3.0 report generators on the market which support Btrieve. From Crystal Reports is a Windows based report generator so an initial list of about 15 possible systems, we have chosen installation was standard for a well implemented Windows seven systems to demonstrate here. application. It did install WBTRCALL.DLL, the Dynamic Many of the systems that were not included here in this Link Library that Windows applications require to access review are complete application development systems which Btrieve data. It also modified the settings in the [Btrieve] sec- will be covered in detail in the a future issue of Btrieve tion of WIN.INI to accommodate Crystal’s needs. It did not, Developer’s Journal. however, install the version of WBTRCALL.DLL that is required to communicate through BREQUEST.EXE to a Testing Methodology NetWare server. Therefore, we chose to access Btrieve data To review these seven report writers, we installed each on only in version 5.x format via direct Btrieve calls. a workstation on the Smithware network so that each could Crystal Reports is very intuitive to users familiar with the have access to our Customer, Order, and Product databases. Windows user interface. Building the new Invoice report Our project for each report writer was to successfully required selecting New Report from the File menu and pointing install the software, attach to our Data Dictionary Files (or to to the drive that contained our DDF’s. Next, we inserted the import the DDF’s or manually define our Btrieve files into a tables that we would be using, and defined the fields that proprietary data dictionary format). Then, for a certain batch of required joining by selecting the Links... option from the orders, we were to create an report which would print invoices Database menu. Originally, the order_detail table had an index and a sales report for the batch of orders. How this process was which was the order_number and a line_sequence field. carried out with each product is described here. Joining the order_number field from the order_header table to Test Data this index never worked for us. So, we added another index to The Smithware customer table has information about our the order_detail table that was only the order_number field. customers including mailing address, phone number, etc. The That join worked fine. order_header table has header information about the order The included on-line help system includes several pages including order_number and batch_number fields for each of information on how to create several types of reports includ- order. The order_detail table has the detail of the order while ing a section on printing an invoice. This was very helpful in the products table has pricing and descriptions for each prod- getting the invoices report to print correctly. Bear in mind that uct. the interface is very Windows oriented. If you are familiar with The customer_number field in the customer table had to Word for Windows or other Microsoft applications, be joined to the customer_number field in the order_header you should not have any trouble figuring out how to move table to retrieve the correct address and other information for around this system. the order. The order_number field in the order_detail table After figuring out how sections of data are separated in had to be joined to the order_number field in the order_header Crystal, the batch sales report was fairly easy to set up. Sub table to retrieve the detail lines for each order. Finally, the totals, headers and footers are all right in front of you during product_code field in the products table had to be joined to the the design process. product_code field in the order_detail table to print each pro- Crystal seems to access Btrieve indexes well, so all index duct’s description. paths are available for reports. One drawback that we noticed In this review, certainly we can only relate our “real was that if a change is made in a Btrieve table (the addition of world” experiences with each of these products. Your experi- a new index, for example), Crystal does not immediately rec- ence may be better or worse, depending our your environment ognize this information in an existing report that uses that and your particular requirements. Therefore, use this review as table. You must first drop that table from the report, then re-

5 insert it. This re-loads the new information contained in the Reports are generated to a spool file, and can be viewed prior DDF, but you must repaint your report for any fields that were to printing. from a dropped table. Oddly enough, we had better success creating reports One of the advantages of Crystal Reports is its ability to which joined several files, such as the customer, order_header, merge reports designed and compiled with the layout facility and order_detail tables than we did simply trying to print a list into Visual Basic applications. A limited version of Crystal of customers. This may have been sheer stupidity on our part, Reports with a special VBX control for report access is includ- but we noticed that the Customer List sample report which ed with the Microsoft Professional Edition of Visual Basic. came with Insight only listed one customer, although the sam- All in all, Crystal Reports is a product that has come a ple customer file contained 117 records. It finally took a call to long way in the past few years. If you are comfortable in tech support to resolve this difficulty. Windows, Crystal is a nice product. We were impressed with the range of data types support- ed. Something report writer vendors often overlook is that many Btrieve files simply cannot be defined in DDS’s because BDJ Fact File: Crystal Reports Version 3.0 data in the records is stored in field formats which do not cor- Environment: Windows respond to the Btrieve data types. For an inexpensive, DOS- In Short: A good end-user report writing tool with easy-to-use based reporting solution, this package has a lot to WYSIWYG layout facilities. Makes direct calls to Btrieve or can use recommend it. ODBC for file access. Uses DDF’s for file structure determination. Price: Standard edition, single user $195, 5-user LAN pack $395; BDJ Fact File: Insight Report Writer Version 2.0 Professional edition, single user $395, 5-user LAN pack $895. Environment: DOS In Short: Useful for those who need a DOS-based report writer, Insight Report Writer Version 2.0 especially if their data files were generated by a Magic or TAS Insight is a DOS based report writer designed primarily to application, or by any app which uses non-indexable data types. use Btrieve files, though it will also import ASCII text. The Price: Single user $199, LAN $499. installation procedure is fairly simple, and incorporates an interface similar to the program itself. The program installs in Intelligent Query Version 3.0 for DOS and Version 1.0 about three minutes, and requires a little over two meg of disk space. An impressive list of printer drivers appears to be sup- for Windows ported. Insight uses its own data dictionary format to define We have heard much recently about the use of the IQ database files, and can therefore report on numerous field for- product line to access Btrieve data. We have included mats which do not conform to the Btrieve extended key types. Intelligent Query in this review because we felt that they defi- Magic PC and TAS Professional data types are supported, in nitely belong in a list of potential Btrieve reporting tools. addition to a number of different date formats. Unfortunately, IQ Software Corporation did not meet our The menu and dialog box interface is divided into sections deadline for the submission of materials for this review. We for defining databases, deriving database views, defining report may, in a future issue, take another look at IQ as a Btrieve formats, and generating, viewing, and printing reports. reporting tool, but for now you are on your own to decide Defining your data is the first task. It’s fairly straightforward, whether IQ is right for you. but it can get tedious, especially if you already have DDF’s. ProPrint Report Generator Version 3.1 Insight says they are working on an import facility for DDF From the moment you install it, you can tell that ProPrint files, but we got impatient and wrote our own. Once the data- is not an end-user report writer in any sense of the word. The base is defined, it’s a simple job to pull fields out and place one word that best describes the interface is “minimalist.” them on a report. Calculated fields and totals are also easy to However, for those not intimidated by frequent encounters specify. Record selection criteria and views are generated in with the C:> prompt, and especially those with a fluency in C SQL statements, but a knowledge of SQL syntax is not code, the rewards of persistence can be substantial. The system required, as the program prompts the user with a series of lists is rather segmented, with separate executables to define data for the fields, constants, conjunctions and conditions. Context- files, define reports, print reports, generate C code from report sensitive help is available from all screens. As with most DOS definitions, and view queries. It took some time to find our text-based applications, room for description is limited, so we place in the system. We used DDF2DEF.EXE to convert our found ourselves pressing F1 a lot at first. Once we got used to database definition formats and were up and running pretty the terminology and concepts, though, things got easier. quickly. Defining report formats consists mainly of placing previously The program interfaces take time to learn, as they are pri- defined objects, such as database fields, calculated fields, and marily keyboard driven, with few of the comforts of menus or user-defined report parameters on a WYSIWYG form, and toolbars. On-line help is available, and we used it extensively. adding other graphical elements such as labels and borders. Once our data dictionary was converted, we used PP.EXE to 6 define our reports. PP uses a checklist approach to report ed normally. It would have been nice had that error been in the design, allowing you to define a primary file, set secondary file help file. relations, record selection criteria, etc. and checking off each The best surprise about R&R came after choosing the operation as it is completed. It took about 90 seconds to pro- order_header table as the master table for the report. R&R duce a list of customers. One pleasant surprise was the ability churned for about 20 seconds, displayed a complete report lay- to view live data in the report layout screen, giving the design- out, and asked the question, “Do you want to use this instant er a better idea of the look of the finished report. Reports can report layout?” The Instant Report Layout was a columnar be run from within the editor as well. report of order header information including order_number, ProPrint is a little overwhelming in the number of options company_name, and order_batch, and other fields across the available—the option to use any key on a Btrieve file being top of the report. Almost everything that was required for our among the most useful. Report run times can be cut dramati- batch sales report was laid our for us. After we said YES that cally by a judicious selection of keys for each related file. we wanted to use the Instant Report Layout, we had to restrict The real fun starts after the report layout is saved. The the report to a certain batch by entering the restriction in the PRINTGEN program takes the report layout, and translates it Filter option of the Database menu. Once the filter condition into surprisingly readable and well-documented C source. “order_batch equals 318” was entered, we previewed the People who organize their sock drawers and worry about the report to see an instant display of all orders from batch 318. optimum page size for their Btrieve files will really enjoy this R&R knew which index to use from the order_header table, product, since the level of control it provides is unmatched by and the report was presented quickly. any other report writer we tested. Program libraries are provid- One drawback to R&R is its lack of support for variable ed for Borland and Microsoft C compilers. length records, but we have been told that version 2.5 will sup- port them. R&R is also limited to only those data types that are supported as extended key types in Btrieve. BDJ Fact File: ProPrint Report Generator Version 3.1 With some setup assistance from a technician in the know, R&R is a good choice for end users who are not very techni- Environment: DOS cally oriented. Getting up to speed quickly seems to be what In Short: Not for the faint of heart. A generally user-hostile system Concentric had in mind when they produced R&R for with a steep learning curve, this is nonetheless the best developer’s Windows. report generator we have seen. Price: $249. BDJ Fact File: R&R Report Writer SQL Edition for R&R Report Writer SQL Edition for Windows Windows Version 2.0 Version 2.0 Environment: Windows R&R Report Writer has been around for a long time— since the mid 1980’s to be exact. While older versions of R&R In Short: A good end-user report writing tool with easy-to-use only supported Btrieve via NetWare SQL, this new version WYSIWYG layout facilities. Communicates with Btrieve through the supports Btrieve with the Q+E Database Library from Q+E Q+E Database Library. Instant Report Layouts help to make learning Software of Raleigh, North Carolina. how to design report easier. Like Crystal Reports, the installation of R&R for Price: $395. Windows was straight forward. Again, only the local version of WBTRCALL.DLL was installed so it would have been up Snow Report Writer, Version 4.1 to us to attempt to implement NetWare Btrieve access. Also, Snow Report Writer by Snow Software has been a leader R&R did not check or alter the [Btrieve] section of WIN.INI, in character-based data reporting for several years. Originally so it will be up to the user to be familiar with the way Btrieve introduced in 1984, Snow can give the developer access to a operates in Windows. myriad of database formats, including Btrieve. After installation, selecting a Btrieve file as the Master The interface to Snow is typical for a character-based sys- Table was easy. We simply pointed to FILE.DDF and chose tem that has evolved over the years: once you get used to it, our order_header table from the list. (Concentric should have your can remember how things work. Until then, movement is left out the tables in FILE.DDF that make up the DDF set itself a little slow. Our first introduction with Snow meant that we because these tables can appear confusing to non-technical had to re-type all of our Btrieve file definitions into the system users) When we selected our order_header table, R&R report- as Snow does not recognize DDF’s and does not have a con- ed an error: “Key count discrepancy.” Pressing the HELP com- version utility. mand button listed the definitions of many errors except this Once our tables were defined (we never were sure exactly one, but a little common sense reminded us that there was an how to define our index for the order_header table, but it did index defined in the order_header table that was not defined in work!), we were able to define a very quick solution to our INDEX.DDF. After we corrected that omission, R&R proceed- weekly sales report project. With Snow, one of the first options 7 is to “Do a Quick Query/Report.” When we chose to do so, we WinQL, Version 2.0 were able to choose the order_header table, select the fields WinQL, by Data Access International, is an implementa- that we were interested in, specify a Where clause to restrict tion of Crystal Reports Version 2.0. WinQL was designed by the output to batch 318, and generate a fast, report of the Data Access as the Windows report generation component of data. their DataFlex system. DataFlex is the company’s development Creating the invoices for batch 318 was a horse of another platform that now supports, among others, Btrieve as a data- base format. color. The only drawback to Snow was the fact that it was If you are using DataFlex to build applications that inter- character-based and therefore, report layout is slow. But this act with Btrieve data, then WinQL would certainly be a report- “drawback” will be its most attractive feature to the many of ing tool that you may wish to consider because Access us who do not have, and do not want, an alternative to charac- International would be the best source of support. ter based systems. Data Access also has another product called FlexQL Although a facility to translate DDF definitions for which is WinQL’s cousin in DOS. Although FlexQL does not Btrieve files into the proprietary Snow format would be nice, support Btrieve at this time, we understand that Btrieve sup- Snow is a proven system for wide range database reporting. port is slated for their next release.

BDJ Fact File: Snow Report Writer Version 4.1 BDJ Fact File: WinQL Version 2.0 Environment: DOS, Windows, OS/2, Mac, UNIX, VMS Environment: Windows In Short: Long lasting player in character-based report generating In Short: If you are using DataFlex for Btrieve development, this systems. Offers Btrieve access among many other database formats. version of Crystal Reports 2.0 may right for you.

Price: Single user $385-$695, LAN Pack $595-$995. Price: Single user $295, LAN pack $595.

ddddddddecddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddcedddddddd

ddddddddecddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddcedddddddd

ddhc dd

ddhc dd

ddhc dd

ddhc dd

ddhc dd

ddhc dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd dd

dd Turn your raw data into professional reports ProPrint Version 3.1

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd

dd The P roPrint R eport and C Code Generator is a powerful set of data pr ocessing tools featuring a full

dd dd

dd dd

dd dd

dd dd

dd dd

dd

dd scr een, menu-driven user interface that lets you easily work with a number of database file formats

dd dd

dd dd

dd dd

dd dd

dd

dd including all versions of Btrieve (fix ed and variable r ecor ds), P ARADOX, xBASE, ASCII te xt, and dd dd

dd dd

dd dd

dd dd

dd dd

dd

dd binary data files with fix ed length r ecor ds. P roPrint is easy to learn and easy to use.

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd Powerful Report Writer File Viewer/Definition Utility

dd dd

dd dd

dd dd

dd dd

ProPrint provides you with instant access to all of your data. dd dd Stand-alone utility for viewing and defining any of the supported

dd dd

dd dd

dd dd dd

dd Powerful reporting capabilities allow you to create any type of file formats on screen.

dd dd

dd dd

dd dd

dd dd

dd dd

dd

dd report that can be viewed on the computer screen, output to any Search for records based on any field in a file.

dd dd

dd dd

dd

dd printer device, or written to any disk file.

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd dd

dd Stand Alone Sort Utility

File Conversion dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd dd

dd Built-in file conversion capabilities make it easy to convert Powerful stand-alone sort utility supports all file formats and data

dd dd

dd dd

dd dd

dd

dd between any of the supported file formats. types. Sort on up to 10 ascending or descending keys at a time. dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd dd

dd C Code Generator Complete Online Documentation

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd Quick view and search utility lets you find

dd

dd Turbo-charge your report applications for speed. The C Code

dd dd

dd

dd the information you need fast.

dd

dd Generator (and your C Compiler) can instantly turn any dd dd

dd dd

dd dd

dd dd

dd dd dd

dd application into a super-fast executable program module .EXE.

dd dd

dd dd

dd dd

dd dd

dd dd

dd

dd Supports Microsoft, Turbo and Borland C Compilers. C Code is dd dd

dd dd

dd dd

dd

dd commented and utilizes all the variable names from the original

dd dd

dd dd Royalty-free distibution of runtime module

dd dd

dd dd

dd dd dd

dd ProPrint Report Generator application program. Automatic ProPrint Report and C Code Generator V3.1 (Single User) ..... $349

dd dd

dd dd

dd dd

dd dd indentation of loop and logic constructs is provided for

dd

dd ProPrint Report and C Code Generator V3.1 (8 User LAN) .. $899 dd dd

dd dd dd

dd increased program readability. Visa/MC accepted. Free working demo version available

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd dd

dd CALL OR WRITE TODAY

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd dd

dd

dd CONQUEST

dd dd

dd dd

dd dd dd

dd 7 Century Way, Hamilton Square, New Jersey 08690-1540 Telephone: (609) 586-1681 DATA SYSTEMS

ddg cdd

ddg cdd

ddg cdd

ddg cdd

ddg cdd

ddg cdd

dddddddd cddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddcedddddddd cdddddddd

dddddddd cddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddceddddddddecddddddddcedddddddd cdddddddd

8 PRODUCT NAME: Crystal Insight Intelligent ProPrint R&R Snow WinQL Reports Report Query Report Report Report Writer Generator Writer for Writer Windows, SQL Edition Version: 3.0 2.0 3.0 3.1 2.0 4.1 2.0 Date of Initial Release: May 1992 Dec 1991 1985 Jun 1987 1984 Feb 1993 — Date of Current Release: Dec 1993 Oct 1993 Dec 1992 Nov 1993 Aug 1993 Jul 1993 — Approximate Users: 60,000 200+ 1,000,000 1,000+ 2000 2,000,000 1,000+

ENVIRONMENT Character-based DOS: No Yes Yes Yes No Yes No Windows: Yes No No No Yes Yes Yes OS/2: No No Yes No No Yes No Other: — —- — — — Mac, Unix, VMS — Makes Calls to Btrieve: Yes Yes Yes Yes No Yes Yes Uses ODBC: Can use No No No Q+E Database No No Q+E ODBC library calls Variable Length Record Support: No Yes Yes Yes No (coming in Yes Yes version 2.5) Btrieve Version 4.x: No Yes Yes Yes Yes Yes No Btrieve Version 5.x: Yes Yes Yes Yes Yes Yes Yes Btrieve Version 6.x: Yes Yes Yes Yes No (coming in Yes version 2.5) NetWare Btrieve: Yes Yes No Yes Yes Yes Yes Uses Standard DDF’s: Yes No—can No No—can Yes No Yes convert convert Tech Support Reps: 10 2 20 1 5 23 2

DATA TYPES Standard Btrieve Data Types: Yes Yes Yes Yes Yes Yes Yes COBOL NumericSTS: No Yes No Yes No Yes Yes BCD 10: No No Yes No No Yes Yes Magic Data Types: No Yes No Numeric No Yes Yes Character Dates: 8 Byte only Yes Yes 8 Byte only No Yes Yes TAS Data Types: No No No No No Yes Yes Visual Basic Data Types: Yes Yes No Yes No Yes Yes Turbo Pascal Real: No Yes Yes No No Yes Yes Return Policy: 60-day 30-day 30-day 30-day 60-day None 30-day money back money back money back money back money back money back Single User Price: $195/Std $199 $500 $249 $395 $385-$695 $295 $395/Pro LAN Price: $395/Std $499 $595-$995 $595 $895/Pro Manufacturer: Crystal First Choice Intelligent Conquest Concentric Snow Data Access Services Software Query Data Data Software International Systems Systems Telephone: 604-681-3435 215-682-1759 404-446-8880 609-586-1681 508-366-1122 813-784-8899 305-238-0012

Note: Information from this chart was supplied by the manufacturers of each respective product. We cannot guarantee that the information provided is correct.

9 Btrieve, and can be defined as data type 11, ZStr ng. ZStrings are the same as strings in most respects, except that the last character of the string is presumed to be followed by a null character. In sorting Zstring data, Btrieve ignores any Data Types: characters beyond the first null character it encounters in the string. This is the only difference between the string and zstring types. If the field is null-padded, in other words if no Ins and Outs… garbage is left between the null byte and the end of the field by any program which updates the file, zstring and string keys will collate the same. It is customary when creating a zstring field to insure that the field is long enough to hold the entire By Steve Mook text of the field, plus at least one terminating null character, as This is the first in a series of articles addressing the issues some C routines do not take a byte count argument, but use the involved in converting data types in Btrieve files. Because the null byte to signify the end of the string. Btrieve record manager will interface with a number of differ- The other string data type supported by Btrieve is the ent programming languages, data in Btrieve files can take a LString, type 10. It corresponds to the Pascal lstring data type, maddeningly diverse range of formats. This first article will in which the leftmost byte of the storage field represents the deal with explaining the Btrieve Extended Key types, which string’s length, 0 to 255 bytes, and the subsequent bytes con- are definable using the standard DDF format, and which are tain the string itself. therefore accessible to most third-party Btrieve front-ends. Whole Number Storage Types Future articles in this series will deal with other data types Integer fields store signed whole numbers in Intel binary commonly encountered in non-key fields of Btrieve files, and integer format, in which the high-order and low-order bytes are how these may be translated. reversed within each word The sign is the high-order bit of String Storage Types the rightmost byte. Common integer sizes are 2 and 4 bytes, The String data type, defined as type 0 in Btrieve, it is corresponding to the integer and long integer storage types simply a sequence of characters, ordered from left to right. supported by most programming languages. The range for a When used as part of a key in Btrieve, it sorts according to 2-byte integer is -32,768 to 32,767, for a 4-byte integer, ASCII byte value, left to right. -2,147,483,648 to 2,147,483,647. If the key has an alternate collating sequence, the string Btrieve will sort Integers of any even number of bytes in will sort according to the translated value of each byte. length, but sizes other than 2 and 4 bytes are unusual. NetWare Alternate collating sequences are simply a list of byte-value SQL and some other applications will allow the definition of translations for a string key. Only string-type fields, as defined 1-byte integers, but these are not defined as integer keys in in this section, can use an alternate collating sequence. The Btrieve. If they are to be indexed, they must be indexed as most common alternate collating sequence in English language 1-byte sting keys. They are interpreted numerically as the databases is UPPER.ALT, a sequence in which lowercase let- binary value of the stored character, with a range of 0 to 255. ters of the alphabet sort as their uppercase equivalents. Btrieve Unsigned Binary storage is similar to Integer storage, version 6 supports case-insensitive keys, defined by setting bit except that there is no sign bit. Currently there is no standard 10 of the key flag field in the file’s status buffer. This makes DDF support for unsigned binary numbers, though unsigned the use of the Alternate Collating Sequence for case-insensitive binary numbers in 2 and 4 byte sizes are supported by several sorts unnecessary in version 6 files. languages. The range for a 2-byte Unsigned Binary number is Though string fields are fairly simple, they do present 0 to 65,535, for a 4-byte, 0 to 4,294,967,295. some data conversion issues. Standard DDF definitions will AutoIncrement storage is the same as signed Integer stor- allow only 255 characters in any string field—the reason being age, and may be 2 or 4 bytes in length. AutoIncrement keys that the maximum length of a key in Btrieve is 255 bytes, and are incremented by Btrieve when a new record is inserted with if the field is to be indexed, it can be no longer than this. a zero value in an AutoIncrement key field. Btrieve sorts One other consideration, especially when using Btrieve AutoIncrement keys based upon their absolute value. Hence string data in Windows-based programs, is that Windows gen- values of one and negative one are duplicate key values. For a erally assumes that strings are null-terminated. Therefore, 2-byte field, Btrieve will return a status 5 when the 32,769th Windows Text Boxes will stop at the first null character they record is inserted, because the positive range of a 2-byte signed encounter in the string. Also, all character values in a string integer is 1 to 32,767. The 32,768th record will be inserted as key are significant when using the field as a key, including -32,768. On the next insert, Btrieve will try to increment the whitespace characters and nulls. These issues can become sig- number with the highest absolute value, -32,768, and return a nificant if the program which created the Btrieve data pads its status 5, duplicate key value. It bears repeating that this is a strings with spaces, or contains embedded null characters. feature, not a bug. The absolute value range for a 4-byte Null-terminated strings are treated as a special case by AutoIncrement field is 1 to 2,147,483,647. Real Number Storage Types Field Value: -1234.5 Decimal or real numbers provide the most interesting data Field Storage (left to right): storage problems, since there seem to be as many different 0x00 0x00 0x00 0x00 ways to pack a real number as there are programming m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m m languages. Since Btrieve will interface to most programming — — — — — — — L — — — — — — — — — — — — — — — — — — — — — — — — 4 4 4 4 4 5 5 S 3 3 3 4 4 4 4 4 2 3 3 3 3 3 3 3 2 2 2 2 2 2 2 2 languages, it supports several common real number formats as 5 6 7 8 9 0 1 B 7 8 9 0 1 2 3 4 9 0 1 2 3 4 5 6 1 2 3 4 5 6 7 8 key types. 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 The Float data type, type 2, is consistent with the IEEE standard for single and double precision real numbers. Most programming languages support IEEE real number formats. 0x00 0x4A 0x93 0xC0 These fields may be 4 or 8 bytes in length. The format for a m m m m m m m m m m m m m m m m S m m e m m m m S e m m m m m m — — — — — — — — m m m m m m — — i m m L m m m m i M m m m m m L 4-byte floating point number is a sign bit in the MSB of the 1 1 1 1 1 1 1 2 — — — — — 1 1 1 e e e S — — — — g S e e e e e e rightmost byte, an 8-bit exponent biased by 127 stored in the 3 4 5 6 7 8 9 0 5 6 7 8 9 0 1 2 3 2 1 B 1 2 3 4 n B 9 8 7 6 5 4 following 7 of the rightmost byte and the MSB of the 0 0 0 0 0 0 0 0 0 1 0 0 1 0 1 0 1 0 0 1 0 0 1 1 1 1 0 0 0 0 0 0 penultimate byte. The mantissa is typical for floating point 1 storage types, consisting of an implied “1” bit in the MSB m position, plus the remaining 23 storage bits ordered left to right M S within each byte, proceeding by byte from right to left within B the field. The mantissa is a binary fraction, which means that Value of Exponent: 10 (20+23+210-1023) the value of each bit is multiplied by two raised to the negative Value of Sign: 1 (negative) value of its association bit position relative to position of the Value of Mantissa: 1.2055664 (20+2-3+24+2-6+2-9+2-11) implied MSB at position 0. The field value is obtained by mul- Value of Storage: -1234.5 (-1.2055664*210) tiplying two raised to the power of the exponent less its bias value, by the value of the mantissa, and signed according to The Bfloat data type, type 9, supports numbers stored in the value of the sign bit, a 1 value denoting a negative number. Microsoft Binary Format. This format was used by Microsoft’s Basic and QuickBasic languages. The format for a 4-byte Bfloat is a sign bit in the MSB of the penultimate byte, an 8-bit Field Value: -1234.5 exponent biased by 128 in the rightmost byte, and a mantissa Field Storage (left to right): consisting of an implied MSB of 1 copositioned with the sign 0x00 0x50 0x9A 0xC4 bit, followed by the remaining 23 storage bits ordered left to m m m m m m m m m m m m m m m m e m m m m m m m S e m m m m m m right within each byte, proceeding by byte from right to left — — — — — — — L m m — — — — — — L m m m m m m m i M m m m m m m 1 1 1 1 2 2 2 S — — 1 1 1 1 1 1 S — — — — — — — g S e e e e e e within the field. Unlike the IEEE floating point number, which 6 7 8 9 0 1 2 B 8 9 0 1 2 3 4 5 B 1 2 3 4 5 6 7 n B 6 5 4 3 2 1 has a range of values m where (m>=1) to (m<2), the mantissa 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 1 1 0 1 0 1 1 0 0 0 1 0 0 of a Bfloat number has a range of values m where (m>=1/2) to 1 (m<1). In other words, the MSB of the mantissa is multiplied -1 0 m by 2 instead of 2 , and the remaining bits are multiplied by M subsequent inverse powers of 2 to yield the result. A value of S B zero in the rightmost (exponent) byte, regardless of the contents of the three other bytes, defines the number stored as zero. Value of Exponent: 10 (20+23+27-127) Value of Sign: 1 (negative) Field Value: -1234.5 0 -3 -4 -6 -9 -11 Value of Mantissa: 1.2055664 (2 +2 +2 +2 +2 +2 ) Field Storage (left to right): Value of Storage: -1234.5 (-1.2055664*210) 0x00 0x50 0x9A 0x8B m m m m m m m m m m m m m m m m S m m m m m m m e e m m m m m m The range for a 4-byte float is approximately -3.4E38 to — — — — — — — L m — — — — — — — i m m m m m m m M M m m m m m L -1.4E-45 for negative numbers, 0, and 1.4E-45 to 3.4E38 for 1 1 1 1 2 2 2 S — 1 1 1 1 1 1 1 g — — — — — — — S e e e e e e S 6 7 8 9 0 1 2 B 9 0 1 2 3 4 5 6 n 2 3 4 5 6 7 8 B 6 5 4 3 2 1 B positive numbers. 0 0 0 0 0 0 0 0 0 1 0 1 0 0 0 0 1 0 0 1 1 0 1 0 1 0 0 0 1 0 1 1 The 8-byte floating point number consists of a sign bit in the MSB of the rightmost byte, an 11-bit exponent in the sub- 1 m sequent 7 bits of the rightmost byte and the left 4 bits of the M penultimate byte, biased by 1023. The mantissa consists of an S B implied bit copositioned with the LSB of the exponent, plus the remaining 52 bits of storage. The range for an 8-byte Float Value of Exponent: 11 (20+21+23+27-128) is approximately -180E308 to -4.94E-324,0, and 4.94E-324 to Value of Sign: 1 (negative) 1.80E308. Value of Mantissa: 0.60278320313 (2-1+2-4+2-5+2-7+2-10+2-12) Value of Storage: -1234.5 (-0.60278320313*211) 2 The range for a 4-byte Bfloat is approximately -1.7E38 to Converting BFloat to IEEE Real Numbers -2.9E-39 for negative numbers, true zero, and 2.9E-39 to typedef struct BFLOAT{ 1.7E38 for positive numbers. It is accurate to 7 decimal places. byte[8]; An 8-byte Bfloat number uses the same storage format, but }; includes an additional 4 bytes of storage to the left for the typedef union IEEE{ mantissa. The range for an 8-byte Bfloat is the same as that of byte[8]; double value; a 4-byte, but it is accurate to 15 decimal places. }; The Decimal data type, type 5, is a type used primarily by

// Convert 4-byte or 8-byte Bfloat to 8-byte COBOL programs. It is stored as a Binary Coded Decimal // IEEE float format number, with two digits per byte. Data is stored right-justified double BfloatToDouble(BFLOAT bfloat, int nSize) and padded with leading binary 0’s. The low-order digit is { IEEE ieeefloat; stored in the leftmost 4 bits of the last byte, and the sign is char Sign; stored in the rightmost 4 bits. For a decimal field of n bytes, int Exp; int X; this allows storage of 2n - 1 digits The sign is either 0xF or 0xC for positive numbers, or 0xD for negative numbers. ieeefloat.value = 0; Decimal point information is not stored with the data, so it is switch (nSize){ up to the program to determine how many decimal places to case 4: if (bfloat.byte[3] != 0x00) use, either internally or by referring to the DDF definition for { the field. All values in a field must have the same number of Sign = (char)(bfloat.byte[2] & 0x80); decimal places for the field to sort correctly. Decimal fields Exp = bfloat.byte[3] - 0x81 + 0x3FF; ieeefloat.byte[6] = (char)(Exp << 4); may be 1 to 10 bytes long, allowing a maximum storage of ieeefloat.byte[7] = (char)((Exp >> 4) | Sign); 19 digits. for (X = 2; X < 0; X--) { bfloat.byte[X] <<= 1; Field Value: 123.4 bfloat.byte[X] |= bfloat.byte[X-1] >> 7; } Field Storage (left to right): bfloat.byte[0] <<= 1; 0x01 0x23 0x4F for(X = 6; X >= 4; X--) { 0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 1 0 1 0 0 1 1 1 1 ieeefloat.byte[X] |= bfloat.byte[X-4] >> 4; digit digit digit digit digit sign ieeefloat.byte[X-1] = 1 2 3 4 2n-1 byte (char)(bfloat.byte[X-4] << 4); } } break; case 8: if (bfloat.byte[7] != 0x00) The Money data type, type 6, has the same internal stor- { Sign = (char)(bfloat.byte[6] & 0x80); age as the Decimal data type. It is assumed to have two deci- Exp = bfloat.byte[7] - 0x81 + 0x3FF; mal places. Like Decimal, this data type is seldom used out- ieeefloat.byte[6] = (char)(Exp << 4); ieeefloat.byte[7] = (char)((Exp >> 4) | Sign); side of COBOL. Another COBOL format is Numeric, data type 8. It may for(X = 6; X > 0; X--) { be 1 to 15 bytes long, and contains an ASCII string represen- bfloat.byte[X] <<= 1; tation of the number, right justified with leading ASCII bfloat.byte[X] |= bfloat.byte[X-1] >> 7; } zeroes. As with the Decimal data type, the decimal point is bfloat.byte[0] <<= 1; not stored, but rather defined in the program or in the DDF. The rightmost byte of the number may include an embedded for(X = 6; X >= 2; X--) { sign, according to the following table: ieeefloat.byte[X] |= bfloat.byte[X] >> 4; ieeefloat.byte[X-1] = (char)(bfloat.byte[X] << 4); } Digit Positive Negative } 1 A J break; 2 B K 3 C L default: 4 D M break; 5 E N 6 F O } 7 G P 8 H Q return ieeefloat.value; 9 I R } 0 { }

3 Numerics which do not contain an embedded sign are gen- The Timedata type, type 4, is clock time, not serial time. erally assumed to be positive. It is stored as a 4 byte value, with hundredths of seconds in the Btrieve version 6 also provides key type support for the leftmost byte, seconds in the second byte, minutes in the third NumericSTS, or sign trailing separatedata type, type 17. It byte, and hours in the rightmost byte. Once again, before per- is similar to the Numeric data type, except that the sign is not forming any math using this storage type, you must convert it embedded with the last decimal digit, but is stored separately to a serial time representation. Twelve hours, twenty-two min- at the end of the field. The last byte is either ‘+’ (0x2B) or ‘-’ utes, thirty-five seconds would be stored as: (0x2D) for positive or negative numbers, respectively. Note that many third-party vendors have yet to implement support for Btrieve version 6 files. Field Value: 12:22:35 Field Storage (left to right): Date, Time, and Boolean Storage Types 0x00 0x23 0x16 0x0C The Datedata type, type 3, stores a calendar date, not a serial date. This data type is 4 bytes long. The date is stored, 00000000 00100011 00010110 00001100 from left to right, as a 1-byte binary value representing the day 1/100 second minute hour of the month, (0x01 to 0x1F), a 1-byte binary value represent- ing the month number (0x01 to 0x0C), and a 2-byte integer value representing the year. Hence January 15, 1994, would be The Logicaldata type, type 7, may be either 1 or 2 bytes stored as: in length. Logical key fields collate as strings, and the values which represent different logical states are left to the program- Field Value: 01-15-1994 mer’s discretion. Field Storage (left to right): In the next issue of Btrieve Developer’s Journal, we will look at some of the other common methods of storing data in 0x0F 0x01 0xCA 0x07 Btrieve files including bit fields, variable length note fields, 00001111 00000001 11001010 00000111 Turbo Pascal numeric types, and data types used by popular } Btrieve front-end systems. day month year

Note that this data structure will collate correctly if treated as a 4-byte integer. Btrieve does not do any validation on this or any other key data, so it is entirely possible to store dates like 02-31-1994 or 13-255-32767. These “dates” will collate according to their relationship to other dates in the key, inter- preted as long integers. You cannot use this data directly to perform date math calculations—you must first convert the Btrieve Date type to some type of serial date representation. The following code makes such a conversion, where y, m, and drepresent the calendar year, month, and day respectively, and jdaterepresents the number of days before or after Saturday, December 30, 1899. Note that all division operations are inte- gral, yielding only the whole number and truncating any remainder.

Converting Calendar to Julian Dates long jdate, y, m , d;

jdate = 367 * (y - 1891) - (7 * (y + (m + 9) / 12) / 4) - (3 * ((y + (m - 9) / 7) / 100 + 1) / 4) + (275 * m / 9) + d + 7;

4 table. Extended data types are defined in figure 6 on page 18. The first member of the standard DDF set is called FILE.DDF (see figure 1) which contains a list of the tables that have been defined in the Data Dictionary. When a new table is DDF’s Explained… inserted into the DDF, Btrieve assigns the table a File ID that is unique for all the tables defined in the DDF. This File ID is referred to as the Xf$Id field. If you look carefully into the data contained in the DDF files, you will notice that the three By Scott Smith, Publisher files that make up the standard DDF’s are also defined in the DDF’s themselves. Those fields defined for the definition of One thing that sets Btrieve, as a record manager, apart FILE.DDF begin with Xf$, fields defined for the definition of from relational database engines is the fact that Btrieve lacks FIELD.DDF begin with Xe$, fields defined for the definition field information about the structure of the data that is con- of INDEX.DDF begin with Xi$, fields defined for the defini- tained in each file. In fact, the only fields that Btrieve knows tion of FIELDEXT.DDF begin with Xx$, and fields defined anything about are those fields that were defined as key seg- for the definition of COMMENT.DDF begin with Xc$. ments when the file was created. The Xf$Name field in FILE.DDF is the descriptive name To compensate for Btrieve’s lack of knowing where fields of the table, such as customer_database and the Xf$Location of data exist, Novell (or SoftCraft at the time) developed the is the filename that the operating system uses to open the file DDF standard. DDF stands for Data Dictionary File and is the that contains the table’s data. This often causes difficulty in method by which many commercial applications determine some systems because they require that the drive letter and Btrieve’s field structure. path be included in the table location and other systems do not. There is nothing all that special about the DDF structure, Also, some systems do not allow the Xf$Location to refer to a but Novell has never made information about it easily avail- NetWare volume name and path but rather require the DOS able. drive letter and path. Finally, the Xf$Flags byte indicates The standard DDF set consists of 3 basic Btrieve files: whether the defined table is one of the standard DDF files or FILE.DDF that contains a list of Btrieve tables (note: Novell any other table. If bit 4 is set, then the table is one of the stan- uses SQL vernacular and refers to Btrieve files as “tables”) dard DDF’s, otherwise it is a “user defined” table. defined, FIELD.DDF that contains a list of fields in those The second member of the standard DDF set is tables, and INDEX.DDF that contains a list of fields which FIELD.DDF (see figure 2) which contains a list of fields from are defined as key segments of each table. tables defined in the Data Dictionary. The Xe$Id is the field ID This last sentence indicates one of the biggest problems assigned to the field and is unique for all fields in the entire with the DDF structure: INDEX.DDF assumes that all keys in DDF. The Xe$File corresponds to Xf$Id in FILE.DDF and is a Btrieve file are complete, non-overlapping fields. This causes the ID of the table. Xe$Name is the field name, and difficulty for many users who attempt to build a DDF for exist- Xe$DataType is the Btrieve extended data type code. (See fig- ing Btrieve applications. Btrieve allows keys to be defined for ure 6 on page 18 for a complete list of all standard Btrieve data part of an actual field (the first 7 characters of a last name and types.) Xe$Offset is the offset, 0 relative, of the field in the the first 3 characters of the first name, for example) and two data buffer, and Xe$Size is the size in bytes of the field. keys may refer to the same data as different data types (a date Xe$Dec has 3 purposes depending on Xe$DataType. For field as an 8-byte YYYYMMDD string and a month field as the COBOL Decimal COMP-3 (5), COBOL Money (6), characters 5 and 6 of that field). Since Xtrieve, Novell’s prod- COBOL Numeric (8), and COBOL NumericSTS (17) data uct that builds DDF’s (and the XQL engine that does the actual types, Xe$Dec is the number of decimal places for the field. building), requires that fields be contiguous in the data buffer For the Note (12) and LVar (13) variable length data types, without gaps or overlapping fields, this really can cause prob- Xe$Dec is the field delimiter. And finally, for the Bit (16) data lems. Later, we’ll look at how to overcome most of these prob- type, Xe$Dec is the relative bit position for up to 8 contiguous lems. Bit fields. Support for contiguous Bit data types was a new Since the DDF’s are merely Btrieve files themselves, feature in NetWare SQL version 3.0. Xe$Flags is a two-byte given their structure, one may access them with any applica- field in which bit 0 is a case flag for string data types. tion development system that can read Btrieve files. The struc- Note that before the introduction of NetWare SQL 3.0, ture of the three standard DDF’s is listed in figure 1 through 3 FIELD.DDF did not have the last index shown in figure 2. In on page 18. Two extended DDF’s, FIELDEXT.DDF and order for applications to read FIELD.DDF to build a list of COMMENT.DDF, documented in figure 4 and 5 on page 18, fields for a table by order of the Xe$Offset, any modification were developed by Smithware, Inc. to allow the definition of to the DDF files required that Btrieve completely delete the additional data types that are not supported by Btrieve as index table from the DDF and reinsert the definition. This ensured segments and to allow comments to be kept with any field in a that inserted fields would always return following index 1 in

6 the proper order. Since NetWare SQL 3.0 has added the new DDF’s using one of Novell’s development products. index composed of the Xe$File, Xe$Offset, and Xe$Decimal The primary development product that manipulates DDF’s fields, this method of DDF deletion and reconstruction may no is the XQL Developer’s Kit This product includes a TSR, in longer be necessary. Check to see if your application can read addition to BTRIEVE.EXE, that provides a higher level API to FIELD.DDF using this new index. perform database functions on Btrieve files. One set of calls in One other little known fact about FIELD.DDF is that this API gives the developer the ability to create and manipu- NetWare SQL also uses it to define “Named Indexes.” A late the standard DDF files described here. Xtrieve, Novell’s Named Index is another NetWare SQL term for a Btrieve sup- database reporting and analysis tool for Btrieve and NetWare plemental index that can be given a name. A “Named Index” SQL, uses the XQL/NetWare SQL API to build DDF’s. sets Xe$DataType to 255, converts Xe$Name into an index Smithware’s DDF Builder for DOS uses the XQLPO (XQL name, and turns Xe$Offset into the index number of the sup- Primitives Overlay) API to build and maintain DDF’s, but plemental index of the table. does not include data analysis or reporting tools. The third and final member of the standard DDF set is When we developed DDF Builder for Windows, we want- INDEX.DDF (see figure 3) which contains a list of fields that ed to maintain this level of compatibility with Novell. are key segments of tables defined in the Data Dictionary. Unfortunately, Novell did not at that point have a development Many applications, from Microsoft Access to Smithware product that was a Windows DLL that could manipulate Controls for Btrieve, ignore INDEX.DDF altogether because DDF’s. We discovered that Borland and Novell had jointly index information is the one thing that Btrieve is very good developed a DLL called WDDLSVCS (Windows Data about making available to any application through the use of Definition Language Services) that provided the DDF func- the standard Btrieve status operation. The only case that an tionality of XQLPO in a Windows DLL. Although application might need INDEX.DDF is when it is necessary to WDDLSVCS.DLL is not a part of any Novell development create a new Btrieve table that does not already exist. product, Novell did make it available for members of their Xi$File and Xi$Field identify the table’s Xf$Id and the Professional Developer’s Group through CompuServe, in part field’s Xe$Id that correspond to the current index segment. As due to our persuasive pleading. You may be able to still download the “official” version of mentioned previously, this is often a compatibility issue with WDDLSVCS.DLL from CompuServe, but be aware that the applications written without consideration for this restriction. DLL has SEVERAL limitations, all of which have been Again, Btrieve allows the developer to create any number of patched with the latest version of DDF Builder for Windows. index segments that vary in length and offset which may over- If you really want to, you can do as Microsoft did with lap and coexist. The Xi$Number and Xi$Part fields identify Visual Basic: just create a set of Btrieve files with the names the index number and segment while the Xi$Flags field con- and structures of the DDF’s documented here. That will work tains the index attribute flags. in many cases, except with those Novell products that look for One additional restriction of INDEX.DDF is that there is the special Btrieve owner name normally assigned to the no provision for indicating the Null or Manual value of an DDF’s. Also, bear in mind that Novell has repeatedly stated index. Also, as with FIELD.DDF, the last index (number 2) that the DDF standard may change at any time in future ver- was added for NetWare SQL 3.0. sions of Xtrieve, XQL, and NetWare SQL. So if you plan to Two additional DDF standards have been introduced by write your own, you may not always be in sync with the latest Smithware in our DDF Builder for Windows product. FIELD- version of the DDF structure. EXT.DDF (see figure 4) allows Btrieve databases to be The DDF structure goes a long way in making Btrieve defined that use data types in addition to those supported as more similar to and competitive with end-user oriented data- index data types in Btrieve. Xx$File and Xx$Id identify the bases on the market today. We hope that the standard will con- table’s Xf$Id and the field’s Xe$Id that correspond to the cur- tinue to grow and change as database structures, and Btrieve’s rent field. The Xx$DataType is the extended data type code as functionality in particular, improve over the coming years. listed in figure 6 on page 18. While these data types are currently supported only by Smithware’s Controls for Btrieve, several other application vendors are incorporating this new standard into their products. Products That Create DDF’s The final DDF file is COMMENT.DDF (see figure 5) that allows the storage of comments for each field defined in the DDF Builder from Smithware, Inc. (615) 860-3500 DDF Once again, Xc$File and Xc$Id identify the table’s DDFGen from Classic Software (313) 677-0732 Xf$Id and the field’s Xe$Id that correspond to the current Visual DDF for Btrieve from Comtrec Prodata, Inc. (505) 294-1530 field, and Xc$Comment contains up to 100 characters as the field’s comment. XSupport from Informations Architects (517) 337-0714 Novell has always presented the DDF as a proprietary for- XTrieve from Novell, Inc. (512) 346-8380 mat and suggests strongly that you only create and modify

7 Figure 1—Structure of FILE.DDF Figure 4—Structure of FIELDEXT.DDF DDF Element: FILE.DDF DDF Element: FIELDEXT.DDF Description: Defines tables defined in the Data Dictionary Description: Defines fields that have extended data types not supported by Btrieve Total Record Length: 97 Bytes Total Record Length: 6 Bytes Field Name Description Data Type Position Length Field Name Description Data Type Position Length Xf$Id File ID Integer 1 2 Xx$File File ID from Integer 1 2 Xf$Name Table Name String 3 20 FILE.DDF Xf$Location Table Location String 23 64 Xx$Field Field ID from Integer 3 2 Xf$Flags File Flags Integer 87 1 FIELD.DDF Xf$Reserved Reserved String 88 10 Xx$DataType Extended Data Type Integer 5 2 Index Segment Field Name Description Duplicates Code 0 0 Xf$Id File ID No Index Segment Field Name Description Duplicates 1 0 Xf$Name Table Name No 0 0 Xx$File File ID No 1 Xx$Field Field ID Figure 2—Structure of FIELD.DDF

DDF Element: FIELD.DDF Figure 5—Structure of COMMENT.DDF Description: Defines fields for tables defined in the Data Dictionary Total record length: 32 Bytes DDF Element: COMMENT.DDF Field Name Description Data Type Position Length Description: Defines comments for fields in tables in the Data Dictionary Total record length: 104 Bytes Xe$Id Field ID Integer 1 2 Xe$File File ID from Integer 3 2 Field Name Description Data Type Position Length FILE.DDF Xc$File File ID from Integer 1 2 Xe$Name Field Name String 5 20 FILE.DDF Xe$DataType Data Type Code Integer 25 1 Xc$Field Field ID from Integer 3 2 Xe$Offset Field Offset Integer 26 2 FIELD.DDF Xe$Size Field Size Integer 28 2 Xc$Comment Comment String 5 100 Xe$Dec Decimal/Delimiter/ Integer 30 1 Index Segment Field Name Description Duplicates Bit position 0 0 Xc$File File ID No Xe$Flags Case flag for Integer 31 2 1 Xc$Field Field ID String data types Index Segment Field Name Description Duplicates 0 0 Xe$Id Field ID No Figure 6—DATA TYPE CODES 1 0 Xe$File File ID Yes Standard Data Types Smithware Extended Data Types 2 0 Xe$Name Field Name Yes 0 String 3 0 Xe$File File ID No 238 BCD10 1 Integer 1 Xe$Name Field Name 239 MagicPC Numeric 2 IEEE Float 4 0 Xe$File File ID Yes 240 MagicPC Time 3 Btrieve Date 1 Xe$Offset Field Offset 241 MagicPC Date 4 Btrieve Time 2 Xe$Decimal Decimal/Delimiter 242 YMD 3-Byte Date 5 COBOL Decimal COMP-3 243 YYMMDD 6-Byte Date Note: Index 4 is new and is required by NetWare SQL 3.0 6 COBOL Money 244 YYYYMMDD 8-Byte Date 7 Logical 245 TAS PRO3 Date Figure 3—Structure of INDEX.DDF 8 COBOL Numeric 246 TAS PRO3 Numeric DDF Element: INDEX.DDF 9 BASIC BFloat 247 COBOL Decimal COMP-6 Description: Defines index characteristics of tables in the Data Dictionary 10 Pascal LString 248 Reserved Total Record Length: 10 Bytes 11 C ZString 249 Reserved 12 Variable Length Note 250 Reserved Field Name Description Data Type Position Length 13 LVar 251 Reserved Xi$File File ID From Integer 1 2 14 Unsigned Binary 252 Reserved FILE.DDF 15 AutoIncrement 253 VB Date-Time Xi$Field Field ID from Integer 3 2 16 BIT 254 VB Currency FIELD.DDF 17 COBOL NumericSTS 255 Pascal Real Xi$Number Index Number Integer 5 2 Xi$Part Segment partnumber Integer 7 2 Xi$Flags Btrieve index flags Integer 9 2 Index Segment Field Name Description Duplicates 0 0 Xi$File File ID Yes 1 0 Xi$Field Field ID Yes 2 0 Xi$File File ID No 1 Xi$Number Index Number 2 Xi$Part Segment part number Note: Index 2 is new and is required by NetWare SQL 3.0 8 compression was activated only when the PO number had at least 5 consecutive identical digits (like “144444” or “777777”). Not much of a savings there. Just as significant, compressed records are stored as variable length records as Inside Btrieve… well. This imposes its own overhead of 4 bytes per record. This overhead exists for every record, even those that do not Compressed Files, or 10 pounds of have the required 5 consecutive identical characters. Btrieve in a 5 pound sack Implementing Btrieve Compression Implementing Compression for Btrieve files is easy. Compression is specified when the Btrieve file is created. See by Douglas J. Reilly listing 1 for an example file that can be fed into BUTIL, Novell’s command line Btrieve file utility. When compression Introduction is active, the /U parameter on the BTRIEVE.EXE command In my last Inside Btrieve column, I made the point that, line for stand-alone and non-Novell networks, the /U parame- while there is no such thing as a free lunch, sometimes lunch ter in the [BTRIEVE] section of WIN.INI or in NOVDB.INI can be had at no additional charge. The discussion was cen- for Windows, and the largest compressed record parameter in tered on Btrieve’s use of pages to allocate space for all types BSETUP on NetWare networks must be set correctly. Note of information (Data, Indexes, even the Header of the Btrieve that for BTRIEVE.EXE, the use of compression increases con- file), and how decisions on page size use might impact overall ventional memory use by approximately twice the size of the file size. In this issue, I will show you some situations where largest compressed record. that free lunch might actually exist. One of the nice things about record compression in One of the many options facing the Btrieve application Btrieve is that the application need not take any special steps developer is data compression. Let’s begin with some defini- in order to use it. From the perspective of the application, a tions of terms: All compression discussed here is loss-less compressed record will be returned in almost exactly the same compression. That is, after the data is compressed, the data amount of time as a non-compressed record. must be uncompressed exactly correctly. While this seems To determine the impact of compression on file size and obvious, some situations exist in other compression schemes performance, I started out with a sequential DOS file in the where greater gains can be made using compression that BUTIL format. The BUTIL format is such that the data in the allows the resulting information to be almost the same as input text file is an image of the data as it should appear in the before compression. Still and Video images are objects that Btrieve record. Each record in the sequential file consists of an allow for compression that is not loss-less. A single pixel that ASCII representation of the record length, followed by a is a little bit off will not greatly change the overall effect. comma, followed by the actual data, followed by a carriage However, a change of a single byte in an accounting file can return and line feed combination. Each record was 211 bytes have serious consequences. and the file was an ideal candidate for Btrieve compression. It Unlike the data compression we are all most familiar with contained a couple of fields that in the current implementation (PKZIP by PKWare and other file compression utilities) the are always blank and in every case at least one of several 30 data compression offered by Btrieve is very limited. Through character fields is blank. See table 1 for the results of data an exhaustive search using byte editors to look through files compression for the insertion of 7866 records into the empty with and without data compression, I have made several obser- file, with and without compression, with BTRIEVE.EXE and vations. using BREQUEST.EXE on a NetWare server. All tests were When using Btrieve record compression, only those run on the same machine and the same network drive. This file strings of data that contain repeated characters are compressed. is a VERY compressible file, by most standards, and was only This is important. Other data compression programs take 25% smaller when Btrieve compression was used. On the other advantage of the fact that text often has a large number of cer- hand, when the resulting Btrieve file without compression was tain letters such as “E” and “I” and relatively few occurrences compressed using PKZIP version 1.1, the ZIP file was only of other letters such as “Z” and “X”. These systems encode the 259,135 bytes. Now THAT’S compression! common characters in less than one byte, and the less common Other options for compression also exist. If you are using characters in one byte. While specific algorithms vary, the DOS 6.0 or greater, the operating system supports Double process for most data compression methods works by deter- Space data compression. This data compression is transparent mining the distribution of character population and compress- to all applications, and the data received by an application is ing those characters that are used most often. the actual, uncompressed data. NetWare, beginning with ver- With Btrieve compression, the compression only occurs sion 4.00, also has disk compression available as an option. In when you have 5 or more characters repeated one right after testing the DOS supplied data compression, the non-com- another! In one sample Purchase Order file I looked at, data pressed Btrieve file reported a compression ratio of 3.1-to-1,

9 thus the file was really only taking up 746K. Unlike the ZIP Table 1—Performance results compression mentioned above, the data is always available for LOAD TIMES AND RESULTING BTRIEVE FILE SIZES USING your use by virtually any DOS or Windows Btrieve based VARIOUS COMPRESSION TECHNIQUES: application. Compression Type Btrieve Type Load Time File Size Compression and data recovery—The dark side of the (seconds) (bytes) Uncompressed: BTRIEVE.EXE 246 2,314,240 force... BREQUEST.EXE 105 2,314,240 Keep in mind that some of the my observations come Btrieve BTRIEVE.EXE 290 1,758,720 through the eyes of a developer responsible for writing Btrieve Compression: BREQUEST.EXE 114 1,758,720 utilities and that I deal little with real, valuable data. From the MS-DOS 6.2 BTRIEVE.EXE 246 746,000 perspective of data recovery, all of the data in a compressed Doublespace: BREQUEST.EXE N/A N/A file is variable data. One of the things that is sometimes useful Tests run using BTRIEVE.EXE version 5.10a, BREQUEST version 6.10b, when doing Btrieve data recovery is to try and read a record at BTRIEVE.NLM version 5.15. All files Btrieve 5.x format. every possible record position. Btrieve is fairly well document- ed in this regard, and for fixed length and normal, non-com- Listing 1—Creating a compressed file with BUTIL-CREATE pressed variable length records, finding each possible record record=211 variable=y truncate=n starting position is reasonably easy. (See the special assign- compress=y key=1 page=512 ment article in this issue on Btrieve Data Recovery) allocation=0 replace=y fthreshold=20 However, add Btrieve’s data compression and, except for position=1 length=14 duplicates=n the first record on a data page, it is impossible to tell where modifiable=n type=string alternate=n each record might begin! If you are fortunate enough to work null=n segment=n with databases that are relatively static and are backed up very regularly, this may not be a problem. However, back in the rest Doug Reilly is the owner of Access Microsystems Inc., a software development house specializing in C/C++ software development, of the world, people want every possible chance to recover often using Btrieve as a file manager. He has had articles on Btrieve their data after an accident. published in Dr. Dobb’s Journal and is the author of BTFILER and Another recovery method used by my BTFILER utility is BTVIEWER Btrieve file utilities available on Compuserve. Doug’s to perform a Btrieve close operation on the file if a particular Compuserve address is 74040,607 and he can be contacted at 404 record can’t be read due to an I/O error —status 2. Next, open Midstreams Road, Brick, NJ 08724 or at (908) 892-2683 the file using standard DOS Open calls, read the actual data from the file, and close the file. Then, reopen the file with Btrieve, reestablish positioning, and continue trying to get data through consecutive Btrieve calls. This is fairly awful stuff, but I have seen one case where a file that reported a Status 2 on every single record could clearly have been recovered as seen through the Norton Utilities. This would not have been possi- ble with compressed Btrieve files. As an aside, this is not pos- Btrieve Version 6… sible using Btrieve’s data encryption either. Using the method described above, each and every record from this non-com- pressed, non-encrypted file was recovered. Btrieve version 6.10 adds several new features, many of My recommendations? If you have ever been or expect to which seem to be logical extensions of the functionality found be in a position where a file is damaged and you do not have a in previous versions. Some of these address specific problems recent backup, do not design a database that uses data com- or enhancements suggested by Btrieve developers. There are pression! This is easy for me to say, and of course assumes the several enhancements which make Btrieve more attractive in file in question is not insanely large. Even in the case of the Windows and OS/2 environments, such as percentage opera- insanely large file that is the perfect type for data compression tions, and the ability to handle huge records. And, of course, (lots of contiguous fields that are normally blanks or null char- Btrieve maintains its commitment to keeping your data safe, acters), a test might be in order: Prepare two otherwise identi- with a number of data integrity enhancements. Many new fea- cal files and set up one to use data compression and the other tures should prove quite useful, some of the others seem to have not. Get a good sample of data and load that data into each very limited application. Many of the important changes will be file. Look at the respective file sizes and file loading times. In discussed in this article. most cases, there will be little difference. With the numbers in Index Enhancements mind, decide if the possible risks, should exotic data recovery The maximum number of key segments available for a be required, outweigh the savings of disk space. Btrieve file increases in version 6 from 24 to 119 key segments. As always, the decision is yours. Good luck! Page size options are remain 512 to 4096 bytes, in multiples of 512, and the choice of page size dictates the maximum number 2 of key segments and maximum fixed-length record size as national languages. The ACS may be defined either in manner before, according to the following table: used by earlier versions, or it may be referenced by country ID and code page. The locale sensitive ACS can also query the Page Size Number of Segments operating system of the station running Btrieve (the server, in 512 8 1024 23 the case of the NLM) and use the collating sequence defined for 1536 24 local language support when a file or index is created. 2048-3584 54 4096 119 Btrieve version 6 adds support for index field type 17, the NumericSTS type. Also referred to as the sign trailing separate The ability to add or drop any index on an existing file type, NumericSTS is used primarily by COBOL applications, seems to be more a shift in semantics that an actual structural and by some accounting packages. It is similar to the Numeric change, as there was never a functional difference between sup- data type, key type 8, in that the number is stored in its ASCII plemental indexes (which could be added or dropped) and representation (0x30—0x39), right-justified, and padded with indexes (which could not) in previous versions. Supplemental leading zeros (0x30). As with the Numeric type, the decimal indexes go the way of all great ideas in the newer version, as point is implied. Unlike type 8 Numeric, the sign is not embed- there is no longer a distinction made between indexes and sup- ded with the last decimal digit, but is stored separately in the plemental indexes. Hence the Create Supplemental Index func- rightmost byte of the field. The last decimal digit is stored in the tion, operation code 31, has become simply Create Index. The penultimate byte, and the last byte is either ‘+’ (0x2B) or primary functional difference seems to be that, whereas supple- ‘-’ (0x2D) for positive or negative numbers, respectively. mental indexes had to be dropped on a last in, first out basis, a New Functionality programmer may now drop or add an index in the middle of the Btrieve adds two new percentage operations, Find numeric index sequence, and specify whether or not to renum- Percentage (45) and Get By Percentage (44). Programmers can ber the subsequent indexes. This one seemingly small difference represent record position, either physical position within the file, is worth the price of admission, especially to people developing or position along an index path, as a percentage of the total Btrieve applications, as it reduces the likelihood that one will number of records in the file. With these operations, Btrieve have to recompile an entire system simply to implement a programs can be made as GUI as gum on a sidewalk in July, change in index structure. Performance is further enhanced by with scroll bars, virtual list boxes, and other miracles of modern the fact that files can now be opened and read while a Create technology. Index operation is in progress. The file cannot be updated dur- With the new version it is possible to read along an index ing this time, however, and the new index will not be available path, and update the index values, with no currency change in for use until the process concludes. The time it takes to add an the index positioning. This promises to be a useful enhance- index, as in pre-6.0 versions, will depend on the number of ment. Now it will be a simple matter for me to fetch all the records in the file, the file size, and the length of the index to be unfinished task records in my Btrieve calendar file for January, added. 1994, using the due date as a key, and reschedule them some- In prior versions of Btrieve, case insensitivity was handled time in late February. This is a depressing task, but an illustra- by using UPPER.ALT as the alternate collating sequence for a tive one. With this option I can change a key value from file. ASCII sequence case insensitivity is now an attribute of the January 10th, 1994 to February 29th or 30th, without losing my key itself. Case insensitivity does not apply if the key is sorted place in mid-January. according to an alternate collating sequence, however, so it According to the NetWare 3.11 manuals, “some applica- seems that little has actually changed in this regard. A key can tions cannot be run from subdirectories…if you want to use an now be made ASCII case-insensitive without assigning an alter- application that must be installed at the root, you can load the nate collating sequence to the key, but functionally the effect is files in a subdirectory” and use a MAP ROOT command in the the same. In other words, you may sort a string based upon a login script. Since subdirectories have been around since DOS Danish character set by defining it as an alternate collating version 2, most marginally intelligent programs have no such sequence, but you cannot make it case-insensitive using this root directory limitations. Still, for those locked in glacial ice, flag, because the primary collating sequence remains the ASCII the Btrieve DOS and OS/2 requesters now support MAP ROOT sequence. Instead, you would have to create Danish case-sensi- drives and NetWare file level security. What tremendous advan- tive and case-insensitive collating sequences, and use them as tage accrues from this development is lost on this reviewer, but appropriate. judging by the number of years this has been an issue, I can One promising enhancement is the ability to assign multiple only hope the benefits to whomever they accrue justify the task alternate collating sequences to a file. ACS’s can be assigned on of the revision. an index-by-index basis. This can be done by assigning an alter- New Support for Huge Records nate collating sequence definition to an index when the index or Operation on record chunks from all appearances, is an file is created. Thus a file might contain both case-sensitive and adaptation of the data extractor functions of Btrieve Extended case-insensitive string keys in the Danish character set collating Operations, extended, as it were, to single records. Essentially sequence, or it could contain keys collated correctly in multiple chunk operations allow a programmer to define a structure to receive part or parts of a record buffer. This can be especially the use of variable-tail allocation tables, and the fact that the helpful when dealing with very long records. There are two selected page size must be able to accommodate the size of any chunk operations, Get Direct Chunk, and Update Chunk. The keys added after file creation. structure definition is passed in the data buffer, and the chunk of It is suggested in the new version that developers choose an data is either returned in the data buffer, or returned at an even multiple of 512 for the page size, “to optimize perfor- address specified by a far pointer in the chunk descriptor. mance.” We have not tested this assertion, but Btrieve page size Chunk operations make it possible to create single variable optimization has always been something of a combination of length records with a record length in excess of 64K bytes. The key and record length requirements, algebra, the black arts, and 64K limit imposed by the range of the one-word data buffer personal preference. If previous versions offer any indication, length parameter can be broken by handling the record in seg- even the most poorly optimized of page sizes will work satisfac- ments using these operations. This functionality will prove use- torily. ful to those developing applications which need to index very Enhanced Data Integrity Assurance large data objects, such as documents, images, and multi-media. The Btrieve design team has been justifiably proud of their To optimize chunk operations on large variable-length product’s fault tolerance in the face of potentially catastrophic records, Btrieve can use variable-tail allocation tables or VAT’s. system failures. In a Btrieve context, system failure means These tables are maintained by Btrieve on large variable length something really unfortunate which would wipe out most other records, and allow the record manager to skip over parts of the databases, events such as power outages, impatient users who variable length portion of the record when performing non- re-boot during an update, or mice nesting in the file server. The sequential chunk access on very large records. The programmer new version replaces pre-image files with the technique of shad- makes the decision whether or not to use VAT’s in a file sup- ow paging. Upon updating a page, Btrieve first makes a dupli- porting variable-length records when the file is created. VAT’s cate of the page to be modified in an unused portion of the file offer a performance advantage only if an application uses ran- Changes are made only to the copied page, and when the dom access chunk operations on files with huge records which changes are committed, Btrieve activates the new page, and exceed the physical page size of the file by a factor of at least marks the original page for re-use. In the event of a system fail- eight. They offer no advantage to applications which perform ure during the update, Btrieve simply discards the changes to only whole record operations, or sequential chunk operations. the copied page and reverts to the original. Data integrity is fur- How this technology is to be applied is not altogether clear, as ther insured by file logging, roll forward, and roll back capabili- most objects which require huge record storage, such as images, ties. tend to be stored and retrieved sequentially. Previous versions of Btrieve implemented transaction pro- Storage and Performance Optimization cessing, and it has always been an attractive data integrity Index Balancing improves the way in which Btrieve utilizes option. Because in previous versions, a transaction placed file- its index pages. Without index balancing, when an index page level locks on all of the affected files, it was often not practical became full, Btrieve creates a new index page and splits the to implement transaction processing where it was needed most - index data between the two pages. With index balancing, on large multi-user networks where many programs shared the Btrieve attempts first to utilize unused space on other index same data files. The new version, however, makes use of its pages associated with the same key, possibly resulting in fewer shadow paging capabilities to allow either concurrent or exclu- index pages, better density, and even distribution of keys among sive transactions on the same files. Concurrent transactions nodes on the same level. operate by locking only the pages they need to update. Other Duplicate key values can be stored one two ways in Btrieve stations may lock unused pages, or may read pages locked by a version 6. They may be defined as linked duplicate keys, in transaction. They may not lock pages already locked by another which case a pointer to the previous and next key values are transaction. Prior to version 6, updates within a transaction were stored in the data page of each record containing an instance of committed as they were made, and rolled back if the transaction the duplicate. Or they may be defined as repeating duplicate did not succeed. With shadow paging, transactions are not com- keys, in which case the value of the key resides on the data page mitted until the transaction is complete, so other stations will for each record, and is repeated as an index value entry on the not be able to see the changes made within a transaction until index page. Repeating duplicate keys are defined using the same the transaction finishes. key flag as the old supplemental index type, and this, combined The continuous operation feature adds another weapon in with the fact that in prior versions the addition of supplemental the fight against data loss. Archiving a data file requires a peri- indices did not affect minimum page size considerations for the od of time when the file is not being updated, so that a true copy file, suggests that repeating duplicate keys have the same char- can be made. Continuous operation redirects file changes to a acteristics as the old supplemental index. delta file, so that file operations can continue while the static With the introduction of the new file format, there are sev- copy of the file is being archived. After the archive copy is eral new page size considerations. Several of the new options made, continuous operation can be terminated, at which time the affect the minimum and optimum page size values for a file, file is updated with the changes made since continuous opera- including the number of reserved duplicate pointers specified, tion was begun. COMING UP IN BTRIEVE DEVELOPER’S JOURNAL Special Assignment… The New, Improved Btrieve Are you interested in where Btrieve is headed? We go to talk again with Doug Woodward about how the recent developments between Novell and Btrieve will affect Btrieve as a Btrieve File Recovery database standard and what we can expect to see in the near future... Btrieve and Visual Basic: A By Doug Reilly and Scott Smith How-to Guide Steve Mook looks at Visual Basic and the many ways that Btrieve can be used with this platform that is quickly becoming the most popular Btrieve development Editor’s note: Some of the material for this article was first environment ever... used by Doug Reilly in his article, “Inside Btrieve Files” in the March 1993 issue of Dr. Dobb’s Journal. Btrieve Btrieve’s Extended and Chunk Developer’s Journal is grateful to John Erickson of Dr. Operations Dobb’s for giving us the permission to use many of Doug’s Doug Reilly examines how extended operations from GET to INSERT and how new Btrieve discoveries here in this BDJ Special Assignment. version 6.x chunk operations can be used to get the most speed and efficiency out of your Btrieve applications... Not much has ever been written about the internal struc- Multi Language Applications ture of a Btrieve file. But since Btrieve is a widely used file How well does Btrieve support languages other than English. You will find out in BDJ... manager, maintaining legacy data for small, medium, and large businesses alike, there are many developers who need to know Readership Survey Results exactly how Btrieve works and how best to recover data from We took the task of surveying a few hundred random subscribers of Btrieve Developer’s a damaged Btrieve file. This article attempts to do just that. Journal to see what they thought about Btrieve. You will see our results here... Most of what is presented here is undocumented by All Locked Up: A Guide to Writing Novell. As with any element of a proprietary system, some Multi-User Btrieve Applications aspects of Btrieve files are undocumented in order to hide What is the best way to implement locks in the Btrieve environment? How do locks vary in details of implementation from the outside world in order to different versions of Btrieve? What problems can locks cause that the application developer ensure that the developer is shielded from changes to these should be aware of? We give you the answers to these questions and more in this details. The information presented here is valid for Btrieve Special Report... files version 4.11 through version 5.x. Btrieve version 6.x has NetWare SQL and Btrieve: How certainly changed much of these details. We will present more information on the same recovery methods for Btrieve version Does it all Come Together? 6.x in a future issue of Btrieve Developer’s Journal. We look in depth at the features of Novell’s SQL implementation of Btrieve on a NetWare server. What’s required to use it and what advantages does it give the application Let’s start with some . Btrieve files consist of developer and user? You’ll get the scoop on just how NetWare SQL compares to other SQL “pages.” When a file is created, Btrieve requires that you spec- servers as well... ify a page which is between 512 and 4096 and is divisible by 512. This page size must fit at least one of the fixed length In Our Opinion... portions of the record being created. Btrieve allows variable What does Novell need to do with Btrieve? We compile comments from letters that we length records, but each variable length record has a fixed have been receiving from our readers as well as our own ideas about what we would all length portion as well. like to see in the future of Btrieve. Why don’t you let us hear from you on this topic? A Btrieve file consists of three basic page types. First, Data Type Conversions there is a single header page which contains status information Steve Mook looks into how to convert and decode more data types that developer’s may for the file. A Second header page may exist to define an use to store data in Btrieve files... “Alternate Collating Sequence” which can change the way In the Field strings are sorted. The second type of page is an index page Gary Coombs of Scientific Atlanta explains how Btrieve has become a major player in and the third is the data page. A variation of the data page facilitating many of his company’s data management needs... called the Variable Data Page exists in Btrieve files that allow variable length records. Most Btrieve files have both index pages and data pages, but Btrieve will allow key-only and

23 data-only files. (Note that Novell generally refers to an index cannot be derived from other components or sources. segment as a “key”, and a group of keys as an “index”) Since many different errors can occur in a Btrieve-based All different pages within a Btrieve file are the same size system, the first step in diagnosing a Btrieve file problem is to — the page size specified at the time the file was created. For determine what sort of error is occurring. Btrieve has many this article, we have created a sample Btrieve file with a page status codes. Those related to damaged files are listed in Table size of 512 and one key segment starting at position 1 for 11 2. Several of the status codes that could lead to a damaged bytes. Btrieve file refer to a “pre-image” file. Details of data relevant to file recovery contained in the One of the ways data in Btrieve 5.x files is protected is header page is presented in Table 1.Official information on through use of a pre-image file. This is a file that is created data in the header page is relatively sketchy, but some facts are when a file is first updated, and contains images of the pages known. in the file before the update occurs. If the operation is inter- The byte at offset HEX 0x07 indicates whether the file has rupted (for instance, the program hangs or the power fails), the an owner name and whether the file has enabled data compres- next time the file is opened the pre-image file is read and the sion. If the 5 left-most bits are 1, then the file has an owner file is restored to the condition it was in just after the last com- name. If the right-most bit is 1, then the file has data compres- plete operation. sion enabled. The most common Btrieve error code is status 2, an I/O The byte at offset 0x09 contains the total number of 256 error. This could be caused by almost anything. Novell has a byte segments in each page of the file. A 512 page size will list of 33 distinct causes of status 2’s, and it is possible they have a 2, as 1024 page size will have a 4, etc. Since the value have missed a few! Look back at figures 1 through 4. Notice at offset 0x09 in figure 1 is 0x06, then the page size for this that in byte 3 of each record there is a number that acts like a file is 6 times 256 or 1536 bytes. “page count,” with the header page having a 0, the alternate The bytes beginning at offset 0x26 through 0x29, Btrieve collating sequence having a 1, the index page having a 2, etc. stores the length of the file measured in pages. The directory Btrieve appears to use this number as a “sanity check.” On the listing on the file used to generate figure 1 indicates that the index page, change that 3 to 7 and a status 2 will appear. Your file occupies 9216 bytes on the disk. Dividing this value by data is still just fine, but that one byte changed (or any of the 4 1536, we get 6. So, this file should indicate 6 total pages in the bytes that are part of the page count) will cause a Btrieve sta- data at offset 0x26 through 0x29. tus 2. The owner name is stored in bytes at offset 0x46 through Start with the easiest recovery option first. Btrieve allows 0x54 in a proprietary manner. Note that these bytes continue to reading of records by logical positioning (that is, via an index) have the owner name text even if the owner is subsequently or by physical positioning. To recover data from a damaged cleared from the file. Btrieve file physical positioning must be used. See the pseudo The byte at offset 0x55 is the final important header byte code in listing 1. To recover the damaged file, we start from when considering file recovery. This byte indicates the access the first physical record, and read towards the end of the file. If restrictions used when the owner name was assigned. If bit 2 is we receive a non-zero status other than 9 “End of file”, we 1, then the file has been encrypted and data recovery directly save the physical positioning information from the last suc- from the data contained physically within the Btrieve file is not cessfully read record and get the last physical record. We read possible. towards the beginning of the file, stopping when a Btrieve A second header may exist in a Btrieve file which is used error occurs or when we read the last record we had previously for storing an alternate collating sequence for the file. read. Now we close the files and exit. The next type of page in a Btrieve file is the “index” page The recovery procedure just described is what Novell’s (see figure 4). The number of index pages depends upon the utility BUTIL does during a -RECOVER operation, saving number of indexes in the file, as well as the number of records. records to a sequential file in a special format. In many cases These are of little use independent of the actual data, but one that is all that needs to be done. But what happens in the case might find it interesting to track the pointers near each “key” of multiple non-adjacent errors in the file? In that case, we on the index pages back to the data they are representing. In a start at the beginning of the file, step forward until we find an data only record it is possible that no index page will exist. error, then go the end of the file and step back until we find an The final type of page is the “data” page. There are at error or read the same record as the last successfully read least two types of data pages. The “normal” data page (see fig- record when we were stepping forward. If the error we find ure 2) for fixed length records (or fixed length portions of vari- stepping back is not the error we find stepping forward, the able length records) and the variable length data pages (see fig- records between the two errors will not be read. Here is where ure 3). In a key only record, no data pages will exist. our knowledge of Btrieve files (and some undocumented When it comes to Btrieve file recovery, this last type of aspects of Btrieve files) comes in handy. page is the most important. The header can be rebuilt from a In listing 1, we talk about saving physical positioning similar file (as we will see), indexes can be recreated given the information. This takes the form of a four byte value that is in correct data and enough time, but the data is the one thing that fact the offset in the file where the record occurs. (This discus-

24 sion ignores for a moment the fact that Btrieve for DOS allows listing on the file used to generate figure 1, we find that it is files to extend over more than one disk drive). Btrieve also 9216 bytes. Dividing this value by the page size of 1536, we allows you to set the position in a file. In most uses of this set get 6. So, if we were to be repairing this file, we take the need position function (GET_DIRECT, Btrieve function 23) a 4 to put a 0x06 at byte offset 28. This would make the number of byte block obtained from a previous call to GET_POSITION pages equal to 6. (Btrieve function 22) is used. But this is a time where we have In our example in figure 1, bytes 26 through 29 do contain to figure it out ourselves. “00 00 06 00”. If the header page was damaged, and we did We know that every Btrieve file has 6-bytes of overhead insert the “00 00 06 00” into the file after replacing the header on every data page in addition to the data itself. We can prove page with a header page from a clone file, we would then be this to ourselves by creating a new Btrieve file and then look- able to use the file recovery procedure described above. File ing to see where the record is placed on the data page. From recovery is still needed, because some information needed for this we know that the only possible place where the first record accessing the file will still be missing. C code to rebuild a on a page can be found is 6 bytes from the start of the data damaged file header is provided in listing 2. page. But how do we know what pages are data pages and As we all know, Btrieve as a file manager is fairly robust. what pages are index pages? We could use DOS functions to Many Btrieve developers go for years without seeing some of read through the file, checking the bytes at the beginning of these conditions. The Btrieve Developer’s kit provides the each page. Data pages have some distinctive values in two of BUTIL program that handles the most common of the file the 6 overhead bytes that are not the “page count” discussed recovery procedures. In addition, several commercial, share- above. This seems a little too low level, and thankfully there is ware, and public domain programs exist to recover damaged a better way. Btrieve files. We can ignore the first page of the file, since we know But what you don’t know can hurt you. For instance, some that will always be a header page. We can calculate the total of the data recovery methods described depend upon knowing number of pages in the file by dividing the file length by the where records start. With Btrieve compressed records such page size. Then for each page we do a GET_DIRECT at 6 methods cannot be used, since the starting position for records bytes from the beginning of the page. If there is no error, or is dependent upon the data in previous records. If as a develop- the error that does occur is not a status 43 “Invalid er you do not understand exactly what it means to use Btrieve Positioning,” we have found a data page. We save the record data compression, you can end up with a file that is no smaller we have gotten through the GET_DIRECT operation, and cal- than a similar file without compression that is somewhat slow- culate where the next record will start. er to boot. (See Doug’s Inside Btrieve column on Btrieve From a quick glance through the Btrieve Library Compression on page 19). Reference book, we can tell the physical record length of any In the next issue of Btrieve Developer’s Journal, we will record: discuss how some of the material provided above has changed (logical_record_length+(number_of_dup_keys*8)) with version 6.x Btrieve. So now we can simply take the position of the first record, add the physical record length, and call GET_DIRECT again. Figure 1 — Btrieve Header Page. We can repeat this until the position is past the page on which we are working, and can repeat the entire procedure (look for a record at 6 bytes into the page) for every page in the file. A second type of problem can occur in Btrieve files. This problem will show itself by reporting a status 30 “Not a Btrieve file” after an OPEN operation. You can try to recover a file using the procedures described above, but it will not work since Btrieve will not open the file. When Btrieve reports a sta- tus 30, what it is really saying is that the header of the file is not consistent with what Btrieve expects in the header. Fortunately, there is a possible solution. This solution uses a “clone” of the damaged file. A “clone” is a Btrieve file with the exact same page size, record length, key structure, etc. Copy the header from the good “clone” file over the header in the damaged file, remembering that the header is the first x bytes of the file where x is the page size. Now we have to do one more thing before we can use this data recovery method. In the bytes at offset 0x26 through 0x29, Btrieve stores the length of the file, measured in pages. If we do a directory

25 Figure 2 — Btrieve Data Page. Table 1 — Description of recovery data found in the Btrieve header page.

HEX Offset Description 0x07 If 5 left bits of byte are 1 (0xF8) then owner name is set. 0x09 Total 256 byte segments in one Btrieve page. Ox26—Ox29 Total pages in file. 0x46—0x54 Coded owner name. 0x55 Encryption/Read Only flag.

Table 2 — Status codes which may indicate a damaged file.

Status Description Figure 3 — Btrieve Variable Data Page. 2 I/O Error 14 Pre-image Open Error 15 Pre-image I/O Error 30 Not a Btrieve File Error 42 Incomplete Accelerated Access 56 Incomplete Index

Listing 1— Pseudo code for Btrieve error 2 recovery OPEN (Btrieve function 0) damaged file Open destination file (Could be Btrieve file, could be DOS Sequential file) if STEP_FIRST (Btrv op 33) does not return an error DO write record to destination file save physical position from call to Figure 4 — Btrieve Index Page. GET_POSITION (Btrv op 22) in last_saved_pos. WHILE STEP_NEXT (Btrv op 24) does not return an error. if last Btrieve error is not an end of file error if STEP_LAST (Btrv op 34) does not return an error DO write record to destination file save the physical position from call to GET_POSITION (Btrv op 22) in cur_pos. WHILE STEP_PREV (Btrv op 35) does not return an error AND cur_pos is not equal to last_saved_pos CLOSE (Btrieve function 1) source close destination file (either Btrieve or DOS sequential file).

Listing 2— C Code to rebuild a damaged file. #include “stdio.h” #include “stdio.h”

/* Given a FILE pointer, return the length of the file. */

long filelen(FILE *t) { int i; long loc;

26 long begloc; b1=b1/0x1000000L; b2=(num_pages&0x00FF0000L); extern errno; b2=b2/0x10000L; errno=0; b3=(num_pages&0x0000FF00L); if ( (begloc=ftell(t))==-1L || b3=b3/0x100; (fseek(t,0L,SEEK_END))!=0 || b4=(num_pages&0x000000FFL); (loc=ftell(t))==-1L || headerbuf[0x26]=(char)(b2); (fseek(t,begloc,SEEK_SET))!=0 ) headerbuf[0x27]=(char)(b1); { headerbuf[0x28]=(char)(b4); return(-1L); headerbuf[0x29]=(char)(b3); } /* get to the start of the file... */ return(loc); fseek(out,0L,SEEK_SET); } /* write the header */ ret=fwrite(headerbuf,1,pageSize,out); /* fclose(out); Given the name of a damaged file, a good return(ret); “clone” of the damaged file, rebuild the } header on the damaged file. Don’t use this file directly, but next do a simple recover on the file so that the rest of the informa- tion in the header is updated.

This should NOT be tried on any file except one that returns a Btrieve status 2 (I/O error) or 30 (Not a Btrieve file) on OPEN. */ int do_hdr_rebld(char *damagedFile,char *goodClone,int pageSize) { Interested in BDJ Advertising? Btrieve Developer’s Journal has a limited amount of int ret; space reserved for products that supprt Btrieve. To receive char headerbuf[4096]; an advertising packet including rate card and requirements, long damaged_size=0L; long num_pages=0L; contact: long b1,b2,b3,b4; Btrieve Developer’s Journal FILE *in; Advertising FILE *out; Post Office Box 50002 /* Open the good clone file, if you can */ Nashville, TN 37205 if ( (in=fopen(goodClone,”rb”))==NULL ) FAX: (615) 665-2383 { printf(“\nCan’t open undamaged file to CompuServe: 73173,2731 read header. Exiting”); return(0); } /* read the header from the good file */ fread(headerbuf,1,pageSize,in); fclose(in); if ( (out=fopen(damagedFile,”r+b”))==NULL ) { printf(“\nCan’t open damaged file. Exiting.”); return(0); } /* get the length of the file, in bytes. */ if ( (damaged_size=filelen(out))==-1 ) { printf(“\nCan’t read damaged file. Exiting.”); return(0); } /* convert to pages. We could do a sanity check to ensure that the file length is even- ly divisible by the page length. */ num_pages=damaged_size/(long)pageSize; /* isolate each byte. Yep, there probably is a better way (shifting bits), but this seems clearer to me, and we won’t use this routine very often. */ b1=(num_pages&0xFF000000L);

27 In the first darn paragraph, you told me something I really needed to know... that was probably worth the subscription price. Then, the interview with Doug Woodward went a long way towards explaining why Btrieve is the way it is. The Letters and enhancements he envisions for it seems to fit right in with our thoughts, too. Nice job; ’nuff said. After looking over Doug Reilly’s page size optimization Comments… routine, I realized that we had an error in our own routine. Then I read about DDF’s. I didn’t even know such a thing existed. In short, you guys taught me something on 6 out of 8 Dear Btrieve Developer’s Journal pages; a superb “hit” ratio, and in the very first issue, no less. I I am in receipt of your Premier issue of Btrieve really think BDJ is a required part of any developer’s “tool Developer’s Journal, and want to begin my subscription for kit.” our bank ASAP. The concept is an excellent one, as no period- Mark Fisher, Cincinnati, Ohio ical exists that is solely dedicated to Btrieve issues. Kudos for an excellent idea! Dear Btrieve Developer’s Journal Kenneth A. Lundberg, Louisville, Kentucky It’s good to see that you’ve started a publication devoted to Btrieve. I’ve been using it for years and I can certainly ben- Dear Btrieve Developer’s Journal efit from a publication that can keep me up-to-date on Btrieve- I just finished reading your premier issue, and I want to related products. Your interview with Doug Woodward was congratulate you on an excellent trade journal. We’ve chosen amazing in at least one way. Does Doug really believe we to subscribe… We are concerned about the use of Novell’s would buy his response to the comment that Btrieve is a “lega- 16-bit version of WBTRCALL from a 32-bit application… cy product?” It’s clear to me that many within Novell do not So far it looks like we can get to the DLL through a mecha- know what Btrieve is or does. They don’t know why you nism Microsoft refers to as a “Universal Thunk,” but I think would use it instead of one of the more fashionable, higher we still have some homework to do. priced, lower performance SQL engines. The Novell manager It would seem many Btrieve developers will be going that made the comment that Btrieve was a legacy product through this same research exercise, so I thought you could meant that it was an obsolete product. No need to hide that fact explore and perhaps share your findings to other developers. from me Doug. I can take it. Again, thanks for an excellent journal. Where were you guys You mention that you’ll be running an article soon which when I was first learning Btrieve? compares the performance of the various Btrieve implementa- John J. McCarthy, Smyrna, Georgia tions. While this will certainly be interesting reading, I really Dear Btrieve Developer’s Journal don’t need to know how badly the Btrieve VAP performs since …I am most concerned with getting a workable copy of the NetWare 2 product line is obsolete. (A product can still be the Btrieve DLL in Windows NT. Just a few weeks ago, I obsolete even though a vendor is still selling it) I’m far more confirmed that the 16-bit DLL cannot be thunked from the interested in comparing Btrieve’s performance against other 32-bit NT side… database engine products. This is something I plan to do unless Kai Tong Tham, New York City, New York you do it first. Ed Sawicki, Lake Oswego, Oregon Editor’s Note: There is a file on the Novell Vendor Forum (GO NovVen) called BTR32.ZIP. Here is the file’s description: Editor’s Note: Doug Woodward stands by his assertion that “Sorry I can’t offer you a 32-Bit WBTRCALL.DLL, but with when Nancy Cellnicker called Btrieve a “Legacy product,” she the stuff in this you can access your BTRIEVE files from a meant that Btrieve was used to handle legacy data, and it’s 32-BIT app written for Windows NT. Includes a small 16-bit therefore a vital part of many businesses today. Nancy server app with source.” Cellnicker is the Btrieve Product Manager at Novell.

Dear Btrieve Developer’s Journal Let Us Hear From You…We want to make Btrieve Developer’s Journal just right. In Shoot! I’m just about as mad at you guys as I can be! order to do that, we need to know what you would like to see in future issues. Send us When the premier issue of the Btrieve Developer’s Journal any news, information, comments, suggestions or anything else, so that BDJ can address the topics that interest you most. And, since we are working closely with Btrieve showed up in my mailbox earlier this week with its listed price Technologies, Inc., you can be sure that your comments will be heard and they could of $49 for four issues, I showed my boss, and we both had a possibly help define the future of Btrieve. Address letters to: good laugh... Yesterday morning, I didn’t have anything much Btrieve Developer’s Journal to do, so I got a cup of coffee and sat down to give it a more Scott Smith, Publisher thorough post-mortem. After about 15 minutes, I felt pretty Post Office Box 50002, Nashville, TN 37205 foolish. FAX: (615) 665-2383 CompuServe: 73173,2731

28