From e7119d0a40b5e8d94f4262bfe56b61afda2946b9 Mon Sep 17 00:00:00 2001 From: agibert Date: Tue, 28 Feb 2006 23:28:21 +0000 Subject: [PATCH] Initial creation. --- GNU-FDL.txt | 355 +++++++++++++++ GNU-GPL.txt | 340 ++++++++++++++ GNU-LGPL.txt | 504 +++++++++++++++++++++ ReadMe.txt | 36 ++ ReleaseNotes.txt | 47 ++ ToDo.txt | 15 + doc/libdatabase.doc | Bin 0 -> 35840 bytes include/database.h | 359 +++++++++++++++ lib/libdatabase.c | 971 ++++++++++++++++++++++++++++++++++++++++ utils/dbbench.c | 709 +++++++++++++++++++++++++++++ utils/dbtest.c | 241 ++++++++++ utils/perfResults.txt | 91 ++++ utils/testEntr.c | 336 ++++++++++++++ utils/testEntr.h | 65 +++ utils/testEntrColumns.c | 189 ++++++++ utils/testEntrColumns.h | 48 ++ utils/testInsert.c | 368 +++++++++++++++ utils/testSelect.c | 272 +++++++++++ utils/testUpdate.c | 236 ++++++++++ utils/testUpdateArray.c | 338 ++++++++++++++ 20 files changed, 5520 insertions(+) create mode 100644 GNU-FDL.txt create mode 100644 GNU-GPL.txt create mode 100644 GNU-LGPL.txt create mode 100644 ReadMe.txt create mode 100644 ReleaseNotes.txt create mode 100644 ToDo.txt create mode 100644 doc/libdatabase.doc create mode 100644 include/database.h create mode 100644 lib/libdatabase.c create mode 100644 utils/dbbench.c create mode 100644 utils/dbtest.c create mode 100644 utils/perfResults.txt create mode 100644 utils/testEntr.c create mode 100644 utils/testEntr.h create mode 100644 utils/testEntrColumns.c create mode 100644 utils/testEntrColumns.h create mode 100644 utils/testInsert.c create mode 100644 utils/testSelect.c create mode 100644 utils/testUpdate.c create mode 100644 utils/testUpdateArray.c diff --git a/GNU-FDL.txt b/GNU-FDL.txt new file mode 100644 index 0000000..b42936b --- /dev/null +++ b/GNU-FDL.txt @@ -0,0 +1,355 @@ + GNU Free Documentation License + Version 1.1, March 2000 + + Copyright (C) 2000 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + +0. PREAMBLE + +The purpose of this License is to make a manual, textbook, or other +written document "free" in the sense of freedom: to assure everyone +the effective freedom to copy and redistribute it, with or without +modifying it, either commercially or noncommercially. Secondarily, +this License preserves for the author and publisher a way to get +credit for their work, while not being considered responsible for +modifications made by others. + +This License is a kind of "copyleft", which means that derivative +works of the document must themselves be free in the same sense. It +complements the GNU General Public License, which is a copyleft +license designed for free software. + +We have designed this License in order to use it for manuals for free +software, because free software needs free documentation: a free +program should come with manuals providing the same freedoms that the +software does. But this License is not limited to software manuals; +it can be used for any textual work, regardless of subject matter or +whether it is published as a printed book. We recommend this License +principally for works whose purpose is instruction or reference. + + +1. APPLICABILITY AND DEFINITIONS + +This License applies to any manual or other work that contains a +notice placed by the copyright holder saying it can be distributed +under the terms of this License. The "Document", below, refers to any +such manual or work. Any member of the public is a licensee, and is +addressed as "you". + +A "Modified Version" of the Document means any work containing the +Document or a portion of it, either copied verbatim, or with +modifications and/or translated into another language. + +A "Secondary Section" is a named appendix or a front-matter section of +the Document that deals exclusively with the relationship of the +publishers or authors of the Document to the Document's overall subject +(or to related matters) and contains nothing that could fall directly +within that overall subject. (For example, if the Document is in part a +textbook of mathematics, a Secondary Section may not explain any +mathematics.) The relationship could be a matter of historical +connection with the subject or with related matters, or of legal, +commercial, philosophical, ethical or political position regarding +them. + +The "Invariant Sections" are certain Secondary Sections whose titles +are designated, as being those of Invariant Sections, in the notice +that says that the Document is released under this License. + +The "Cover Texts" are certain short passages of text that are listed, +as Front-Cover Texts or Back-Cover Texts, in the notice that says that +the Document is released under this License. + +A "Transparent" copy of the Document means a machine-readable copy, +represented in a format whose specification is available to the +general public, whose contents can be viewed and edited directly and +straightforwardly with generic text editors or (for images composed of +pixels) generic paint programs or (for drawings) some widely available +drawing editor, and that is suitable for input to text formatters or +for automatic translation to a variety of formats suitable for input +to text formatters. A copy made in an otherwise Transparent file +format whose markup has been designed to thwart or discourage +subsequent modification by readers is not Transparent. A copy that is +not "Transparent" is called "Opaque". + +Examples of suitable formats for Transparent copies include plain +ASCII without markup, Texinfo input format, LaTeX input format, SGML +or XML using a publicly available DTD, and standard-conforming simple +HTML designed for human modification. Opaque formats include +PostScript, PDF, proprietary formats that can be read and edited only +by proprietary word processors, SGML or XML for which the DTD and/or +processing tools are not generally available, and the +machine-generated HTML produced by some word processors for output +purposes only. + +The "Title Page" means, for a printed book, the title page itself, +plus such following pages as are needed to hold, legibly, the material +this License requires to appear in the title page. For works in +formats which do not have any title page as such, "Title Page" means +the text near the most prominent appearance of the work's title, +preceding the beginning of the body of the text. + + +2. VERBATIM COPYING + +You may copy and distribute the Document in any medium, either +commercially or noncommercially, provided that this License, the +copyright notices, and the license notice saying this License applies +to the Document are reproduced in all copies, and that you add no other +conditions whatsoever to those of this License. You may not use +technical measures to obstruct or control the reading or further +copying of the copies you make or distribute. However, you may accept +compensation in exchange for copies. If you distribute a large enough +number of copies you must also follow the conditions in section 3. + +You may also lend copies, under the same conditions stated above, and +you may publicly display copies. + + +3. COPYING IN QUANTITY + +If you publish printed copies of the Document numbering more than 100, +and the Document's license notice requires Cover Texts, you must enclose +the copies in covers that carry, clearly and legibly, all these Cover +Texts: Front-Cover Texts on the front cover, and Back-Cover Texts on +the back cover. Both covers must also clearly and legibly identify +you as the publisher of these copies. The front cover must present +the full title with all words of the title equally prominent and +visible. You may add other material on the covers in addition. +Copying with changes limited to the covers, as long as they preserve +the title of the Document and satisfy these conditions, can be treated +as verbatim copying in other respects. + +If the required texts for either cover are too voluminous to fit +legibly, you should put the first ones listed (as many as fit +reasonably) on the actual cover, and continue the rest onto adjacent +pages. + +If you publish or distribute Opaque copies of the Document numbering +more than 100, you must either include a machine-readable Transparent +copy along with each Opaque copy, or state in or with each Opaque copy +a publicly-accessible computer-network location containing a complete +Transparent copy of the Document, free of added material, which the +general network-using public has access to download anonymously at no +charge using public-standard network protocols. If you use the latter +option, you must take reasonably prudent steps, when you begin +distribution of Opaque copies in quantity, to ensure that this +Transparent copy will remain thus accessible at the stated location +until at least one year after the last time you distribute an Opaque +copy (directly or through your agents or retailers) of that edition to +the public. + +It is requested, but not required, that you contact the authors of the +Document well before redistributing any large number of copies, to give +them a chance to provide you with an updated version of the Document. + + +4. MODIFICATIONS + +You may copy and distribute a Modified Version of the Document under +the conditions of sections 2 and 3 above, provided that you release +the Modified Version under precisely this License, with the Modified +Version filling the role of the Document, thus licensing distribution +and modification of the Modified Version to whoever possesses a copy +of it. In addition, you must do these things in the Modified Version: + +A. Use in the Title Page (and on the covers, if any) a title distinct + from that of the Document, and from those of previous versions + (which should, if there were any, be listed in the History section + of the Document). You may use the same title as a previous version + if the original publisher of that version gives permission. +B. List on the Title Page, as authors, one or more persons or entities + responsible for authorship of the modifications in the Modified + Version, together with at least five of the principal authors of the + Document (all of its principal authors, if it has less than five). +C. State on the Title page the name of the publisher of the + Modified Version, as the publisher. +D. Preserve all the copyright notices of the Document. +E. Add an appropriate copyright notice for your modifications + adjacent to the other copyright notices. +F. Include, immediately after the copyright notices, a license notice + giving the public permission to use the Modified Version under the + terms of this License, in the form shown in the Addendum below. +G. Preserve in that license notice the full lists of Invariant Sections + and required Cover Texts given in the Document's license notice. +H. Include an unaltered copy of this License. +I. Preserve the section entitled "History", and its title, and add to + it an item stating at least the title, year, new authors, and + publisher of the Modified Version as given on the Title Page. If + there is no section entitled "History" in the Document, create one + stating the title, year, authors, and publisher of the Document as + given on its Title Page, then add an item describing the Modified + Version as stated in the previous sentence. +J. Preserve the network location, if any, given in the Document for + public access to a Transparent copy of the Document, and likewise + the network locations given in the Document for previous versions + it was based on. These may be placed in the "History" section. + You may omit a network location for a work that was published at + least four years before the Document itself, or if the original + publisher of the version it refers to gives permission. +K. In any section entitled "Acknowledgements" or "Dedications", + preserve the section's title, and preserve in the section all the + substance and tone of each of the contributor acknowledgements + and/or dedications given therein. +L. Preserve all the Invariant Sections of the Document, + unaltered in their text and in their titles. Section numbers + or the equivalent are not considered part of the section titles. +M. Delete any section entitled "Endorsements". Such a section + may not be included in the Modified Version. +N. Do not retitle any existing section as "Endorsements" + or to conflict in title with any Invariant Section. + +If the Modified Version includes new front-matter sections or +appendices that qualify as Secondary Sections and contain no material +copied from the Document, you may at your option designate some or all +of these sections as invariant. To do this, add their titles to the +list of Invariant Sections in the Modified Version's license notice. +These titles must be distinct from any other section titles. + +You may add a section entitled "Endorsements", provided it contains +nothing but endorsements of your Modified Version by various +parties--for example, statements of peer review or that the text has +been approved by an organization as the authoritative definition of a +standard. + +You may add a passage of up to five words as a Front-Cover Text, and a +passage of up to 25 words as a Back-Cover Text, to the end of the list +of Cover Texts in the Modified Version. Only one passage of +Front-Cover Text and one of Back-Cover Text may be added by (or +through arrangements made by) any one entity. If the Document already +includes a cover text for the same cover, previously added by you or +by arrangement made by the same entity you are acting on behalf of, +you may not add another; but you may replace the old one, on explicit +permission from the previous publisher that added the old one. + +The author(s) and publisher(s) of the Document do not by this License +give permission to use their names for publicity for or to assert or +imply endorsement of any Modified Version. + + +5. COMBINING DOCUMENTS + +You may combine the Document with other documents released under this +License, under the terms defined in section 4 above for modified +versions, provided that you include in the combination all of the +Invariant Sections of all of the original documents, unmodified, and +list them all as Invariant Sections of your combined work in its +license notice. + +The combined work need only contain one copy of this License, and +multiple identical Invariant Sections may be replaced with a single +copy. If there are multiple Invariant Sections with the same name but +different contents, make the title of each such section unique by +adding at the end of it, in parentheses, the name of the original +author or publisher of that section if known, or else a unique number. +Make the same adjustment to the section titles in the list of +Invariant Sections in the license notice of the combined work. + +In the combination, you must combine any sections entitled "History" +in the various original documents, forming one section entitled +"History"; likewise combine any sections entitled "Acknowledgements", +and any sections entitled "Dedications". You must delete all sections +entitled "Endorsements." + + +6. COLLECTIONS OF DOCUMENTS + +You may make a collection consisting of the Document and other documents +released under this License, and replace the individual copies of this +License in the various documents with a single copy that is included in +the collection, provided that you follow the rules of this License for +verbatim copying of each of the documents in all other respects. + +You may extract a single document from such a collection, and distribute +it individually under this License, provided you insert a copy of this +License into the extracted document, and follow this License in all +other respects regarding verbatim copying of that document. + + +7. AGGREGATION WITH INDEPENDENT WORKS + +A compilation of the Document or its derivatives with other separate +and independent documents or works, in or on a volume of a storage or +distribution medium, does not as a whole count as a Modified Version +of the Document, provided no compilation copyright is claimed for the +compilation. Such a compilation is called an "aggregate", and this +License does not apply to the other self-contained works thus compiled +with the Document, on account of their being thus compiled, if they +are not themselves derivative works of the Document. + +If the Cover Text requirement of section 3 is applicable to these +copies of the Document, then if the Document is less than one quarter +of the entire aggregate, the Document's Cover Texts may be placed on +covers that surround only the Document within the aggregate. +Otherwise they must appear on covers around the whole aggregate. + + +8. TRANSLATION + +Translation is considered a kind of modification, so you may +distribute translations of the Document under the terms of section 4. +Replacing Invariant Sections with translations requires special +permission from their copyright holders, but you may include +translations of some or all Invariant Sections in addition to the +original versions of these Invariant Sections. You may include a +translation of this License provided that you also include the +original English version of this License. In case of a disagreement +between the translation and the original English version of this +License, the original English version will prevail. + + +9. TERMINATION + +You may not copy, modify, sublicense, or distribute the Document except +as expressly provided for under this License. Any other attempt to +copy, modify, sublicense or distribute the Document is void, and will +automatically terminate your rights under this License. However, +parties who have received copies, or rights, from you under this +License will not have their licenses terminated so long as such +parties remain in full compliance. + + +10. FUTURE REVISIONS OF THIS LICENSE + +The Free Software Foundation may publish new, revised versions +of the GNU Free Documentation License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. See +http://www.gnu.org/copyleft/. + +Each version of the License is given a distinguishing version number. +If the Document specifies that a particular numbered version of this +License "or any later version" applies to it, you have the option of +following the terms and conditions either of that specified version or +of any later version that has been published (not as a draft) by the +Free Software Foundation. If the Document does not specify a version +number of this License, you may choose any version ever published (not +as a draft) by the Free Software Foundation. + + +ADDENDUM: How to use this License for your documents + +To use this License in a document you have written, include a copy of +the License in the document and put the following copyright and +license notices just after the title page: + + Copyright (c) YEAR YOUR NAME. + Permission is granted to copy, distribute and/or modify this document + under the terms of the GNU Free Documentation License, Version 1.1 + or any later version published by the Free Software Foundation; + with the Invariant Sections being LIST THEIR TITLES, with the + Front-Cover Texts being LIST, and with the Back-Cover Texts being LIST. + A copy of the license is included in the section entitled "GNU + Free Documentation License". + +If you have no Invariant Sections, write "with no Invariant Sections" +instead of saying which ones are invariant. If you have no +Front-Cover Texts, write "no Front-Cover Texts" instead of +"Front-Cover Texts being LIST"; likewise for Back-Cover Texts. + +If your document contains nontrivial examples of program code, we +recommend releasing these examples in parallel under your choice of +free software license, such as the GNU General Public License, +to permit their use in free software. diff --git a/GNU-GPL.txt b/GNU-GPL.txt new file mode 100644 index 0000000..5b6e7c6 --- /dev/null +++ b/GNU-GPL.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. diff --git a/GNU-LGPL.txt b/GNU-LGPL.txt new file mode 100644 index 0000000..b1e3f5a --- /dev/null +++ b/GNU-LGPL.txt @@ -0,0 +1,504 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 2.1, February 1999 + + Copyright (C) 1991, 1999 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + +[This is the first released version of the Lesser GPL. It also counts + as the successor of the GNU Library Public License, version 2, hence + the version number 2.1.] + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +Licenses are intended to guarantee your freedom to share and change +free software--to make sure the software is free for all its users. + + This license, the Lesser General Public License, applies to some +specially designated software packages--typically libraries--of the +Free Software Foundation and other authors who decide to use it. You +can use it too, but we suggest you first think carefully about whether +this license or the ordinary General Public License is the better +strategy to use in any particular case, based on the explanations below. + + When we speak of free software, we are referring to freedom of use, +not price. Our General Public Licenses are designed to make sure that +you have the freedom to distribute copies of free software (and charge +for this service if you wish); that you receive source code or can get +it if you want it; that you can change the software and use pieces of +it in new free programs; and that you are informed that you can do +these things. + + To protect your rights, we need to make restrictions that forbid +distributors to deny you these rights or to ask you to surrender these +rights. These restrictions translate to certain responsibilities for +you if you distribute copies of the library or if you modify it. + + For example, if you distribute copies of the library, whether gratis +or for a fee, you must give the recipients all the rights that we gave +you. You must make sure that they, too, receive or can get the source +code. If you link other code with the library, you must provide +complete object files to the recipients, so that they can relink them +with the library after making changes to the library and recompiling +it. And you must show them these terms so they know their rights. + + We protect your rights with a two-step method: (1) we copyright the +library, and (2) we offer you this license, which gives you legal +permission to copy, distribute and/or modify the library. + + To protect each distributor, we want to make it very clear that +there is no warranty for the free library. Also, if the library is +modified by someone else and passed on, the recipients should know +that what they have is not the original version, so that the original +author's reputation will not be affected by problems that might be +introduced by others. + + Finally, software patents pose a constant threat to the existence of +any free program. We wish to make sure that a company cannot +effectively restrict the users of a free program by obtaining a +restrictive license from a patent holder. Therefore, we insist that +any patent license obtained for a version of the library must be +consistent with the full freedom of use specified in this license. + + Most GNU software, including some libraries, is covered by the +ordinary GNU General Public License. This license, the GNU Lesser +General Public License, applies to certain designated libraries, and +is quite different from the ordinary General Public License. We use +this license for certain libraries in order to permit linking those +libraries into non-free programs. + + When a program is linked with a library, whether statically or using +a shared library, the combination of the two is legally speaking a +combined work, a derivative of the original library. The ordinary +General Public License therefore permits such linking only if the +entire combination fits its criteria of freedom. The Lesser General +Public License permits more lax criteria for linking other code with +the library. + + We call this license the "Lesser" General Public License because it +does Less to protect the user's freedom than the ordinary General +Public License. It also provides other free software developers Less +of an advantage over competing non-free programs. These disadvantages +are the reason we use the ordinary General Public License for many +libraries. However, the Lesser license provides advantages in certain +special circumstances. + + For example, on rare occasions, there may be a special need to +encourage the widest possible use of a certain library, so that it becomes +a de-facto standard. To achieve this, non-free programs must be +allowed to use the library. A more frequent case is that a free +library does the same job as widely used non-free libraries. In this +case, there is little to gain by limiting the free library to free +software only, so we use the Lesser General Public License. + + In other cases, permission to use a particular library in non-free +programs enables a greater number of people to use a large body of +free software. For example, permission to use the GNU C Library in +non-free programs enables many more people to use the whole GNU +operating system, as well as its variant, the GNU/Linux operating +system. + + Although the Lesser General Public License is Less protective of the +users' freedom, it does ensure that the user of a program that is +linked with the Library has the freedom and the wherewithal to run +that program using a modified version of the Library. + + The precise terms and conditions for copying, distribution and +modification follow. Pay close attention to the difference between a +"work based on the library" and a "work that uses the library". The +former contains code derived from the library, whereas the latter must +be combined with the library in order to run. + + GNU LESSER GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License Agreement applies to any software library or other +program which contains a notice placed by the copyright holder or +other authorized party saying it may be distributed under the terms of +this Lesser General Public License (also called "this License"). +Each licensee is addressed as "you". + + A "library" means a collection of software functions and/or data +prepared so as to be conveniently linked with application programs +(which use some of those functions and data) to form executables. + + The "Library", below, refers to any such software library or work +which has been distributed under these terms. A "work based on the +Library" means either the Library or any derivative work under +copyright law: that is to say, a work containing the Library or a +portion of it, either verbatim or with modifications and/or translated +straightforwardly into another language. (Hereinafter, translation is +included without limitation in the term "modification".) + + "Source code" for a work means the preferred form of the work for +making modifications to it. For a library, complete source code means +all the source code for all modules it contains, plus any associated +interface definition files, plus the scripts used to control compilation +and installation of the library. + + Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running a program using the Library is not restricted, and output from +such a program is covered only if its contents constitute a work based +on the Library (independent of the use of the Library in a tool for +writing it). Whether that is true depends on what the Library does +and what the program that uses the Library does. + + 1. You may copy and distribute verbatim copies of the Library's +complete source code as you receive it, in any medium, provided that +you conspicuously and appropriately publish on each copy an +appropriate copyright notice and disclaimer of warranty; keep intact +all the notices that refer to this License and to the absence of any +warranty; and distribute a copy of this License along with the +Library. + + You may charge a fee for the physical act of transferring a copy, +and you may at your option offer warranty protection in exchange for a +fee. + + 2. You may modify your copy or copies of the Library or any portion +of it, thus forming a work based on the Library, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) The modified work must itself be a software library. + + b) You must cause the files modified to carry prominent notices + stating that you changed the files and the date of any change. + + c) You must cause the whole of the work to be licensed at no + charge to all third parties under the terms of this License. + + d) If a facility in the modified Library refers to a function or a + table of data to be supplied by an application program that uses + the facility, other than as an argument passed when the facility + is invoked, then you must make a good faith effort to ensure that, + in the event an application does not supply such function or + table, the facility still operates, and performs whatever part of + its purpose remains meaningful. + + (For example, a function in a library to compute square roots has + a purpose that is entirely well-defined independent of the + application. Therefore, Subsection 2d requires that any + application-supplied function or table used by this function must + be optional: if the application does not supply it, the square + root function must still compute square roots.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Library, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Library, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote +it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Library. + +In addition, mere aggregation of another work not based on the Library +with the Library (or with a work based on the Library) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may opt to apply the terms of the ordinary GNU General Public +License instead of this License to a given copy of the Library. To do +this, you must alter all the notices that refer to this License, so +that they refer to the ordinary GNU General Public License, version 2, +instead of to this License. (If a newer version than version 2 of the +ordinary GNU General Public License has appeared, then you can specify +that version instead if you wish.) Do not make any other change in +these notices. + + Once this change is made in a given copy, it is irreversible for +that copy, so the ordinary GNU General Public License applies to all +subsequent copies and derivative works made from that copy. + + This option is useful when you wish to copy part of the code of +the Library into a program that is not a library. + + 4. You may copy and distribute the Library (or a portion or +derivative of it, under Section 2) in object code or executable form +under the terms of Sections 1 and 2 above provided that you accompany +it with the complete corresponding machine-readable source code, which +must be distributed under the terms of Sections 1 and 2 above on a +medium customarily used for software interchange. + + If distribution of object code is made by offering access to copy +from a designated place, then offering equivalent access to copy the +source code from the same place satisfies the requirement to +distribute the source code, even though third parties are not +compelled to copy the source along with the object code. + + 5. A program that contains no derivative of any portion of the +Library, but is designed to work with the Library by being compiled or +linked with it, is called a "work that uses the Library". Such a +work, in isolation, is not a derivative work of the Library, and +therefore falls outside the scope of this License. + + However, linking a "work that uses the Library" with the Library +creates an executable that is a derivative of the Library (because it +contains portions of the Library), rather than a "work that uses the +library". The executable is therefore covered by this License. +Section 6 states terms for distribution of such executables. + + When a "work that uses the Library" uses material from a header file +that is part of the Library, the object code for the work may be a +derivative work of the Library even though the source code is not. +Whether this is true is especially significant if the work can be +linked without the Library, or if the work is itself a library. The +threshold for this to be true is not precisely defined by law. + + If such an object file uses only numerical parameters, data +structure layouts and accessors, and small macros and small inline +functions (ten lines or less in length), then the use of the object +file is unrestricted, regardless of whether it is legally a derivative +work. (Executables containing this object code plus portions of the +Library will still fall under Section 6.) + + Otherwise, if the work is a derivative of the Library, you may +distribute the object code for the work under the terms of Section 6. +Any executables containing that work also fall under Section 6, +whether or not they are linked directly with the Library itself. + + 6. As an exception to the Sections above, you may also combine or +link a "work that uses the Library" with the Library to produce a +work containing portions of the Library, and distribute that work +under terms of your choice, provided that the terms permit +modification of the work for the customer's own use and reverse +engineering for debugging such modifications. + + You must give prominent notice with each copy of the work that the +Library is used in it and that the Library and its use are covered by +this License. You must supply a copy of this License. If the work +during execution displays copyright notices, you must include the +copyright notice for the Library among them, as well as a reference +directing the user to the copy of this License. Also, you must do one +of these things: + + a) Accompany the work with the complete corresponding + machine-readable source code for the Library including whatever + changes were used in the work (which must be distributed under + Sections 1 and 2 above); and, if the work is an executable linked + with the Library, with the complete machine-readable "work that + uses the Library", as object code and/or source code, so that the + user can modify the Library and then relink to produce a modified + executable containing the modified Library. (It is understood + that the user who changes the contents of definitions files in the + Library will not necessarily be able to recompile the application + to use the modified definitions.) + + b) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (1) uses at run time a + copy of the library already present on the user's computer system, + rather than copying library functions into the executable, and (2) + will operate properly with a modified version of the library, if + the user installs one, as long as the modified version is + interface-compatible with the version that the work was made with. + + c) Accompany the work with a written offer, valid for at + least three years, to give the same user the materials + specified in Subsection 6a, above, for a charge no more + than the cost of performing this distribution. + + d) If distribution of the work is made by offering access to copy + from a designated place, offer equivalent access to copy the above + specified materials from the same place. + + e) Verify that the user has already received a copy of these + materials or that you have already sent this user a copy. + + For an executable, the required form of the "work that uses the +Library" must include any data and utility programs needed for +reproducing the executable from it. However, as a special exception, +the materials to be distributed need not include anything that is +normally distributed (in either source or binary form) with the major +components (compiler, kernel, and so on) of the operating system on +which the executable runs, unless that component itself accompanies +the executable. + + It may happen that this requirement contradicts the license +restrictions of other proprietary libraries that do not normally +accompany the operating system. Such a contradiction means you cannot +use both them and the Library together in an executable that you +distribute. + + 7. You may place library facilities that are a work based on the +Library side-by-side in a single library together with other library +facilities not covered by this License, and distribute such a combined +library, provided that the separate distribution of the work based on +the Library and of the other library facilities is otherwise +permitted, and provided that you do these two things: + + a) Accompany the combined library with a copy of the same work + based on the Library, uncombined with any other library + facilities. This must be distributed under the terms of the + Sections above. + + b) Give prominent notice with the combined library of the fact + that part of it is a work based on the Library, and explaining + where to find the accompanying uncombined form of the same work. + + 8. You may not copy, modify, sublicense, link with, or distribute +the Library except as expressly provided under this License. Any +attempt otherwise to copy, modify, sublicense, link with, or +distribute the Library is void, and will automatically terminate your +rights under this License. However, parties who have received copies, +or rights, from you under this License will not have their licenses +terminated so long as such parties remain in full compliance. + + 9. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Library or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Library (or any work based on the +Library), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Library or works based on it. + + 10. Each time you redistribute the Library (or any work based on the +Library), the recipient automatically receives a license from the +original licensor to copy, distribute, link with or modify the Library +subject to these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties with +this License. + + 11. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Library at all. For example, if a patent +license would not permit royalty-free redistribution of the Library by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Library. + +If any portion of this section is held invalid or unenforceable under any +particular circumstance, the balance of the section is intended to apply, +and the section as a whole is intended to apply in other circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 12. If the distribution and/or use of the Library is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Library under this License may add +an explicit geographical distribution limitation excluding those countries, +so that distribution is permitted only in or among countries not thus +excluded. In such case, this License incorporates the limitation as if +written in the body of this License. + + 13. The Free Software Foundation may publish revised and/or new +versions of the Lesser General Public License from time to time. +Such new versions will be similar in spirit to the present version, +but may differ in detail to address new problems or concerns. + +Each version is given a distinguishing version number. If the Library +specifies a version number of this License which applies to it and +"any later version", you have the option of following the terms and +conditions either of that version or of any later version published by +the Free Software Foundation. If the Library does not specify a +license version number, you may choose any version ever published by +the Free Software Foundation. + + 14. If you wish to incorporate parts of the Library into other free +programs whose distribution conditions are incompatible with these, +write to the author to ask for permission. For software which is +copyrighted by the Free Software Foundation, write to the Free +Software Foundation; we sometimes make exceptions for this. Our +decision will be guided by the two goals of preserving the free status +of all derivatives of our free software and of promoting the sharing +and reuse of software generally. + + NO WARRANTY + + 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO +WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. +EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR +OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY +KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE +LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME +THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN +WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY +AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU +FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR +CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE +LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING +RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A +FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF +SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Libraries + + If you develop a new library, and you want it to be of the greatest +possible use to the public, we recommend making it free software that +everyone can redistribute and change. You can do so by permitting +redistribution under these terms (or, alternatively, under the terms of the +ordinary General Public License). + + To apply these terms, attach the following notices to the library. It is +safest to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least the +"copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Also add information on how to contact you by electronic and paper mail. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the library, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the + library `Frob' (a library for tweaking knobs) written by James Random Hacker. + + , 1 April 1990 + Ty Coon, President of Vice + +That's all there is to it! + + diff --git a/ReadMe.txt b/ReadMe.txt new file mode 100644 index 0000000..1d639f8 --- /dev/null +++ b/ReadMe.txt @@ -0,0 +1,36 @@ +# $RCSfile: ReadMe.txt,v $ +# $Revision: 1.1 $ +# $Name: $ +# $Date: 2006/02/28 23:28:21 $ +# $Author: agibert $ + + + + + +Welcome to LibDataBase 1.0.x ! + + + +This release of LibDataBase supports the following OS: + - Solaris 2.6. + + + +This is a snapshot release in order to remember all the work already done ! +This curent version is the one used on the BDM Project. + + + +LibDataBase is licensed under the LGPL/GPL GNU Licenses. +For more information, please read the corresponding source file headers. +The license details can be found in the GNU-GPL.txt, GNU-LGPL.txt and GNU-FDL.txt files. + + + +Enjoy it! + +Your LibDataBase Team. + +arnaud@rx3.net +http://www.rx3.org/dvp/libdatabase diff --git a/ReleaseNotes.txt b/ReleaseNotes.txt new file mode 100644 index 0000000..3e3a583 --- /dev/null +++ b/ReleaseNotes.txt @@ -0,0 +1,47 @@ +# $RCSfile: ReleaseNotes.txt,v $ +# $Revision: 1.1 $ +# $Name: $ +# $Date: 2006/02/28 23:28:21 $ +# $Author: agibert $ + + + + + +------------------------------------------------------------------------------------------------------------------------------------ +LibNode V 1.0.4 - A. Gibert - 28/02/06 +------------------------------------------------------------------------------------------------------------------------------------ + +No code change, just a CVS commit ! + + + +------------------------------------------------------------------------------------------------------------------------------------ +LibDataBase V 1.0.3 - N. Fatout - 11/06/03 +------------------------------------------------------------------------------------------------------------------------------------ + +No log... + + + +------------------------------------------------------------------------------------------------------------------------------------ +LibDataBase V 1.0.2 - O. Des Mares - 26/09/00 +------------------------------------------------------------------------------------------------------------------------------------ + +No log... + + + +------------------------------------------------------------------------------------------------------------------------------------ +LibDataBase V 1.0.1 - F. Xhumari - 18/09/00 +------------------------------------------------------------------------------------------------------------------------------------ + +No log... + + + +------------------------------------------------------------------------------------------------------------------------------------ +LibDataBase V 1.0.0 - A. Gibert / S. Mas - 01/07/00 +------------------------------------------------------------------------------------------------------------------------------------ + +Inital version for BDM project (Société Générale - Paris) diff --git a/ToDo.txt b/ToDo.txt new file mode 100644 index 0000000..09c4be8 --- /dev/null +++ b/ToDo.txt @@ -0,0 +1,15 @@ +# $RCSfile: ToDo.txt,v $ +# $Revision: 1.1 $ +# $Name: $ +# $Date: 2006/02/28 23:28:21 $ +# $Author: agibert $ + + + + + +- Add proper Makefiles, +- Add Linux support, +- Major code clean up ! +- New English documentation (man/tex), +- Improve API consitency. diff --git a/doc/libdatabase.doc b/doc/libdatabase.doc new file mode 100644 index 0000000000000000000000000000000000000000..0c653698e32cb894f4d89bb28db557d7a95533db GIT binary patch literal 35840 zcmeI5e{3DqmB;UM?8Jd2kPv>9@?!`;VjJT);a4zA8YgzJX%eTl1Ks6^JAQ9$4?Mqd zXWp|h3&<2!TiOZ*LD?TgDoD%H3aD6GsVhVaU9HOgQ5vW~i2k6d1fkuf6`&$Wwc!1n zJ9FPJ+t1G?AXsLc@4GX1?mhS1bI(2Zocm^8p54Ft!2SPr;_p=1u|+LW?@upRON;Uo zoVT0nqm|mux#Yb+Jv}YiTLGu>@d=W^>ks@yU1Tk)+ZN4q$Djqmz%R) zuQk<4FN^AaZ)KQSoNgxTAo(ju-y%J)sQmZo{}$?QS{2q?bPAmsNSqhSv#RtA%D=f< zDT|7$>C8P`f06pfhOCr)n*JO9N^Wvt^5;s0t{iKkK{519YU+ih3iL*)cU)0DQ{SXg zZ!7o9>6Bk@irP2yO?`7+ZEE;5^n{MZ_?6Q$_YEH=t+t)=a)zF1|1A0~`gGs@Z$JFq zSN4wL_2q|{RXKJv}Axo`Su^xdSUe{-cZ>LsXk zwD-4fYwzo98Cl7(p~>nQb25RIb_adipS0{u%5pPq*0s~_4NhS7Z11+5%(&}&nNcT` zZCTl|t$&~|YiDzT)v;}0XIO1Oh%~sFtd(*GbHh8*_HfX6aY%oA+6y35+(0=|tLkH= zwS0C4bSn+xo|`i5Ug~6N)ef?j!hr~Nh>?z7|vQMF|jh~ zWuTNCv3;wFes>DVfn6cV0h+Q(+TQMEGES2AvmO$)dVD*XcC3`0wFm9Mso2s?E*PVR z?hQSS7CZ=5*UPk7?WvSc>y|ep4dgO~F-tKn{R0sPl%3IG3i53hS?9-FOR6->bgwkmu&h;3=2nLrL_`B?$oEF8;I<%#@-yi5 z)9+-?_nC=S*0(c(t<|B~azza$Ndq_^9d)y!-}4-ioD02f)AY-vf-0m$jiX`}#&hKi zK^MATLDqB4*Gz77(DAiFGE>(MEZ@oI{7g7`Bb}HSahY7E8<}BYQH0;nT{>kJ-7%4) zCdeGbmTdP@4moX>HUc!9TIh@xg2G@(uP^IMhM^aAwt}Fg^o#=rXIFDfz(C&@c7_%U zOI2Ygnyr+c!A(&w(Qa+<bb%aVCoOaG^ZwP9TWxU3+?Z``dT-qk$8i z_2r!7yDS-gE@K7mXfB<#Gme)F(vwz$T)Ej1-?3AT)@Y77ih^2MYMBFiDR*ed(UYWf z%$Xl8jMb!<3#%sWbXr!i?V(|XjGJ_tEidC(L#!B%ogC2vRW#KW)kVXa>F?py%o)?J zzhD_;srD-kd45c{YqPGjg-k}g_w7^P!%nSWPs*iyu@{^Fw}-%fRnCS zZnOI26pwCjGK=kuoTQLCO|@8^*SEoL$3XY){?1D~d)qLrH#pvqc-8B8s+Szo$;wzY9CCJl#rAcP=3p+{Q`BV#w~a9ItEpY8khq%@@~ z290_8hM=2Cxk;P3CEe*C=r)%!`1#5uck(1kJ17M8C?wH9bWHmDw~=(3!;Uxa*xA$G z-`vr&ciYa+WN<@IuCeRL;c zR0v9;uzkzPCR?oCUe;;T)x$9eWXhDash905uZEa}a~UsdIxYlleYfe#s~b)32S|nB z4g{~cL_F4z>!efgBqlHHxL%|YFV@Rr+?W*Ou1$r34ldedvwY)y*LUOUj6C#x2EV8K-ke5BEHoP2-G<@VB&<7M9fjza|t!fkU)H zw~C#U8ImMQ#97fS2{X7mX)EnyhO;9jGg~uRm?9C2GaQ1*LJjocJdbJfY;0CjbV6ei zQeY^;GqDXQ7U8tjq#J2w#EK_dQ+{0X9)t|r5Nm)pAyOTplM<@pCbG(zC}PykxMMl7 z=0!m<<|^#Is~ut83z2fh&bs5;6&tm)73Q58nTn|pY)@xLyxi~zq9k-?_{WH!jGVop ztdp@uWlhHE9FrADM?Ha?Vnmp`A)6R$y*%mJ&d5izP!Bd0QqGXeN*~#B-7zAQz`>`@ zBr7jS!l4*xlq>0_QAF{urQK$0U0>(U&h7nSz78bW#M#;TMeB;L&fZR|rKM$^n7^_^ z2%4JxJpa zz1AD#8lALFhu5Rt(ZVJsA+(}l8NF0(YAqQ@2$s2ZWkx|OtK<#rAxdh}7Nww}qI#m1 zcuCQIRH6C~-*HN7izv0dnOTkC2Av(~_q0)(qgvRmo4VeFMbX3vV32L8M*kajlpKX6ihRmsg?-{l%Uy+sHtrXdW z7As%eYRdDZEfzf&6%o@NcsW1GS($rjjrq>F8^)c*+iQ6`C8``rGJjJ#u5D(XgOcL& z4o`)ShkKny@wF7odnW^1z5%+x4Hb3*t`kG3Mz0ZE{g9>;9audiALtVm}b7CNQtuQ z)oAzLoja|j4Krm7!DE4%;zcExb5naqK@wsvZrK3V(%|4^815vB`#tf;=V#?<4K%X{= z6^6J1tG!X&i0(Vr=Pjyb6N|8$p?AV3_0$-22u_?(VyV!~%@8?bH(OU57CVG9ztAa& zaR-|bBMa{{EN-`%-R#0jjO8YYarr_kK!r=aFa5>skTf#Om=t@iX#1e=l5KG|GDgoZ}I}&UKX^;U=f>*#naABQNUjl>RZC(Z)UZ&Kw;F@}+ z?gsaO3zsYPYp~@A-VX&Y9Ld{Py!mu2cpSV7{sOl02GbO{6+FUQZcl-O$0*g$8%|e% zeY{q7CwSs`rG5+^J3*RcDmC$0rEUN(fnR~flax9e+zkE*{sekY zR%$Q!{VAlpn|L|+8Q2eeOR3+01K`}#l=>?8I@qvIsT;w~;5o4Nbl!FYkAs)NZ-KlQ z`PT1WezD}=GsV|W%dHplInQvZFA5(;b=Avx-8?1+?J-q_RCt8)Gsc+OWyO8@m~Q}f>pri!YJp( z`tT~(#X4b^>BR_o;YRv#C3<0WN!tQRky-=kW6OfvIUp z)g7f)-}aw1Ujiz@>yfobsU>G5>@yPTBpH9B*YCYoEZ6w_|F;BcYgHmqBlGd4BK!S0 z?Dy8lj{gEXZfyB6*zdJKZ2A!RAuzW65a(jwKhK-g_kv5X@5a{O!ueMsoBurNnW$fh znw4Ci+HrDLBfLXiuvUXn{t>NDxJp?Y}mGy6d*TE&M>32kH`+m|ANq#afKE(0=zyc}Z zZNBlB@pu+2JzlA0zy^are6Sw@@xxZ(hYbMZk1fLoEB47=jr_9LNR3bS%Obz5316(( zH!JDkJH;G+;5#J*s=Sz+gSiPTrcMd9DhX6sY;MxU(w%Mo7yHV6C*zBQ*?i__@R@&J z<~zS^;SYmiANqED=&wb-bTj_5@uzPp@~P+Mw&YHg7juhf?mHit^hZUYq@Bg|XTI?_ zG0w5XG!o|wgYsDCP%)7bCaSzBA@FuFwURrHBW4I|H2g=was|CitoXY0w$;o-@Z?-1XTcj)CuAe&BQ$lJEQZFoB1IH^=&tU1+a!4mt(+Ma4Z-C zKLn41cfld>7w~yHaxb_fivFfZzXEOr&x14R*f@9^oInR%Akp8Ebo46l2zVd#(CPcY zn_wHJ<}Pp$^b=9+1y_LYfJ5LiqKa>U*TE%36?cF;!G7>8SW1Mk4A@{0JOO?LehgL- zVGMxBz)~WNWuP8B1YQBJf`i~SaKrJ)3H%cL3N+%$Hi5Ij&ESvVPoNj?wGZ@zz2Nuk zGVaBTy&U`uJOh3X_5&Y}_BY^V@LO;IoO?36h~RecHSl%N%+BKma3i=0+zg%rYtfx! z!Es<1JPv*b{t=xxs+A8prUY@0h=OBE5KBWu!7(MMMjHQ2!C0dfBC(lLjb(`Z0z`PN5v z{$=-9b^v7;NWRs^WmUML$^xeWvK867j(qct>#7gqCmX-m_`=5beIfE^m#A8z%3=_d za1b8oSV!U<6W^Fv#>6h=@rsE}B+l3!#Taa5=y>8?;t3N!i0>^Bf4Yv?Y$2%Cv0N?O zEm7N4huWo%=d(>+rTTOfImFpc;>1C6ZE|c%*(xAPY$0;=h;B{2G{255^{ya#?Nhz# za?bY&2rB5J8~ z>9P9~Q%At@^4glZ`X#ln&#|oD$SK@dQ4DGyJj&2!7~BzBRO+1RbEhq}YUt!)!u<1f z+sl?Luc@i4shzX!?bOWa_8mS=?`2BYs*UwuJwd&}!vN~LnvJoGgMYmR2uDlxYwUThl6v_Zg;` z;*+0dwyGpip%_DKj!n0&mT~$mCb!ZtJV{~}^;|J>AmQ z5?mhmyKldBsAuHphwiLbXRrVMOX#Qi1~=HS(*|H4sVJCuh@w@`1MG%60K`bY4%m#; zk9dh?6`LmpdMzmqNcb!5q|IEj$*8(W*;G{hq+)iyL@J&_nv{iJWl6=*+(^nMpt_Az z+Lvb)#WUFmcyoI}zhKV(psoukwgs&op(B0R*0HOQKg+rFXSe*uQ(6V(b%du2FyWFf zeC~3Sz8CO=V%8P%gV-0fw5rrr^40T?{8`%7=jz4(dXQg@*XMWqQ3B(eJB@jy>mcT+JP$~YedEuEC?rr(((Rcj= z@qhE7?@9cB0s*PS=n|KX0Ex@TfW-SZ0*Uu;1F}c(4Zs68>TV!UM%@b}e*YIBaq+`| zFCf_b3gi7JNQL$xP#o7wyxVta828FHq+HAXfTXfXCh7kkv0S&o>73~)G%kEEYM)>Q zm4zt@>ZOzYZq|2n(?T*nVhO|&h$Rq9AeKNZfmi~u1Y!xq5{M-bOCXlO$65jsyh>Or zF|>T|EpfbrxAOhAd{-~u)5~}B62D7qE^)VfCogfo#PSm7%L5}4&+{^l{-5e4rkA+? z1RxKx@RhaVr5S!~Bz(e9LTH`}Qx-T4tOKWmGr;@P)6-{>t_KaE5j26bK{Gf9w15pj z%1SK137iYg1LuPaz=c5WUqsplE(U)EE&*G>=YZUQ4{VFh}>?`9N+;3a(D(md@sH`NB(7m3T}6^s%t~07Vx=-_Qi&Y&8oJ2A#Yj=TXh)wtbRu|e85vmRCgT5j^cd% zH+pZ<>L^!VYQFX>Q4-mG+H792ygu#c2}XYj3%tmo+;+?Q-Qgv3`akX~eTYr_1iSj= ec{WODV6LB=CQ^oz>F- literal 0 HcmV?d00001 diff --git a/include/database.h b/include/database.h new file mode 100644 index 0000000..f01911c --- /dev/null +++ b/include/database.h @@ -0,0 +1,359 @@ +/*---------------------------------------------------------------------------------*/ +/* $RCSfile: database.h,v $ */ +/*---------------------------------------------------------------------------------*/ +/* $Revision: 1.1 $ */ +/* $Name: $ */ +/* $Date: 2006/02/28 23:28:21 $ */ +/* $Author: agibert $ */ +/*---------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------*/ +/* This file is part of LibDataBase */ +/* */ +/* LibDataBase is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU Lesser General Public Licence as published by */ +/* the Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* LibDataBase is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with LibDataBase; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/*---------------------------------------------------------------------------------*/ + + + + + +#ifndef DATABASE_H +#define DATABASE_H + + +#include +#include +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + + +/* API return codes */ +typedef int DBT_Status; + +#define DB_ERROR(s) ((s) < 0) + +#define DBS_OK 1 /* OK */ +#define DBS_END_OF_DATA 2 /* No more data available */ +#define DBS_ERRAPI -1 /* Bad use of arguments */ +#define DBS_ERROCI -2 /* OCI problem */ +#define DBS_ERRMEM -3 /* Not enough memory */ + +#define ERROR_TO_STRING(e) \ +((e) == DBS_OK) ? "OK" : \ +((e) == DBS_END_OF_DATA) ? "END_OF_DATA" : \ +((e) == DBS_ERRAPI) ? "ERRAPI" : \ +((e) == DBS_ERROCI) ? "ERROCI" : \ +((e) == DBS_ERRMEM) ? "ERRMEM" : "Unknown Error" + + +/* Library opening mode */ +#define DBD_ERRMSG 1 +#define DBD_DEBUG 2 + + +/* DB type */ +#define DBD_ORACLE 1 + + +/* data types for host variables */ +#define DBD_STRING 1 +#define DBD_INTEGER 2 +#define DBD_FLOAT 3 +#define DBD_DOUBLE 4 +#define DBD_DATE 5 +#define DBD_ROWID 6 + + +/* Types */ +typedef sb2 DBT_Indicator; + +typedef void *DBT_Date_Ptr; /* Date is an abstract type, allocated only from the library */ + +typedef struct { + int rowsProcessed; /* rows fetched/inserted/updated, always valid on SELECT statements, */ + /* otherwise -1 if it couldn't be determined */ + int errorIteration; /* iteration which caused the error; -1 if it couldn't be determined */ +} DBT_Result; + +typedef struct { + OCIEnv * envhp; /* Handle d'environnement */ + OCIError * errhp; /* Handle d'erreur */ + OCIServer * srvhp; /* Handle de serveur */ + OCISvcCtx * svchp; /* Handle de context */ + OCISession * authp; /* Handle de session ouverte */ + OCITrans * transp; /* Handle de transaction */ + int handlesAreValid; /* true if all handles are valid */ + char error[512]; /* erreur OCI */ + dword errorCode; /* code erreur OCI */ +} DBT_Connection; + +typedef struct { + DBT_Connection *connection; + OCIStmt *handle; /* Handle de requête */ + OCIError *errhp; /* Handle d'erreur */ + char error[512]; /* erreur OCI */ + dword errorCode; /* code erreur OCI */ + + int isPrepared; + int isExecuted; + int isSelect; + int varsDefined; + int varsBound; + int rowsToFetch; + int rowsBound; + int rowsFetchedSoFar; /* total rows fetched so far for a query */ + int isEOF; /* true if EOF reached fetching data (SELECT statements) */ +} DBT_Statement; + +typedef struct { + int type; /* type de la valeur */ + int size; /* taille du buffer pour une valeur */ + void *value; /* pointeur sur la valeur ou le tableau de valeurs */ + DBT_Indicator *indicator; /* pointeur sur l'indicateur ou le tableau d'indicateurs */ +} DBT_HostVar; + + + +/*------------------------------------------------------------------------------*/ +/* Opens library and initializes OCI environment. */ +/*------------------------------------------------------------------------------*/ +/* (I) debugFlags: 0, DBD_ERRMSG, DBD_DEBUG or a binary OR-ed combination. */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Library_Open(int debugFlags); + +/*------------------------------------------------------------------------------*/ +/* Closes library and OCI environment. */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Library_Close(void); + +/*------------------------------------------------------------------------------*/ +/* Gets last error message generated by the library. */ +/*------------------------------------------------------------------------------*/ +const char *DB_Error_Message_Get (void); + +/*------------------------------------------------------------------------------*/ +/* Connects to an Oracle database. */ +/*------------------------------------------------------------------------------*/ +/* (I/O) connection: Address of an uninitialized DBT_Connection. */ +/* (I) Login : Login name of user. */ +/* (I) Password : Password. */ +/* (I) Database : Oracle SID of the target database. */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Connect(DBT_Connection *connection, const char *Login, const char *Password, const char *Database); + +/*------------------------------------------------------------------------------*/ +/* Disconnects from database. */ +/* The current transaction, if any, is committed */ +/*------------------------------------------------------------------------------*/ +/* (I) connection: The DBT_Connection used to connect. */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Disconnect(DBT_Connection *connection); + +/*------------------------------------------------------------------------------*/ +/* Gets last error number and message as returned by Oracle while connecting. */ +/*------------------------------------------------------------------------------*/ +/* (I) connection: DBT_Connection used to connect. */ +/* (O) errCode : Error code. */ +/* (O) errStr : Error message. */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Connection_SQLError_Get(DBT_Connection *connection, dword *errCode, char **errStr); + +/*------------------------------------------------------------------------------*/ +/* Starts a new transaction. */ +/* IMPORTANT: Two queries run simultaneously (multithread) must use two */ +/* different DBT_Connection, i.e. you must call DB_Connect twice, one for each */ +/* transaction. */ +/*------------------------------------------------------------------------------*/ +/* (I) connection: DBT_Connection used to connect. */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Transaction_Start(DBT_Connection *connection); + +/*------------------------------------------------------------------------------*/ +/* Commits transaction. */ +/*------------------------------------------------------------------------------*/ +/* (I) connection: DBT_Connection used to connect. */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Transaction_Commit(DBT_Connection *connection); + +/*------------------------------------------------------------------------------*/ +/* Rolls transaction back. */ +/* The state of the database restored is the one that existed before */ +/* DB_Transaction_Start() was called. */ +/*------------------------------------------------------------------------------*/ +/* (I) connection: DBT_Connection used to connect. */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Transaction_Rollback(DBT_Connection *connection); + +/*------------------------------------------------------------------------------*/ +/* Initializes an 'hostvar', variable that will be later associated to an */ +/* input or output value. */ +/*------------------------------------------------------------------------------*/ +/* (I/O) HostVar: Address of an existing DBT_HostVar that will be filled in. */ +/* (I) type : Type of data this hostvar refers to. */ +/* (I) size : Size in bytes of the data type. Ex: DBD_INTEGER: sizeof(int); */ +/* DBD_STRING: size of largest string + 1. */ +/* (I) value : Pointer to input or output value (or array of values). */ +/* (I) indicator: DBT_Indicator or array of DBT_Indicator. */ +/* */ +/* Type can be DBD_{INTEGER,STRING,FLOAT,DOUBLE,DATE}. */ +/* */ +/* Value points to an array of data (int[] for DBD_INTEGER, double[] for */ +/* DBD_DOUBLE etc. Note: for strings, value points to a char[][] and not */ +/* a char*[]) */ +/* For DBD_DATE fields, the array must be allocated via DB_DateArray_Alloc. */ +/* */ +/* The value of indicator, for outgoing data, must be -1 for a null value */ +/* and 0 otherwise. For incoming data, it is -1 if the value is null, 0 */ +/* if the value was retrieved correctly, and >0 if the value is truncated */ +/* (in the latter case, it is the real length of the data value). */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_HostVar_Setup(DBT_HostVar *HostVar, int type, int size, void *value, DBT_Indicator *indicator); + +/*------------------------------------------------------------------------------*/ +/* The following functions are used to manipulate Oracle dates in their */ +/* native format. */ +/* Although less compact, it is often more simple to consider dates in a table */ +/* as strings and to define hostvars in consequence. */ +/* Ex: if col1 is a date, "SELECT col1 from TABLEX WHERE ..." or */ +/* "SELECT TO_CHAR(col1, 'DD/MM/YYYY HH24:MI:SS') from TABLEX WHERE ..." */ +/* will do the job with a hostvar's type of DBD_STRING with size 20. */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_DateArray_Alloc(DBT_Date_Ptr *array, int size); + +DBT_Status DB_DateArray_Free(DBT_Date_Ptr dateArray); + +DBT_Status DB_String_To_Date(DBT_Date_Ptr dateArray, int idx, char *value, char *format); + +DBT_Status DB_Date_To_String(DBT_Date_Ptr dateArray, int idx, char *value, char *format); + + +/*------------------------------------------------------------------------------*/ +/* Initializes a statement. */ +/*------------------------------------------------------------------------------*/ +/* (I) connection: DBT_Connection used to connect. */ +/* (I) statement : An uninitialized DBT_Statement. */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_Init(DBT_Connection *connection, DBT_Statement *statement); + +/*------------------------------------------------------------------------------*/ +/* Frees resources associated to a previously initialized statement. */ +/*------------------------------------------------------------------------------*/ +/* (I) statement : A DBT_Statement. */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_Close(DBT_Statement *statement); + +/*------------------------------------------------------------------------------*/ +/* Gets last error number and message as returned by Oracle while working on */ +/* a statement. . . . . . . . . */ +/*------------------------------------------------------------------------------*/ +/* (I) statement : DBT_Statement. */ +/* (O) errCode : Error code. */ +/* (O) errStr : Error message. */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_SQLError_Get(DBT_Statement *statement, dword *errCode, char **errStr); + +/*------------------------------------------------------------------------------*/ +/* */ +/*------------------------------------------------------------------------------*/ +/* */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_Prepare(DBT_Statement *statement, const char *query); + +/*------------------------------------------------------------------------------*/ +/* Used to retrieve select-list results. */ +/*------------------------------------------------------------------------------*/ +/* */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_DefineVars(DBT_Statement *statement, int rows, ... /* HostVar *, ending with NULL */); + +/*------------------------------------------------------------------------------*/ +/* */ +/*------------------------------------------------------------------------------*/ +/* */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_DefineVar(DBT_Statement *statement, int rows, int column, DBT_HostVar *hv); + + +/*------------------------------------------------------------------------------*/ +/* */ +/*------------------------------------------------------------------------------*/ +/* Used for placeholders (like ":1" in "select * from TB where col = :1") */ +/* */ +/* Note: you cannot use the same placeholder more than once in a statement. */ +/* */ +/* Note: The bindings are done in the order of the placeholders in the */ +/* statement from left to right, and the name of the placeholder (like :1, :2) */ +/* has no influence. */ +/* */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_BindVars(DBT_Statement *statement, int rows, ... /* HostVar *, ending with NULL */); + +/*------------------------------------------------------------------------------*/ +/* */ +/*------------------------------------------------------------------------------*/ +/* */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_BindVar(DBT_Statement *statement, int rowsBound, int placeHolderIndex, DBT_HostVar *hostVar); + +/*------------------------------------------------------------------------------*/ +/* For SELECT statements, startingRow and endingRow must be 0 (array binds */ +/* cannot be used). */ +/*------------------------------------------------------------------------------*/ +/* */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_Execute(DBT_Statement *statement, int startingRow, int count, DBT_Result *result); + +/*------------------------------------------------------------------------------*/ +/* A shorthand for DB_Statement_Execute for SELECT statements. */ +/*------------------------------------------------------------------------------*/ +/* */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_ExecuteSelect(DBT_Statement *statement, DBT_Result *result); + +/*------------------------------------------------------------------------------*/ +/* Retrieves next results after a query has been executed with */ +/* DB_Statement_Execute(). */ +/*------------------------------------------------------------------------------*/ +/* */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_Fetch(DBT_Statement *statement, DBT_Result *result); + +/*------------------------------------------------------------------------------*/ +/* Cancels implicit cursor associated to last fetch. */ +/*------------------------------------------------------------------------------*/ +/* */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_Fetch_Terminate(DBT_Statement *statement); + +/*------------------------------------------------------------------------------*/ +/* Sets debug level for debug messages display. */ +/*------------------------------------------------------------------------------*/ +/* (I) level: 0 to disable display. */ +/*------------------------------------------------------------------------------*/ +void DB_Debug_Level_Set(int level); + + +#ifdef __cplusplus +} +#endif + + +#endif + diff --git a/lib/libdatabase.c b/lib/libdatabase.c new file mode 100644 index 0000000..02293cb --- /dev/null +++ b/lib/libdatabase.c @@ -0,0 +1,971 @@ +/*---------------------------------------------------------------------------------*/ +/* $RCSfile: libdatabase.c,v $ */ +/*---------------------------------------------------------------------------------*/ +/* $Revision: 1.1 $ */ +/* $Name: $ */ +/* $Date: 2006/02/28 23:28:21 $ */ +/* $Author: agibert $ */ +/*---------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------*/ +/* This file is part of LibDataBase */ +/* */ +/* LibDataBase is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU Lesser General Public Licence as published by */ +/* the Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* LibDataBase is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with LibDataBase; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/*---------------------------------------------------------------------------------*/ + + + + + +#include +#include +#include +#include +extern char *strdup (const char *); + +#include +#include "database.h" + +BDM_VERSION_EXPORT(libdatabase, "$Revision: 1.1 $", "$Name: $", __FILE__, "$Author: agibert $") + +/* fonctions locales */ +static DBT_Status DB__Disconnect(DBT_Connection *connection, int reportErrors); +static void DB__Error(OCIError *errhp, char *buffer, int length, dword *errorCode, sword status); +static void DB__Error_Connection(DBT_Connection *connection, sword status); +static void DB__Error_Statement(DBT_Statement *statement, sword status); +static DBT_Status DB__CheckFetch(DBT_Statement *statement, sword OCIrc, DBT_Result *result); + +static int initialized = 0; + + +/*---------------------------------------------------------------------------------*/ +/* Initializes library and OCI environment. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Library_Open(int flags) { + /* flags non utilisé */ + if (flags) BDM_Trace(1, "libdatabase", "DB_Library_Open", "Le paramètre flags (%d) est ignoré car il est obsolète", flags); + + if (!initialized) { + sword OCIrc = OCIInitialize(OCI_OBJECT | OCI_THREADED, NULL, NULL, NULL, NULL); + if (OCIrc != OCI_SUCCESS) { + BDM_Trace(0, "libdatabase", "DB_Library_Open", "Echec d'initialisation du process OCI"); + return DBS_ERROCI; + } + initialized = 1; + } + + initialized++; + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Closes library. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Library_Close(void) { + initialized--; + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Connects to an Oracle database. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Connect(DBT_Connection *connection, const char *Login, const char *Password, const char *Database) { + sword OCIrc; + char *buf, *ptr; + + memset(connection, 0, sizeof(DBT_Connection)); + + ptr = buf = strdup(Password); + while (*ptr) *(ptr++) = '*'; + BDM_Trace(3, "libdatabase", "DB_Connect", "Connexion à la base %s/%s%s%s...\n", Login, buf, Database ? "@" : "", Database ? Database : ""); + free(buf); + + if (!initialized) { + BDM_Trace(0, "libdatabase", "DB_Connect", "La librairie n'a pas été initialisée"); + return DBS_ERRAPI; + } + + /* Initialisation de l'environnement OCI */ + OCIrc = OCIEnvInit(&connection->envhp, OCI_DEFAULT, 0, NULL); + if (OCIrc != OCI_SUCCESS) { + BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'initialisation du process OCI"); + DB__Disconnect(connection, 0); + return DBS_ERROCI; + } + + /* Allocation d'un handle de contexte */ + OCIrc = OCIHandleAlloc(connection->envhp, (void **)&connection->svchp, OCI_HTYPE_SVCCTX, 0, NULL); + if (OCIrc != OCI_SUCCESS) { + BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'allocation du handle de contexte"); + DB__Disconnect(connection, 0); + return DBS_ERROCI; + } + + /* Allocation d'un handle d'erreur */ + OCIrc = OCIHandleAlloc(connection->envhp, (void **)&connection->errhp, OCI_HTYPE_ERROR, 0, NULL); + if (OCIrc != OCI_SUCCESS) { + BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'allocation du handle d'erreur"); + DB__Disconnect(connection, 0); + return DBS_ERROCI; + } + + /* Allocation d'un handle de serveur */ + OCIrc = OCIHandleAlloc(connection->envhp, (void **)&connection->srvhp, OCI_HTYPE_SERVER, 0, NULL); + if (OCIrc != OCI_SUCCESS) { + BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'allocation du handle de serveur"); + DB__Disconnect(connection, 0); + return DBS_ERROCI; + } + + /* Allocation d'un handle de session */ + OCIrc = OCIHandleAlloc(connection->envhp, (void **)&connection->authp, OCI_HTYPE_SESSION, 0, NULL); + if (OCIrc != OCI_SUCCESS) { + BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'allocation du handle de session"); + DB__Disconnect(connection, 0); + return DBS_ERROCI; + } + + /* Allocation d'un handle de transaction */ + OCIrc = OCIHandleAlloc(connection->envhp, (void **)&connection->transp, OCI_HTYPE_TRANS, 0, NULL); + if (OCIrc != OCI_SUCCESS) { + BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'allocation du handle de transaction"); + DB__Disconnect(connection, 0); + return DBS_ERROCI; + } + + connection->handlesAreValid = 1; + + /* log in */ + OCIrc = OCIAttrSet(connection->authp, OCI_HTYPE_SESSION, (char *)(int)Login, strlen(Login), OCI_ATTR_USERNAME, connection->errhp); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Connection(connection, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de définition de l'attribut USERNAME : %s", connection->error); + DB__Disconnect(connection, 0); + return DBS_ERROCI; + } + + OCIrc = OCIAttrSet(connection->authp, OCI_HTYPE_SESSION, (char *)(int)Password, strlen(Password), OCI_ATTR_PASSWORD, connection->errhp); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Connection(connection, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de définition de l'attribut PASSWORD : %s", connection->error); + DB__Disconnect(connection, 0); + return DBS_ERROCI; + } + + /* Allocation et initialisation du handle de serveur */ + OCIrc = OCIServerAttach(connection->srvhp, connection->errhp, (text *)(int)Database, (signed)(Database ? strlen(Database) : 0), OCI_DEFAULT); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Connection(connection, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Connect", "Echec de l'attachement de la base %s%sau serveur : %s", Database ? Database : "", Database ? " " : "", connection->error); + DB__Disconnect(connection, 0); + return DBS_ERROCI; + } + + /* Ajoute le handle du serveur au handle de contexte */ + OCIrc = OCIAttrSet(connection->svchp, OCI_HTYPE_SVCCTX, connection->srvhp, 0, OCI_ATTR_SERVER, connection->errhp); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Connection(connection, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Connect", "Echec d'attachement du handle de serveur au handle de service : %s", connection->error); + DB__Disconnect(connection, 0); + return DBS_ERROCI; + } + + /* Ouverture d'une session */ + OCIrc = OCISessionBegin(connection->svchp, connection->errhp, connection->authp, OCI_CRED_RDBMS, OCI_DEFAULT); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Connection(connection, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Connect", "Echec du démarrage de la session : %s", connection->error); + DB__Disconnect(connection, 0); + return DBS_ERROCI; + } + + /* Référencement de la session ouverte dans le handle de contexte */ + OCIrc = OCIAttrSet(connection->svchp, OCI_HTYPE_SVCCTX, connection->authp, 0, OCI_ATTR_SESSION, connection->errhp); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Connection(connection, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Connect", "Echec du référencement de la session dans le handle de contexte : %s", connection->error); + DB__Disconnect(connection, 0); + return DBS_ERROCI; + } + + /* Référencement de la transaction */ + OCIrc = OCIAttrSet(connection->svchp, OCI_HTYPE_SVCCTX, connection->transp, 0, OCI_ATTR_TRANS, connection->errhp); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Connection(connection, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Connect", "Echec du référencement de la transaction"); + DB__Disconnect(connection, 0); + return DBS_ERROCI; + } + + BDM_Trace(2, "libdatabase", "DB_Connect", "Connecté à Oracle %s%s%s", Login, Database ? "@" : "", Database ? Database : ""); + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Disconnects from an Oracle database. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Disconnect(DBT_Connection *connection) { + return DB__Disconnect(connection, 1); +} + + +/*---------------------------------------------------------------------------------*/ +/* Starts a new transaction. */ +/* */ +/* User can then execute one or more statements before committing or rolling back. */ +/* If multiple transactions are necessary, each DB_Transaction_Start() must be */ +/* called on a different DBT_Connection, i.e. DB_Connect() should be called as */ +/* many times as there will be transactions. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Transaction_Start(DBT_Connection *conn) { + sword OCIrc; + + OCIrc = OCITransStart(conn->svchp, conn->errhp, 1, OCI_TRANS_NEW); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Connection(conn, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Transaction_Start", "Echec du démarrage de la transaction : %s", conn->error); + return DBS_ERROCI; + } + + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Commits a transaction. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Transaction_Commit(DBT_Connection *conn) { + sword OCIrc; + + OCIrc = OCITransCommit(conn->svchp, conn->errhp, OCI_DEFAULT); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Connection(conn, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Transaction_Commit", "Echec du commit de la transaction : %s", conn->error); + return DBS_ERROCI; + } + + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Rolls back a transaction. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Transaction_Rollback(DBT_Connection *conn) { + sword OCIrc; + + OCIrc = OCITransRollback(conn->svchp, conn->errhp, OCI_DEFAULT); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Connection(conn, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Transaction_Rollback", "Echec du rollback de la transaction : %s", conn->error); + return DBS_ERROCI; + } + + return DBS_OK; +} + + +/*------------------------------------------------------------------------------*/ +/* Initializes an 'hostvar', variable that will be later associated to an */ +/* input or output value. */ +/*------------------------------------------------------------------------------*/ +/* (I/O) HostVar: Address of an existing DBT_HostVar that will be filled in. */ +/* (I) type : Type of data this hostvar refers to. */ +/* (I) size : Size in bytes of the data type. Ex: DBD_INTEGER: sizeof(int); */ +/* DBD_STRING: size of largest string + 1. */ +/* (I) value : Pointer to input or output value (or array of values). */ +/* (I) indicator: DBT_Indicator or array of DBT_Indicator. */ +/* */ +/* Type can be DBD_{INTEGER,STRING,FLOAT,DOUBLE,DATE}. */ +/* */ +/* Value points to an array of data (int[] for DBD_INTEGER, double[] for */ +/* DBD_DOUBLE etc. Note: for strings, value points to a char[][] and not */ +/* a char*[]) */ +/* For DBD_DATE fields, the array must be allocated via DB_DateArray_Alloc. */ +/* */ +/* The value of indicator, for outgoing data, must be -1 for a null value */ +/* and 0 otherwise. For incoming data, it is -1 if the value is null, 0 */ +/* if the value was retrieved correctly, and >0 if the value is truncated */ +/* (in the latter case, it is the real length of the data value). */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_HostVar_Setup(DBT_HostVar *HostVar, int type, int size, void *value, DBT_Indicator *indicator) { + if (type != DBD_STRING && size) + BDM_Trace(1, "libdatabase", "DB_HostVar_Setup", "Le paramètre size n'est utilisé que pour le type DBD_STRING"); + switch (type) { + case DBD_STRING: + if (size <= 0) { + BDM_Trace(0, "libdatabase", "DB_HostVar_Setup", "Le paramètre size doit être > 0"); + return DBS_ERRAPI; + } + HostVar->size = size; + HostVar->type = SQLT_STR; + break; + case DBD_INTEGER: + HostVar->size = sizeof(int); + HostVar->type = SQLT_INT; + break; + case DBD_FLOAT: + HostVar->size = sizeof(float); + HostVar->type = SQLT_FLT; + break; + case DBD_DOUBLE: + HostVar->size = sizeof(double); + HostVar->type = SQLT_FLT; + break; + case DBD_DATE: + HostVar->size = sizeof(OCIDate); + HostVar->type = SQLT_ODT; + break; + case DBD_ROWID: + HostVar->size = 16;/*sizeof(OCIRowid);*/ + HostVar->type = SQLT_RDD; + break; + default: + BDM_Trace(0, "libdatabase", "DB_HostVar_Setup", "Paramètre type (%d) non reconnu ; les valeurs possibles sont DBD_STRING, DBD_INTEGER, DBD_FLOAT, DBD_DOUBLE, DBD_DATE"); + return DBS_ERRAPI; + } + + HostVar->value = value; + HostVar->indicator = indicator; + + return DBS_OK; +} + + +/*------------------------------------------------------------------------------*/ +/* The following functions are used to manipulate Oracle dates in their */ +/* native format. */ +/* Although less compact, it is often more simple to consider dates in a table */ +/* as strings and to define hostvars in consequence. */ +/* Ex: if col1 is a date, "SELECT col1 from TABLEX WHERE ..." or */ +/* "SELECT TO_CHAR(col1, 'DD/MM/YYYY HH24:MI:SS') from TABLEX WHERE ..." */ +/* will do the job with a hostvar's type of DBD_STRING with size 20. */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_DateArray_Alloc(DBT_Date_Ptr *array, int size) { + *array = (OCIDate *)malloc(size * sizeof(OCIDate)); + if (!array) { + BDM_Trace(0, "libdatabase", "DB_DateArray_Alloc", "Impossible d'allouer de la mémoire pour un tableau de %d dates", size); + return DBS_ERRMEM; + } + + return DBS_OK; +} + + +/*------------------------------------------------------------------------------*/ +/* Free memory allocated by DB_DateArray_Alloc */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_DateArray_Free(DBT_Date_Ptr array) { + free(array); + return DBS_OK; +} + + +/*------------------------------------------------------------------------------*/ +/* Convert a string into the native type Date using a given format */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_String_To_Date(DBT_Date_Ptr array, int idx, char *value, char *format) { + sword OCIrc; + + OCIDate *Date = ((OCIDate *)array) + idx; + + OCIrc = OCIDateFromText(NULL, (text *)value, strlen(value), (text *)format, strlen(format), NULL, 0, Date); + if (OCIrc != OCI_SUCCESS) { + BDM_Trace(0, "libdatabase", "DB_String_To_Date", "Erreur lors de la conversion de \"%s\" en date avec le format \"%s\"", value, format); + return DBS_ERRAPI; + } + + return DBS_OK; +} + + +/*------------------------------------------------------------------------------*/ +/* Convert a date into a string using a given format */ +/*------------------------------------------------------------------------------*/ +DBT_Status DB_Date_To_String(DBT_Date_Ptr array, int idx, char *Value, char *format) { + sword OCIrc; + unsigned long Value_Size; + + OCIDate *Date = ((OCIDate*)array) + idx; + Value_Size = strlen(format) + 1; + + OCIrc = OCIDateToText(NULL, Date, (text *)format, strlen(format), NULL, 0, &Value_Size, (text *)Value); + if (OCIrc != OCI_SUCCESS) { + BDM_Trace(0, "libdatabase", "DB_Date_To_String", "Erreur lors de la conversion d'une date avec le format \"%s\"", format); + return DBS_ERRAPI; + } + + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Initializes a statement. */ +/* */ +/* A statement is initialized only once, but can be prepared as many times as */ +/* wanted (cf. DB_Statement_Prepare()). */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_Init(DBT_Connection *connection, DBT_Statement *statement) { + sword OCIrc; + + memset(statement, 0, sizeof(DBT_Statement)); + statement->connection = connection; + + /* Allocation d'un handle de statement */ + OCIrc = OCIHandleAlloc(connection->envhp, (dvoid **)&statement->handle, OCI_HTYPE_STMT, 0, NULL); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Connection(connection, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Statement_Init", "Echec de l'allocation d'un handle de statement : %s", connection->error); + return DBS_ERROCI; + } + + /* Allocation d'un handle d'erreur */ + OCIrc = OCIHandleAlloc(connection->envhp, (dvoid **)&statement->errhp, OCI_HTYPE_ERROR, 0, NULL); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Connection(connection, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Statement_Init", "Echec de l'allocation d'un handle d'erreur : %s", connection->error); + DB_Statement_Close(statement); + return DBS_ERROCI; + } + + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Frees all resources used by a previously initialized statement. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_Close(DBT_Statement *statement) { + if (statement->errhp) + OCIHandleFree(statement->errhp, OCI_HTYPE_ERROR); + if (statement->handle) + OCIHandleFree(statement->handle, OCI_HTYPE_STMT); + + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Prepares a statement, i.e. associates SQL request and statement structure. */ +/* A statement is initialized only once, but can be prepared as many times as */ +/* wanted. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_Prepare(DBT_Statement *statement, const char *query) { + sword OCIrc; + ub2 statementType; + + OCIrc = OCIStmtPrepare(statement->handle, statement->errhp, (text *)(int)query, strlen(query), OCI_NTV_SYNTAX, OCI_DEFAULT); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Statement(statement, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Statement_Prepare", "Echec de la préparation du statement \"%s\" : %s", query, statement->error); + return DBS_ERROCI; + } + + /* It will be useful to know if the query is a SELECT: */ + OCIrc = OCIAttrGet(statement->handle, OCI_HTYPE_STMT, &statementType, 0, OCI_ATTR_STMT_TYPE, statement->errhp); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Statement(statement, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Statement_Prepare", "Erreur lors de la récupération du type pour le statement \"%s\" : %s", query, statement->error); + return DBS_ERROCI; + } + + statement->isSelect = (statementType == OCI_STMT_SELECT); + statement->isPrepared = 1; + + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Defines output variables associations. */ +/* Should be called to associate hostvar variables to output results (one hostvar */ +/* for one column). Not needed if SQL request doesn't produce any result. */ +/*---------------------------------------------------------------------------------*/ +/* (I) statement: An initialized statement. */ +/* (I) rows : Size of the array of values each HostVar uses (1 if not an array)*/ +/* (I) ... : One or more pointers to initialized HostVar, ending with NULL. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_DefineVars(DBT_Statement *statement, int rows, ...) { + va_list args; + DBT_HostVar *hostVar = NULL; + int column = 1; + DBT_Status rc = DBS_OK; + + va_start(args, rows); + + /* Associate all hostvars to each columns that will be potentially output */ + while (rc == DBS_OK && (hostVar = va_arg(args, DBT_HostVar *))) { + rc = DB_Statement_DefineVar(statement, rows, column, hostVar); + if (rc != DBS_OK) break; + ++column; + } + + va_end(args); + return rc; +} + + +/*---------------------------------------------------------------------------------*/ +/* Defines output variable association. */ +/* Called to associate one hostvar variable to one output result. See */ +/* DB_Statement_DefineVars(). */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_DefineVar(DBT_Statement *statement, int rows, int column, DBT_HostVar *hv) { + OCIDefine *def = NULL; + sword OCIrc; + + if (!statement->isPrepared) { + BDM_Trace(0, "libdatabase", "DB_Statement_DefineVar", "Le statement n'a pas été préparé"); + return DBS_ERRAPI; + } + + /* Associate hostvar to the current column: */ + OCIrc = OCIDefineByPos(statement->handle, &def, statement->errhp, (unsigned)column, hv->value, hv->size, hv->type, hv->indicator, NULL, NULL, OCI_DEFAULT); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Statement(statement, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Statement_DefineVar", "Echec de la définition de la variable n° %d : %s", column, statement->error); + return DBS_ERROCI; + } + + statement->varsDefined = 1; + statement->rowsToFetch = rows; + + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Binds input variables to placeholders in the SQL request. */ +/* NOTE: The statement must have been prepared using the SQL request */ +/* */ +/* Should be called to associate hostvar variables to input placeholders */ +/* e.g., :1 and :2 in "INSERT INTO TableX (col1, col2) VALUES (:1, :2)". */ +/* Placeholders can be named whatever you want since binding is done by position, */ +/* not by name. */ +/*---------------------------------------------------------------------------------*/ +/* (I) statement: An initialized statement. */ +/* (I) rowsBound: Size of the array of values each HostVar uses (1 if not an array)*/ +/* (I) ... : One or more pointers to initialized HostVar, ending with NULL. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_BindVars(DBT_Statement *statement, int rowsBound, ...) { + va_list args; + DBT_HostVar *hostVar; + int placeHolderIndex = 1; + DBT_Status rc = DBS_OK; + + va_start(args, rowsBound); + + /* Bind each hostvar to each placeholder, starting form 1: */ + while (rc == DBS_OK && (hostVar = va_arg(args, DBT_HostVar *))) { + rc = DB_Statement_BindVar(statement, rowsBound, placeHolderIndex, hostVar); + if (rc != DBS_OK) break; + ++placeHolderIndex; + } + + va_end(args); + return rc; +} + + +/*---------------------------------------------------------------------------------*/ +/* Binds one input variable to one placeholders in the SQL request. */ +/* Cf. DB_Statement_BindVars(). */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_BindVar(DBT_Statement *statement, int rowsBound, int placeHolderIndex, DBT_HostVar *hostVar) { + OCIBind *bind = NULL; + sword OCIrc; + + if (!statement->isPrepared) { + BDM_Trace(0, "libdatabase", "DB_Statement_BindVar", "Le statement n'a pas été préparé"); + return DBS_ERRAPI; + } + + OCIrc = OCIBindByPos(statement->handle, &bind, statement->errhp, (unsigned)placeHolderIndex, hostVar->value, hostVar->size, hostVar->type, hostVar->indicator,NULL, NULL, 0, NULL, OCI_DEFAULT); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Statement(statement, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Statement_BindVar", "Echec du binding de la variable n° %d : %s", placeHolderIndex, statement->error); + return DBS_ERROCI; + } + + statement->varsBound = 1; + statement->rowsBound = rowsBound; + + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Shorthand to execute a prepared statement using a SELECT query. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_ExecuteSelect(DBT_Statement *statement, DBT_Result *result) { + return DB_Statement_Execute(statement, 0, 1, result); +} + + +/*---------------------------------------------------------------------------------*/ +/* Executes a prepared statement. */ +/* */ +/* If statement is SELECT: */ +/* _ if DB_Statement_DefineVars() has already been called, as many rows as */ +/* specified by the size of defined hostvars will be directly fetched here. */ +/* Ex: "SELECT col1, col2 FROM table WHERE col3 == 12" */ +/* _ If DB_Statement_DefineVars() has not been called yet, user will need to */ +/* perform one or more DB_Statement_Fetch() to retrieve the results. */ +/* */ +/* If statement is not SELECT: */ +/* _ If no variables were bound, execute statement only once. */ +/* Ex: "INSERT INTO table VALUES (123, 'ABC')" */ +/* _ If some variables are bound, execute statement request 'count' times. */ +/* Ex: "INSERT INTO table VALUES (:1, :2)" */ +/*---------------------------------------------------------------------------------*/ +/* */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_Execute(DBT_Statement *statement, int startingRow, int count, DBT_Result *result) { + sword OCIrc; + sword OCIrc2; + unsigned int iters; + char err[512]; + int errLen = sizeof(err); + dword errCode; + DBT_Status rc; + + if (!statement->isPrepared) { + BDM_Trace(0, "libdatabase", "DB_Statement_Execute", "Le statement n'a pas été préparé"); + return DBS_ERRAPI; + } + + /* Set 'iters', number of times the request will be executed */ + if (statement->isSelect) { + iters = (statement->varsDefined) ? statement->rowsToFetch : 0; + if (statement->varsBound) { + if (startingRow != 0 || count != 1) { + BDM_Trace(0, "libdatabase", "DB_Statement_Execute", "Un statement SELECT avec des variables en sortie ne peut travailler avec des tableaux en entrée"); + return DBS_ERRAPI; + } + } + } else { + if (!statement->varsBound) { + iters = 1; + } else { + if (startingRow < 0 || startingRow >= statement->rowsBound) { + BDM_Trace(0, "libdatabase", "DB_Statement_Execute", "Le paramètre startingRow est invalide (0 à %d au lieu de %d)", statement->rowsBound, startingRow); + return DBS_ERRAPI; + } + if (count <= 0 || startingRow + count > statement->rowsBound) { + BDM_Trace(0, "libdatabase", "DB_Statement_Execute", "Le paramètre count est invalide (1 à %d au lieu de %d)", statement->rowsBound - startingRow, count); + return DBS_ERRAPI; + } + iters = startingRow + count; + } + } + + statement->rowsFetchedSoFar = 0; + statement->isEOF = 0; + statement->isExecuted = 0; + + BDM_Trace(3, "libdatabase", "DB_Statement_Execute", "Exécution du statement, iter = %d, à partir de %d", iters, startingRow); + + OCIrc = OCIStmtExecute(statement->connection->svchp, statement->handle, statement->errhp, iters, (unsigned)startingRow, NULL, NULL, OCI_DEFAULT); + if (statement->isSelect) { + result->errorIteration = 0; /* only one iteration for SELECTs */ + rc = DB__CheckFetch(statement, OCIrc, result); + if (!DB_ERROR(rc)) statement->isExecuted = 1; + return rc; + } + + /* This is not a SELECT statement */ + result->rowsProcessed = -1; + result->errorIteration = -1; + /* Get number of rows processed */ + OCIrc2 = OCIAttrGet(statement->handle, OCI_HTYPE_STMT, &result->rowsProcessed, NULL, OCI_ATTR_ROW_COUNT, statement->errhp); + if (OCIrc2 != OCI_SUCCESS) { + /* Don't report any errors, since the statement succeeded. + Leave rowsProcessed to -1 if impossible to get it. */ + DB__Error(statement->errhp, err, errLen, &errCode, OCIrc2); + BDM_Trace(0, "libdatabase", "DB_Statement_Execute", "Erreur lors de la récupération du nombre de lignes traitées : %s", err); + return DBS_ERROCI; + } + if (OCIrc == OCI_SUCCESS) return DBS_OK; + + /* An error happened */ + DB__Error_Statement(statement, OCIrc); + BDM_Trace(0, "libdatabase", "DB_Statement_Execute", "Erreur lors de l'exécution du statement : %s", statement->error); + if (iters == 1) result->errorIteration = 0; + return DBS_ERROCI; +} + + +/*---------------------------------------------------------------------------------*/ +/* Fetches next rows. */ +/* Called by user after a DB_Statement_Execute() using a SELECT query. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_Fetch(DBT_Statement *statement, DBT_Result *result) { + sword OCIrc; + + if (!statement->isPrepared) { + BDM_Trace(0, "libdatabase", "DB_Statement_Fetch", "Le statement n'a pas été préparé"); + return DBS_ERRAPI; + } + + if (!statement->isSelect) { + BDM_Trace(0, "libdatabase", "DB_Statement_Fetch", "Le statement n'est pas un SELECT"); + return DBS_ERRAPI; + } + + if (!statement->varsDefined) { + BDM_Trace(0, "libdatabase", "DB_Statement_Fetch", "Aucune variable n'est définie"); + return DBS_ERRAPI; + } + + if (!statement->isExecuted) { + BDM_Trace(0, "libdatabase", "DB_Statement_Fetch", "Le statement n'a pas encore été exécuté"); + return DBS_ERRAPI; + } + + if (statement->isEOF) /* the end of data was seen during last fetch */ + return DBS_END_OF_DATA; + + BDM_Trace(3, "libdatabase", "DB_Statement_Fetch", "Fetch..."); + + OCIrc = OCIStmtFetch(statement->handle, statement->errhp, (unsigned)statement->rowsToFetch, OCI_FETCH_NEXT, OCI_DEFAULT); + return DB__CheckFetch(statement, OCIrc, result); +} + + +/*---------------------------------------------------------------------------------*/ +/* Cancels implicit cursor associated to last fetch. */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_Fetch_Terminate(DBT_Statement *statement) { + sword OCIrc; + + if (! statement->isPrepared) { + BDM_Trace(0, "libdatabase", "DB_Statement_Fetch", "Le statement n'a pas été préparé"); + return DBS_ERRAPI; + } + + if (! statement->isSelect) { + BDM_Trace(0, "libdatabase", "DB_Statement_Fetch", "Le statement n'est pas un SELECT"); + return DBS_ERRAPI; + } + + OCIrc = OCIStmtFetch(statement->handle, statement->errhp, 0, OCI_FETCH_NEXT, OCI_DEFAULT); + if (OCIrc != OCI_SUCCESS) { + DB__Error_Statement(statement, OCIrc); + if (statement->errorCode == 1406) { + statement->errorCode = 0; + strcpy(statement->error, ""); + BDM_Trace(1, "libdatabase", "DB_Statement_Fetch_Terminate", "Donnée tronquée"); + return DBS_OK; + } + BDM_Trace(0, "libdatabase", "DB_Statement_FetchTerminate", "Erreur lors du fetch : %s", statement->error); + return DBS_ERROCI; + } + + return DBS_OK; +} + +static DBT_Status DB__Disconnect(DBT_Connection *connection, int reportErrors) { + sword OCIrc; + DBT_Status rc = DBS_OK; + char *err; + int errLen; + char localErr[512]; + dword *errCode; + dword localErrCode; + + if (connection->handlesAreValid) { + if (reportErrors) { + err = connection->error; + errLen = sizeof(connection->error); + errCode = &connection->errorCode; + } else { + err = localErr; + errLen = sizeof(localErr); + errCode = &localErrCode; + } + + /* Déconnexion de la base de données */ + OCIrc = OCISessionEnd(connection->svchp, connection->errhp, connection->authp, 0); + if (OCIrc != OCI_SUCCESS) { + DB__Error(connection->errhp, err, errLen, errCode, OCIrc); + BDM_Trace(0, "libdatabase", "DB__Disconnect", "Echec de la fermeture de la session : %s", err); + rc = DBS_ERROCI; + } + + /* Détachement du serveur */ + OCIrc = OCIServerDetach(connection->srvhp, connection->errhp, OCI_DEFAULT); + if (OCIrc != OCI_SUCCESS) { + DB__Error(connection->errhp, err, errLen, errCode, OCIrc); + BDM_Trace(0, "libdatabase", "DB__Disconnect", "Echec du détachement du serveur : %s", err); + rc = DBS_ERROCI; + } + + BDM_Trace(2, "libdatabase", "DB__Disconnect", "Déconnecté d'Oracle"); + } + + if (connection->srvhp) + OCIHandleFree(connection->srvhp, OCI_HTYPE_SERVER); + + if (connection->errhp) + OCIHandleFree(connection->errhp, OCI_HTYPE_ERROR); + + if (connection->authp) + OCIHandleFree(connection->authp, OCI_HTYPE_SESSION); + + if (connection->transp) + OCIHandleFree(connection->transp, OCI_HTYPE_TRANS); + + if (connection->svchp) + OCIHandleFree(connection->svchp, OCI_HTYPE_SVCCTX); + + memset(connection, 0, sizeof(DBT_Connection)); + + return rc; +} + + +static void DB__Error(OCIError *errhp, char *buffer, int length, dword *errorCode, sword status) { + unsigned int len = length; + *errorCode = 0; + + switch (status) { + case OCI_SUCCESS: + buffer[0] = '\0'; + break; + case OCI_SUCCESS_WITH_INFO: + snprintf(buffer, len, "ErrorOCI_SUCCESS_WITH_INFO"); + break; + case OCI_NEED_DATA: + snprintf(buffer, len, "ErrorOCI_NEED_DATA"); + break; + case OCI_NO_DATA: + snprintf(buffer, len, "ErrorOCI_NO_DATA"); + break; + case OCI_ERROR: + OCIErrorGet(errhp, 1, NULL, errorCode, (text*)buffer, len, OCI_HTYPE_ERROR); + break; + case OCI_INVALID_HANDLE: + snprintf(buffer, len, "ErrorOCI_INVALID_HANDLE"); + break; + case OCI_STILL_EXECUTING: + snprintf(buffer, len, "ErrorOCI_STILL_EXECUTE"); + break; + case OCI_CONTINUE: + snprintf(buffer, len, "ErrorOCI_CONTINUE"); + break; + default: + snprintf(buffer, len, "Unknown Error"); + break; + } +} + + +static void DB__Error_Connection(DBT_Connection *connection, sword status) { + DB__Error(connection->errhp, connection->error, sizeof(connection->error), &connection->errorCode, status); +} + + +static void DB__Error_Statement(DBT_Statement *statement, sword status) { + DB__Error(statement->errhp, statement->error, sizeof(statement->error), &statement->errorCode, status); +} + + +static DBT_Status DB__CheckFetch(DBT_Statement *statement, sword OCIrc, DBT_Result *result) { + sword OCIrc2; + int fetched = 0; + + result->rowsProcessed = 0; /* will set it later if possible */ + + if (OCIrc == OCI_ERROR) { + /* see whether the error is "Fetched column value is truncated" */ + /* do not consider it an error -- indicators indicate truncated data */ + DB__Error_Statement(statement, OCIrc); + if (statement->errorCode == 1406) { + OCIrc = OCI_SUCCESS; + BDM_Trace(1, "libdatabase", "DB__CheckFetch", "Donnée tronquée"); + } else { + BDM_Trace(0, "libdatabase", "DB__CheckFetch", "Erreur à l'exécution du statement : %s", statement->error); + return DBS_ERROCI; + } + } else if (OCIrc != OCI_SUCCESS && OCIrc != OCI_SUCCESS_WITH_INFO && OCIrc != OCI_NO_DATA) { + DB__Error_Statement(statement, OCIrc); + BDM_Trace(0, "libdatabase", "DB__CheckFetch", "Erreur à l'exécution du statement : %s", statement->error); + return DBS_ERROCI; + } + + /* OCI_SUCCESS_WITH_INFO may happen because of EOF reached or some + * data was truncated. I don't know how to distinguish these. */ + + /* get number of rows fetched -- this is mandatory */ + OCIrc2 = OCIAttrGet(statement->handle, OCI_HTYPE_STMT, &fetched, NULL, OCI_ATTR_ROW_COUNT, statement->errhp); + if (OCIrc2 != OCI_SUCCESS) { + DB__Error_Statement(statement, OCIrc2); + BDM_Trace(0, "libdatabase", "DB__CheckFetch", "Echec de la récupération du nombre de lignes du fetch : %sErreur à l'exécution du statement : %s", statement->error); + return DBS_ERROCI; + } + + result->rowsProcessed = fetched - statement->rowsFetchedSoFar; + statement->rowsFetchedSoFar = fetched; + + if (OCIrc == OCI_NO_DATA) { + statement->isEOF = 1; + return result->rowsProcessed ? DBS_OK : DBS_END_OF_DATA; + } + + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Fonction pour compatibilité avec les précédentes versions de libdatabase */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Connection_SQLError_Get(DBT_Connection *connection, dword *errCode, char **errStr) { + BDM_Trace(1, "libdatabase", "DB_Connection_SQLError_Get", "Cette fonction est obsolète ; cf BDT_Connection"); + *errCode = connection->errorCode; + *errStr = connection->error; + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Fonction pour compatibilité avec les précédentes versions de libdatabase */ +/*---------------------------------------------------------------------------------*/ +void DB_Debug_Level_Set(int level) { + BDM_Trace(1, "libdatabase", "DB_Debug_Level_Set", "Cette fonction est obsolète ; cf BDM_Trace_SetLevel"); + BDM_Trace_SetLevel(level, "libdatabase"); +} + + +/*---------------------------------------------------------------------------------*/ +/* Fonction pour compatibilité avec les précédentes versions de libdatabase */ +/*---------------------------------------------------------------------------------*/ +DBT_Status DB_Statement_SQLError_Get(DBT_Statement *st, dword *errCode, char **errStr) { + BDM_Trace(1, "libdatabase", "DB_Statement_SQLError_Get", "Cette fonction est obsolète ; cf BDT_Statement"); + *errCode = st->errorCode; + *errStr = st->error; + return DBS_OK; +} + + +/*---------------------------------------------------------------------------------*/ +/* Fonction pour compatibilité avec les précédentes versions de libdatabase */ +/*---------------------------------------------------------------------------------*/ +const char *DB_Error_Message_Get() { + BDM_Trace(1, "libdatabase", "DB_Error_Message_Get", "Cette fonction est obsolète ; cf BDM_Trace_LastError"); + return BDM_Trace_LastError(); +} diff --git a/utils/dbbench.c b/utils/dbbench.c new file mode 100644 index 0000000..70d4e64 --- /dev/null +++ b/utils/dbbench.c @@ -0,0 +1,709 @@ +/*---------------------------------------------------------------------------------*/ +/* $RCSfile: dbbench.c,v $ */ +/*---------------------------------------------------------------------------------*/ +/* $Revision: 1.1 $ */ +/* $Name: $ */ +/* $Date: 2006/02/28 23:28:21 $ */ +/* $Author: agibert $ */ +/*---------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------*/ +/* This file is part of LibDataBase */ +/* */ +/* LibDataBase is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU Lesser General Public Licence as published by */ +/* the Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* LibDataBase is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with LibDataBase; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/*---------------------------------------------------------------------------------*/ + + + + + +#include +#include +#include +#include + +#include "../lib/database.h" + + +/* Définition des propriétés de la tables sur laquelle les tests sont réalisés */ + +/* CREATE TABLE TOTO ( + CD_TOTO CHAR (3) NOT NULL PRIMARY KEY, + LIB_TOTO VARCHAR2 (50), + NUM_TOTO NUMBER (5) NOT NULL, + DAT_TOTO DATE); +*/ +#define CD_TOTO_LEN 3 +#define LIB_TOTO_LEN 50 + +/* Mesure des temps d'exécution */ + +typedef struct +{ + double sec; + struct timeval start; + struct timeval stop; +} cpt; + +#define t_start(x) {gettimeofday (&(x.start), NULL);} +#define t_stop(x) {gettimeofday (&(x.stop), NULL); x.sec=(double)(x.stop.tv_sec)-(double)(x.start.tv_sec)+((double)(x.stop.tv_usec)-(double)(x.start.tv_usec))/1000000;} + +#define NB_MAX_RECORD 2 +#define USAGE "Usage : %s insert|update|delete|select [start=] [exec=]\n" + + +/*--------------------------------------------------------------*/ +/* Fonction principale du bench */ +/*--------------------------------------------------------------*/ +int main ( int argc , char ** argv ) +{ + cpt t_exec; + DBT_Status rc; + DBT_Result Result; + DBT_Result ins_Result; + unsigned int i; + unsigned int Start_Idx = 0; + unsigned int Nb_Exec = NB_MAX_RECORD; + const char * Request; + const char * ins_Request; + DBT_Indicator Tab_Indic [NB_MAX_RECORD]; + DBT_Indicator Tab_ins_Indic [NB_MAX_RECORD]; + char Tab_CD_TOTO [NB_MAX_RECORD][CD_TOTO_LEN + 1]; + char Tab_LIB_TOTO [NB_MAX_RECORD][LIB_TOTO_LEN + 1]; + char Date_Value [11]; + int Tab_NUM_TOTO [NB_MAX_RECORD]; + int Tab_CT_PERSONNE_PHYSIQUE[NB_MAX_RECORD]; + int Tab_ins_CT_PERSONNE_PHYSIQUE[NB_MAX_RECORD]; + char Tab_NUM_PP[NB_MAX_RECORD][8]; + char Tab_ins_NUM_PP[NB_MAX_RECORD][8]; + DBT_Date * Tab_DAT_DER_MAJ_BDM; + DBT_Date * Tab_DAT_CRE_PP_BDM; + int Tab_CT_CG_RDP[NB_MAX_RECORD]; + int Tab_NUM_IDENT_CG_RDP[NB_MAX_RECORD]; + DBT_Date * Tab_DAT_CRE_CG_BDM_RDP; + char Tab_CD_BQUE_RDP[NB_MAX_RECORD][6]; + char Tab_CD_GUI_CLI_RDP[NB_MAX_RECORD][6]; + char Tab_CD_ACT_ECO[NB_MAX_RECORD][3]; + char Tab_CD_PAYS_NAIS[NB_MAX_RECORD][3]; + int Tab_CD_SOGETYPE[NB_MAX_RECORD]; + char Tab_CD_SIT_FAM[NB_MAX_RECORD][3]; + char Tab_CD_CMN_INSEE_NAIS[NB_MAX_RECORD][3]; + char Tab_CD_PAYS_RM[NB_MAX_RECORD][3]; + char Tab_CD_PAYS_RF[NB_MAX_RECORD][3]; + char Tab_CD_DEPT_NAIS[NB_MAX_RECORD][3]; + char Tab_CD_ST_PROF[NB_MAX_RECORD][3]; + char Tab_NOM_PAT[NB_MAX_RECORD][33]; + char Tab_NOM_MAR[NB_MAX_RECORD][33]; + char Tab_PNOM_OFF[NB_MAX_RECORD][33]; + char Tab_PNOM_SUPP[NB_MAX_RECORD][33]; + char Tab_RAISON_SOC[NB_MAX_RECORD][41]; + int Tab_CT_FOYER_MKT[NB_MAX_RECORD]; + char Tab_CD_CAT_PROF[NB_MAX_RECORD][3]; + int Tab_CT_ADRESSE[NB_MAX_RECORD]; + char Tab_CD_SEXE[NB_MAX_RECORD][3]; + int Tab_CD_ST_INT_CHQ[NB_MAX_RECORD]; + char Tab_CD_ST_DECEDE[NB_MAX_RECORD][3]; + int Tab_CD_ST_COM_PP[NB_MAX_RECORD]; + int Tab_CD_ETA_PP[NB_MAX_RECORD]; + int Tab_CD_ST_TECH[NB_MAX_RECORD]; + char Tab_CD_IND_PP_ANO[NB_MAX_RECORD][2]; + int Tab_CD_CAP_JUR[NB_MAX_RECORD]; + int Tab_CD_UNIC_PP[NB_MAX_RECORD]; + char Tab_ADR_EMAIL[NB_MAX_RECORD][81]; + DBT_Date * Tab_DAT_DER_MAJ_BLPP; + DBT_Date * Tab_DAT_DEB_REL_PP; + DBT_Date * Tab_DAT_NAIS; + DBT_Date * Tab_DAT_PUR_BLPP; + DBT_Date * Tab_DAT_FIN_ACT_COM; + int Tab_AGE[NB_MAX_RECORD]; + char Tab_NUM_FAX[NB_MAX_RECORD][16]; + char Tab_NUM_TEL_DOM[NB_MAX_RECORD][16]; + char Tab_NUM_PORT[NB_MAX_RECORD][16]; + int Tab_STP_MKT[NB_MAX_RECORD]; + int Tab_STP_TEL[NB_MAX_RECORD]; + int Tab_TP_FICP[NB_MAX_RECORD]; + int Tab_TP_BFM[NB_MAX_RECORD]; + int Tab_TP_HDG[NB_MAX_RECORD]; + int Tab_TP_CLI_SNS[NB_MAX_RECORD]; + int Tab_TP_NOR_DAT_NAIS[NB_MAX_RECORD]; + int Tab_TP_TEL_DOM[NB_MAX_RECORD]; + int Tab_TP_RLV_BRA[NB_MAX_RECORD]; + int Tab_CD_PRIO_FOY[NB_MAX_RECORD]; + char Tab_CD_SEG_MAR[NB_MAX_RECORD][6]; + + DBT_HostVar CT_PERSONNE_PHYSIQUE; + DBT_HostVar NUM_PP; + DBT_HostVar DAT_DER_MAJ_BDM; + DBT_HostVar DAT_CRE_PP_BDM; + DBT_HostVar CT_CG_RDP; + DBT_HostVar NUM_IDENT_CG_RDP; + DBT_HostVar DAT_CRE_CG_BDM_RDP; + DBT_HostVar CD_BQUE_RDP; + DBT_HostVar CD_GUI_CLI_RDP; + DBT_HostVar CD_ACT_ECO; + DBT_HostVar CD_PAYS_NAIS; + DBT_HostVar CD_SOGETYPE; + DBT_HostVar CD_SIT_FAM; + DBT_HostVar CD_CMN_INSEE_NAIS; + DBT_HostVar CD_PAYS_RM; + DBT_HostVar CD_PAYS_RF; + DBT_HostVar CD_DEPT_NAIS; + DBT_HostVar CD_ST_PROF; + DBT_HostVar NOM_PAT; + DBT_HostVar NOM_MAR; + DBT_HostVar PNOM_OFF; + DBT_HostVar PNOM_SUPP; + DBT_HostVar RAISON_SOC; + DBT_HostVar CT_FOYER_MKT; + DBT_HostVar CD_CAT_PROF; + DBT_HostVar CT_ADRESSE; + DBT_HostVar CD_SEXE; + DBT_HostVar CD_ST_INT_CHQ; + DBT_HostVar CD_ST_DECEDE; + DBT_HostVar CD_ST_COM_PP; + DBT_HostVar CD_ETA_PP; + DBT_HostVar CD_ST_TECH; + DBT_HostVar CD_IND_PP_ANO; + DBT_HostVar CD_CAP_JUR; + DBT_HostVar CD_UNIC_PP; + DBT_HostVar ADR_EMAIL; + DBT_HostVar DAT_DER_MAJ_BLPP; + DBT_HostVar DAT_DEB_REL_PP; + DBT_HostVar DAT_NAIS; + DBT_HostVar DAT_PUR_BLPP; + DBT_HostVar DAT_FIN_ACT_COM; + DBT_HostVar AGE; + DBT_HostVar NUM_FAX; + DBT_HostVar NUM_TEL_DOM; + DBT_HostVar NUM_PORT; + DBT_HostVar STP_MKT; + DBT_HostVar STP_TEL; + DBT_HostVar TP_FICP; + DBT_HostVar TP_BFM; + DBT_HostVar TP_HDG; + DBT_HostVar TP_CLI_SNS; + DBT_HostVar TP_NOR_DAT_NAIS; + DBT_HostVar TP_TEL_DOM; + DBT_HostVar TP_RLV_BRA; + DBT_HostVar CD_PRIO_FOY; + DBT_HostVar CD_SEG_MAR; + DBT_HostVar SEL_NUM_TOTO; + DBT_Cursor Cursor; + int t1, t2; + + DBT_Indicator Tab_Indic_CT_PERSONNE_PHYSIQUE [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_NUM_PP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_DAT_DER_MAJ_BDM [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_DAT_CRE_PP_BDM [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CT_CG_RDP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_NUM_IDENT_CG_RDP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_DAT_CRE_CG_BDM_RDP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_BQUE_RDP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_GUI_CLI_RDP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_ACT_ECO [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_PAYS_NAIS [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_SOGETYPE [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_SIT_FAM [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_CMN_INSEE_NAIS [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_PAYS_RM [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_PAYS_RF [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_DEPT_NAIS [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_ST_PROF [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_NOM_PAT [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_NOM_MAR [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_PNOM_OFF [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_PNOM_SUPP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_RAISON_SOC [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CT_FOYER_MKT [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_CAT_PROF [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CT_ADRESSE [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_SEXE [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_ST_INT_CHQ [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_ST_DECEDE [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_ST_COM_PP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_ETA_PP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_ST_TECH [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_IND_PP_ANO [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_CAP_JUR [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_UNIC_PP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_ADR_EMAIL [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_DAT_DER_MAJ_BLPP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_DAT_DEB_REL_PP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_DAT_NAIS [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_DAT_PUR_BLPP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_DAT_FIN_ACT_COM [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_AGE [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_NUM_FAX [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_NUM_TEL_DOM [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_NUM_PORT [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_STP_MKT [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_STP_TEL [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_TP_FICP [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_TP_BFM [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_TP_HDG [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_TP_CLI_SNS [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_TP_NOR_DAT_NAIS [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_TP_TEL_DOM [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_TP_RLV_BRA [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_PRIO_FOY [NB_MAX_RECORD]; + DBT_Indicator Tab_Indic_CD_SEG_MAR [NB_MAX_RECORD]; + + /* Ouverture de la librairie */ + + if (DB_Library_Open (DBD_ERRMSG | DBD_DEBUG) != DBS_OK) + { + fprintf (stderr, "=> Ouverture de la lbrairie LIBDATABASE impossible\n"); + goto Error0; + } + + /* Connexion à la base de données */ + + /* if (DB_DataBase_Connect (ORACLE, "PBDME1", "entr", "entr") != DBS_OK) */ + if (DB_DataBase_Connect (ORACLE, "ENT1", "beatrice", "beatrice") != DBS_OK) + { + fprintf (stderr, "=> Connexion à la base impossible\n"); + DB_Library_Close (); + goto Error1; + } + + /* D\351finition des tableaux de valeurs */ + + DB_DateArray_Alloc (&Tab_DAT_DER_MAJ_BDM, NB_MAX_RECORD); + DB_DateArray_Alloc (&Tab_DAT_CRE_PP_BDM, NB_MAX_RECORD); + DB_DateArray_Alloc (&Tab_DAT_CRE_CG_BDM_RDP, NB_MAX_RECORD); + DB_DateArray_Alloc (&Tab_DAT_DER_MAJ_BLPP, NB_MAX_RECORD); + DB_DateArray_Alloc (&Tab_DAT_DEB_REL_PP, NB_MAX_RECORD); + DB_DateArray_Alloc (&Tab_DAT_NAIS, NB_MAX_RECORD); + DB_DateArray_Alloc (&Tab_DAT_PUR_BLPP, NB_MAX_RECORD); + DB_DateArray_Alloc (&Tab_DAT_FIN_ACT_COM, NB_MAX_RECORD); + + /* Définition des variables hôtes */ + + DB_HostVar_Setup (&CT_PERSONNE_PHYSIQUE,INTEGER,35,Tab_CT_PERSONNE_PHYSIQUE, Tab_Indic_CT_PERSONNE_PHYSIQUE); + DB_HostVar_Setup (&NUM_PP, STRING,7,Tab_NUM_PP, Tab_Indic_NUM_PP); + DB_HostVar_Setup (&DAT_DER_MAJ_BDM,DATE,NULL,Tab_DAT_DER_MAJ_BDM, Tab_Indic_DAT_DER_MAJ_BDM); + DB_HostVar_Setup (&DAT_CRE_PP_BDM,DATE,NULL,Tab_DAT_CRE_PP_BDM, Tab_Indic_DAT_CRE_PP_BDM); + DB_HostVar_Setup (&CT_CG_RDP,INTEGER,35,Tab_CT_CG_RDP, Tab_Indic_CT_CG_RDP); + DB_HostVar_Setup (&NUM_IDENT_CG_RDP,INTEGER,11,Tab_NUM_IDENT_CG_RDP, Tab_Indic_NUM_IDENT_CG_RDP); + DB_HostVar_Setup (&DAT_CRE_CG_BDM_RDP,DATE,NULL,Tab_DAT_CRE_CG_BDM_RDP, Tab_Indic_DAT_CRE_CG_BDM_RDP); + DB_HostVar_Setup (&CD_BQUE_RDP, STRING,5,Tab_CD_BQUE_RDP, Tab_Indic_CD_BQUE_RDP); + DB_HostVar_Setup (&CD_GUI_CLI_RDP, STRING,5,Tab_CD_GUI_CLI_RDP, Tab_Indic_CD_GUI_CLI_RDP); + DB_HostVar_Setup (&CD_ACT_ECO, STRING,2,Tab_CD_ACT_ECO, Tab_Indic_CD_ACT_ECO); + DB_HostVar_Setup (&CD_PAYS_NAIS, STRING,2,Tab_CD_PAYS_NAIS, Tab_Indic_CD_PAYS_NAIS); + DB_HostVar_Setup (&CD_SOGETYPE,INTEGER,2,Tab_CD_SOGETYPE, Tab_Indic_CD_SOGETYPE); + DB_HostVar_Setup (&CD_SIT_FAM, STRING,2,Tab_CD_SIT_FAM, Tab_Indic_CD_SIT_FAM); + DB_HostVar_Setup (&CD_CMN_INSEE_NAIS, STRING,5,Tab_CD_CMN_INSEE_NAIS, Tab_Indic_CD_CMN_INSEE_NAIS); + DB_HostVar_Setup (&CD_PAYS_RM, STRING,2,Tab_CD_PAYS_RM, Tab_Indic_CD_PAYS_RM); + DB_HostVar_Setup (&CD_PAYS_RF, STRING,2,Tab_CD_PAYS_RF, Tab_Indic_CD_PAYS_RF); + DB_HostVar_Setup (&CD_DEPT_NAIS, STRING,2,Tab_CD_DEPT_NAIS, Tab_Indic_CD_DEPT_NAIS); + DB_HostVar_Setup (&CD_ST_PROF, STRING,2,Tab_CD_ST_PROF, Tab_Indic_CD_ST_PROF); + DB_HostVar_Setup (&NOM_PAT, STRING,32,Tab_NOM_PAT, Tab_Indic_NOM_PAT); + DB_HostVar_Setup (&NOM_MAR, STRING,32,Tab_NOM_MAR, Tab_Indic_NOM_MAR); + DB_HostVar_Setup (&PNOM_OFF, STRING,32,Tab_PNOM_OFF, Tab_Indic_PNOM_OFF); + DB_HostVar_Setup (&PNOM_SUPP, STRING,32,Tab_PNOM_SUPP, Tab_Indic_PNOM_SUPP); + DB_HostVar_Setup (&RAISON_SOC, STRING,40,Tab_RAISON_SOC, Tab_Indic_RAISON_SOC); + DB_HostVar_Setup (&CT_FOYER_MKT,INTEGER,35,Tab_CT_FOYER_MKT, Tab_Indic_CT_FOYER_MKT); + DB_HostVar_Setup (&CD_CAT_PROF, STRING,2,Tab_CD_CAT_PROF, Tab_Indic_CD_CAT_PROF); + DB_HostVar_Setup (&CT_ADRESSE,INTEGER,35,Tab_CT_ADRESSE, Tab_Indic_CT_ADRESSE); + DB_HostVar_Setup (&CD_SEXE, STRING,2,Tab_CD_SEXE, Tab_Indic_CD_SEXE); + DB_HostVar_Setup (&CD_ST_INT_CHQ,INTEGER,1,Tab_CD_ST_INT_CHQ, Tab_Indic_CD_ST_INT_CHQ); + DB_HostVar_Setup (&CD_ST_DECEDE, STRING,2,Tab_CD_ST_DECEDE, Tab_Indic_CD_ST_DECEDE); + DB_HostVar_Setup (&CD_ST_COM_PP,INTEGER,1,Tab_CD_ST_COM_PP, Tab_Indic_CD_ST_COM_PP); + DB_HostVar_Setup (&CD_ETA_PP,INTEGER,1,Tab_CD_ETA_PP, Tab_Indic_CD_ETA_PP); + DB_HostVar_Setup (&CD_ST_TECH,INTEGER,1,Tab_CD_ST_TECH, Tab_Indic_CD_ST_TECH); + DB_HostVar_Setup (&CD_IND_PP_ANO, STRING,1,Tab_CD_IND_PP_ANO, Tab_Indic_CD_IND_PP_ANO); + DB_HostVar_Setup (&CD_CAP_JUR,INTEGER,1,Tab_CD_CAP_JUR, Tab_Indic_CD_CAP_JUR); + DB_HostVar_Setup (&CD_UNIC_PP,INTEGER,12,Tab_CD_UNIC_PP, Tab_Indic_CD_UNIC_PP); + DB_HostVar_Setup (&ADR_EMAIL, STRING,60,Tab_ADR_EMAIL, Tab_Indic_ADR_EMAIL); + DB_HostVar_Setup (&DAT_DER_MAJ_BLPP,DATE,NULL,Tab_DAT_DER_MAJ_BLPP, Tab_Indic_DAT_DER_MAJ_BLPP); + DB_HostVar_Setup (&DAT_DEB_REL_PP,DATE,NULL,Tab_DAT_DEB_REL_PP, Tab_Indic_DAT_DEB_REL_PP); + DB_HostVar_Setup (&DAT_NAIS,DATE,NULL,Tab_DAT_NAIS, Tab_Indic_DAT_NAIS); + DB_HostVar_Setup (&DAT_PUR_BLPP,DATE,NULL,Tab_DAT_PUR_BLPP, Tab_Indic_DAT_PUR_BLPP); + DB_HostVar_Setup (&DAT_FIN_ACT_COM,DATE,NULL,Tab_DAT_FIN_ACT_COM, Tab_Indic_DAT_FIN_ACT_COM); + DB_HostVar_Setup (&AGE,INTEGER,3,Tab_AGE, Tab_Indic_AGE); + DB_HostVar_Setup (&NUM_FAX, STRING,15,Tab_NUM_FAX, Tab_Indic_NUM_FAX); + DB_HostVar_Setup (&NUM_TEL_DOM, STRING,15,Tab_NUM_TEL_DOM, Tab_Indic_NUM_TEL_DOM); + DB_HostVar_Setup (&NUM_PORT, STRING,15,Tab_NUM_PORT, Tab_Indic_NUM_PORT); + DB_HostVar_Setup (&STP_MKT,INTEGER,1,Tab_STP_MKT, Tab_Indic_STP_MKT); + DB_HostVar_Setup (&STP_TEL,INTEGER,1,Tab_STP_TEL, Tab_Indic_STP_TEL); + DB_HostVar_Setup (&TP_FICP,INTEGER,1,Tab_TP_FICP, Tab_Indic_TP_FICP); + DB_HostVar_Setup (&TP_BFM,INTEGER,1,Tab_TP_BFM, Tab_Indic_TP_BFM); + DB_HostVar_Setup (&TP_HDG,INTEGER,1,Tab_TP_HDG, Tab_Indic_TP_HDG); + DB_HostVar_Setup (&TP_CLI_SNS,INTEGER,1,Tab_TP_CLI_SNS, Tab_Indic_TP_CLI_SNS); + DB_HostVar_Setup (&TP_NOR_DAT_NAIS,INTEGER,1,Tab_TP_NOR_DAT_NAIS, Tab_Indic_TP_NOR_DAT_NAIS); + DB_HostVar_Setup (&TP_TEL_DOM,INTEGER,1,Tab_TP_TEL_DOM, Tab_Indic_TP_TEL_DOM); + DB_HostVar_Setup (&TP_RLV_BRA,INTEGER,1,Tab_TP_RLV_BRA, Tab_Indic_TP_RLV_BRA); + DB_HostVar_Setup (&CD_PRIO_FOY,INTEGER,2,Tab_CD_PRIO_FOY, Tab_Indic_CD_PRIO_FOY); + DB_HostVar_Setup (&CD_SEG_MAR, STRING,5,Tab_CD_SEG_MAR, Tab_Indic_CD_SEG_MAR); + + /* Exécution de la requête */ + + /* DB_HostVar_Setup(&SEL_NUM_TOTO, INTEGER, NULL, &Start_Idx, &Start_Idx); */ + + Request = "SELECT \ + CT_PERSONNE_PHYSIQUE, \ + NUM_PP, \ + DAT_DER_MAJ_BDM, \ + DAT_CRE_PP_BDM, \ + CT_CG_RDP, \ + NUM_IDENT_CG_RDP, \ + DAT_CRE_CG_BDM_RDP, \ + CD_BQUE_RDP, \ + CD_GUI_CLI_RDP, \ + CD_ACT_ECO, \ + CD_PAYS_NAIS, \ + CD_SOGETYPE, \ + CD_SIT_FAM, \ + CD_CMN_INSEE_NAIS, \ + CD_PAYS_RM, \ + CD_PAYS_RF, \ + CD_DEPT_NAIS, \ + CD_ST_PROF, \ + NOM_PAT, \ + NOM_MAR, \ + PNOM_OFF, \ + PNOM_SUPP, \ + RAISON_SOC, \ + CT_FOYER_MKT, \ + CD_CAT_PROF, \ + CT_ADRESSE, \ + CD_SEXE, \ + CD_ST_INT_CHQ, \ + CD_ST_DECEDE, \ + CD_ST_COM_PP, \ + CD_ETA_PP, \ + CD_ST_TECH, \ + CD_IND_PP_ANO, \ + CD_CAP_JUR, \ + CD_UNIC_PP, \ + ADR_EMAIL, \ + DAT_DER_MAJ_BLPP, \ + CD_SEG_MAR \ + FROM TB_PERSONNE_PHYSIQUE"; + + /* Ouverture d'un curseur */ + + rc = DB_Cursor_Open (&Cursor, &Result, Request,NULL); + if (rc != DBS_OK) + { + fprintf (stderr, "=> Sélection impossible\n"); + goto Error2; + } + + /* Fetch du curseur */ + + rc = DB_Cursor_Fetch (Cursor, &Result, Nb_Exec, + &CT_PERSONNE_PHYSIQUE, + &NUM_PP, + &DAT_DER_MAJ_BDM, + &DAT_CRE_PP_BDM, + &CT_CG_RDP, + &NUM_IDENT_CG_RDP, + &DAT_CRE_CG_BDM_RDP, + &CD_BQUE_RDP, + &CD_GUI_CLI_RDP, + &CD_ACT_ECO, + &CD_PAYS_NAIS, + &CD_SOGETYPE, + &CD_SIT_FAM, + &CD_CMN_INSEE_NAIS, + &CD_PAYS_RM, + &CD_PAYS_RF, + &CD_DEPT_NAIS, + &CD_ST_PROF, + &NOM_PAT, + &NOM_MAR, + &PNOM_OFF, + &PNOM_SUPP, + &RAISON_SOC, + &CT_FOYER_MKT, + &CD_CAT_PROF, + &CT_ADRESSE, + &CD_SEXE, + &CD_ST_INT_CHQ, + &CD_ST_DECEDE, + &CD_ST_COM_PP, + &CD_ETA_PP, + &CD_ST_TECH, + &CD_IND_PP_ANO, + &CD_CAP_JUR, + &CD_UNIC_PP, + &ADR_EMAIL, + &DAT_DER_MAJ_BLPP, + &CD_SEG_MAR, + NULL); + if (rc == DBS_OK) + { + fprintf (stderr, "=> %d enregistrement(s) sélectionné(s) :\n", Result.Row_Num); + } + else if (rc == DBS_ERRNODATA) + { + fprintf (stderr, "=> Il y a moins de %d enregistrement(s) à sélectionner.\n", Nb_Exec); + } + else + { + fprintf (stderr, "=> Sélection impossible\n"); + DB_Cursor_Close (Cursor); + goto Error2; + } + + for (i = 0; i < Result.Row_Num; i++) + { + if (DB_DateToString_Convert (Tab_DAT_DER_MAJ_BDM, i, Date_Value, NULL) != DBS_OK) goto Error2; + fprintf (stderr, "Debug HME Tab_Indic_CD_ETA_PP = ##%d##\n", Tab_Indic_CD_ETA_PP[i]); + fprintf (stderr, "Debug HME CD_ETA_PP = ##%d##\n", Tab_CD_ETA_PP[i]); + fprintf (stderr, "Debug HME Tab_Indic_CD_ST_TECH = ##%d##\n", Tab_Indic_CD_ST_TECH[i]); + fprintf (stderr, "Debug HME CD_ST_TECH = ##%d##\n", Tab_CD_ST_TECH[i]); + } + + /* Fermeture du curseur */ + + DB_Cursor_Close (Cursor); + + if (DB_DataBase_Disconnect () != DBS_OK) + { + fprintf (stderr, "=> D\351connexion de la base impossible\n"); + goto Error1; + } + + + /* INsertion dans la table TEST_ENS */ + + t_start (t_exec); + + /* Connexion \340 la base de donn\351es */ + + if (DB_DataBase_Connect (ORACLE, "ENT1", "beatrice", "beatrice") != DBS_OK) + { + fprintf (stderr, "=> Connexion \340 la base impossible\n"); + DB_Library_Close (); + goto Error1; + } + + ins_Request = "INSERT INTO TEST_ENS \ + ( \ + CT_PERSONNE_PHYSIQUE, \ + NUM_PP, \ + DAT_DER_MAJ_BDM \ + /* DAT_CRE_PP_BDM, \ + CT_CG_RDP, \ + NUM_IDENT_CG_RDP, \ + DAT_CRE_CG_BDM_RDP, \ + CD_BQUE_RDP, \ + CD_GUI_CLI_RDP, \ + CD_ACT_ECO, \ + CD_PAYS_NAIS, \ + CD_SOGETYPE, \ + CD_SIT_FAM, \ + CD_CMN_INSEE_NAIS, \ + CD_PAYS_RM, \ + CD_PAYS_RF, \ + CD_DEPT_NAIS, \ + CD_ST_PROF, \ + NOM_PAT, \ + NOM_MAR, \ + PNOM_OFF, \ + PNOM_SUPP, \ + RAISON_SOC, \ + CT_FOYER_MKT, \ + CD_CAT_PROF, \ + CT_ADRESSE, \ + CD_SEXE, \ + CD_ST_INT_CHQ, \ + CD_ST_DECEDE, \ + CD_ST_COM_PP, \ + CD_ETA_PP, \ + CD_ST_TECH, \ + CD_IND_PP_ANO, \ + CD_CAP_JUR, \ + CD_UNIC_PP, \ + ADR_EMAIL, \ + DAT_DER_MAJ_BLPP, \ + CD_SEG_MAR */ + ) \ + VALUES \ + ( \ + :1, \ + :2, \ + :3 \ + /* :4, \ + :5, \ + :6, \ + :7, \ + :8, \ + :9, \ + :10, \ + :11, \ + :12, \ + :13, \ + :14, \ + :15, \ + :16, \ + :17, \ + :18, \ + :19, \ + :20, \ + :21, \ + :22, \ + :23, \ + :24, \ + :25, \ + :26, \ + :27, \ + :28, \ + :29, \ + :30, \ + :31, \ + :32, \ + :33, \ + :34, \ + :35, \ + :36, \ + :37, \ + :38 */ + )"; +fprintf (stderr, "Result.Row_Num = ##%d##\n",Result.Row_Num); +fprintf (stderr, "Start_Idx = ##%d##\n",Start_Idx); +fprintf (stderr, "ins_Request = ##%s##\n",ins_Request); + rc = DB_Insert_Exec (&ins_Result, ins_Request, Nb_Exec, Start_Idx, + &CT_PERSONNE_PHYSIQUE, + &NUM_PP, + &DAT_DER_MAJ_BDM, + /* &DAT_CRE_PP_BDM, + &CT_CG_RDP, + &NUM_IDENT_CG_RDP, + &DAT_CRE_CG_BDM_RDP, + &CD_BQUE_RDP, + &CD_GUI_CLI_RDP, + &CD_ACT_ECO, + &CD_PAYS_NAIS, + &CD_SOGETYPE, + &CD_SIT_FAM, + &CD_CMN_INSEE_NAIS, + &CD_PAYS_RM, + &CD_PAYS_RF, + &CD_DEPT_NAIS, + &CD_ST_PROF, + &NOM_PAT, + &NOM_MAR, + &PNOM_OFF, + &PNOM_SUPP, + &RAISON_SOC, + &CT_FOYER_MKT, + &CD_CAT_PROF, + &CT_ADRESSE, + &CD_SEXE, + &CD_ST_INT_CHQ, + &CD_ST_DECEDE, + &CD_ST_COM_PP, + &CD_ETA_PP, + &CD_ST_TECH, + &CD_IND_PP_ANO, + &CD_CAP_JUR, + &CD_UNIC_PP, + &ADR_EMAIL, + &DAT_DER_MAJ_BLPP, + &CD_SEG_MAR, */ + NULL); + + if (rc == DBS_OK) + { + fprintf (stderr, "Insert OK\n"); + } + else + { + fprintf (stderr, "Insert a échoué\n"); + } + +/* +if (DB_Transaction_Start (&t1) != DBS_OK) goto Error2; +rc = DB_Insert_Exec (&Result, Request, 10, 0, &CD_TOTO, &LIB_TOTO, &NUM_TOTO, &DAT_TOTO, NULL); + +if (DB_Transaction_Start (&t2) != DBS_OK) goto Error2; +rc = DB_Insert_Exec (&Result, Request, 10, 10, &CD_TOTO, &LIB_TOTO, &NUM_TOTO, &DAT_TOTO, NULL); + +if (DB_Transaction_Change (t1) != DBS_OK) goto Error2; +rc = DB_Insert_Exec (&Result, Request, 10, 20, &CD_TOTO, &LIB_TOTO, &NUM_TOTO, &DAT_TOTO, NULL); + +if (DB_Transaction_Change (t2) != DBS_OK) goto Error2; +rc = DB_Insert_Exec (&Result, Request, 10, 30, &CD_TOTO, &LIB_TOTO, &NUM_TOTO, &DAT_TOTO, NULL); +if (DB_Rollback_Exec () != DBS_OK) goto Error2; +if (DB_Transaction_End () != DBS_OK) goto Error2; + +if (DB_Transaction_Change (t1) != DBS_OK) goto Error2; +if (DB_Commit_Exec () != DBS_OK) goto Error2; +if (DB_Transaction_End () != DBS_OK) goto Error2; +*/ + t_stop (t_exec); + + + /* Affichage du temps d'exécution */ + + if (Result.Row_Num) + { + fprintf (stdout, "%d enregistrement(s) traité(s) en %.4f sec (%.2f enreg/sec)\n", + Result.Row_Num, t_exec.sec, Result.Row_Num / t_exec.sec ); + } + + if (DB_Commit_Exec () != DBS_OK) goto Error2; + + /* Libération des ressources */ + + DB_DateArray_Free (Tab_DAT_DER_MAJ_BDM); + DB_DateArray_Free (Tab_DAT_CRE_PP_BDM); + DB_DateArray_Free (Tab_DAT_CRE_CG_BDM_RDP); + DB_DateArray_Free (Tab_DAT_DER_MAJ_BLPP); + DB_DateArray_Free (Tab_DAT_DEB_REL_PP); + DB_DateArray_Free (Tab_DAT_NAIS); + DB_DateArray_Free (Tab_DAT_PUR_BLPP); + DB_DateArray_Free (Tab_DAT_FIN_ACT_COM); + + /* Déconnexion de la base */ + + if (DB_DataBase_Disconnect () != DBS_OK) + { + fprintf (stderr, "=> Déconnexion de la base impossible\n"); + goto Error1; + } + + /* Fermeture de la librairie */ + + if (DB_Library_Close () != DBS_OK) + { + fprintf (stderr, "=> Fermeture de la librairie LIBDATABASE impossible\n"); + goto Error0; + } + + return 0; + + /* Traitement des erreurs */ + + Error2: + DB_DateArray_Free (Tab_DAT_DER_MAJ_BDM); + DB_DateArray_Free (Tab_DAT_CRE_PP_BDM); + DB_DateArray_Free (Tab_DAT_CRE_CG_BDM_RDP); + DB_DateArray_Free (Tab_DAT_DER_MAJ_BLPP); + DB_DateArray_Free (Tab_DAT_DEB_REL_PP); + DB_DateArray_Free (Tab_DAT_NAIS); + DB_DateArray_Free (Tab_DAT_PUR_BLPP); + DB_DateArray_Free (Tab_DAT_FIN_ACT_COM); + DB_DataBase_Disconnect (); + + Error1: + DB_Library_Close (); + + Error0: + return -1; +} diff --git a/utils/dbtest.c b/utils/dbtest.c new file mode 100644 index 0000000..aaaa401 --- /dev/null +++ b/utils/dbtest.c @@ -0,0 +1,241 @@ +/*---------------------------------------------------------------------------------*/ +/* $RCSfile: dbtest.c,v $ */ +/*---------------------------------------------------------------------------------*/ +/* $Revision: 1.1 $ */ +/* $Name: $ */ +/* $Date: 2006/02/28 23:28:21 $ */ +/* $Author: agibert $ */ +/*---------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------*/ +/* This file is part of LibDataBase */ +/* */ +/* LibDataBase is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU Lesser General Public Licence as published by */ +/* the Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* LibDataBase is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with LibDataBase; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/*---------------------------------------------------------------------------------*/ + + + + + +#include "../lib/database.h" + +DBT_Connection conn; +DBT_Statement st; +DBT_Result res; + + +DBT_HostVar hv1; +DBT_HostVar hv2; +DBT_HostVar hv3; +DBT_HostVar hv4; +DBT_HostVar hv5; +DBT_HostVar hv6; +DBT_HostVar hv7; +DBT_HostVar hv8; +DBT_HostVar hv9; + +char buf1[100][20]; +char buf2[100][20]; +char buf3[100][20]; +char buf4[100][20]; +char buf5[100][20]; +char buf6[100][20]; +char buf7[100][20]; +char buf8[100][20]; +char buf9[100][20]; + +int int1[100]; +int int2[100]; +int int3[100]; +int int4[100]; +int int5[100]; +int int6[100]; +int int7[100]; +int int8[100]; +int int9[100]; + + +DBT_Indicator indic1[100]; +DBT_Indicator indic2[100]; +DBT_Indicator indic3[100]; +DBT_Indicator indic4[100]; +DBT_Indicator indic5[100]; +DBT_Indicator indic6[100]; +DBT_Indicator indic7[100]; +DBT_Indicator indic8[100]; +DBT_Indicator indic9[100]; +int i; + + +int main(int argc, char **argv) +{ + DBT_Status rc; + char *err; + + rc = DB_Library_Open(DBD_DEBUG | DBD_ERRMSG); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("open: %s\n", err); + return 1; + } + + rc = DB_Connect(&conn, "florian", "florian", "hera"); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("connect: %s\n", err); + return 1; + } + + rc = DB_Statement_Init(&conn, &st); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("st_init: %s\n", err); + return 1; + } + + rc = DB_Statement_Prepare(&st, argv[1]); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("st_prep: %s\n", err); + return 1; + } + + + + rc = DB_HostVar_Setup(&hv1, DBD_STRING, 20, buf1, indic1); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("hv1_set: %s\n", err); + return 1; + } + rc = DB_HostVar_Setup(&hv2, DBD_STRING, 20, buf2, indic2); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("hv2_set: %s\n", err); + return 1; + } + rc = DB_HostVar_Setup(&hv3, DBD_STRING, 20, buf3, indic3); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("hv3_set: %s\n", err); + return 1; + } + rc = DB_HostVar_Setup(&hv4, DBD_STRING, 20, buf4, indic4); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("hv4_set: %s\n", err); + return 1; + } + + rc = DB_HostVar_Setup(&hv5, DBD_INTEGER, 0, int1, indic5); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("hv5_set: %s\n", err); + return 1; + } + rc = DB_HostVar_Setup(&hv6, DBD_INTEGER, 0, int2, indic6); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("hv6_set: %s\n", err); + return 1; + } + rc = DB_HostVar_Setup(&hv7, DBD_STRING, 20, buf7, indic7); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("hv7_set: %s\n", err); + return 1; + } + rc = DB_HostVar_Setup(&hv8, DBD_STRING, 20, buf8, indic8); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("hv8_set: %s\n", err); + return 1; + } + rc = DB_HostVar_Setup(&hv9, DBD_STRING, 20, buf9, indic9); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("hv9_set: %s\n", err); + return 1; + } + + + + + + rc = DB_Statement_DefineVars(&st, 10, &hv1, &hv2, NULL); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("st_def: %s\n", err); + return 1; + } + + rc = DB_Statement_BindVars(&st, 100, &hv5, &hv6, NULL); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("st_bind: %s\n", err); + return 1; + } + + + + for (i = 0; i < 100; i++) { + indic5[i] = 0; strcpy(buf5[i], "4"); int1[i] = 1; + indic6[i] = 0; strcpy(buf6[i], "6"); int2[i] = i; + } + + + rc = DB_Statement_Execute(&st, atoi(argv[2]), atoi(argv[3]), &res); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("st_ex: %s\n", err); + } + + printf("Rc: %d; Res: %d processed, error iteration %d\n", + rc, res.rowsProcessed, res.errorIteration); + + if (st.isSelect) { + while (rc == DBS_OK) { + for (i = 0; i < res.rowsProcessed; i++) { + printf("%2d: %s(%d) | %s(%d) | %s(%d)\n", + i, + buf1[i], indic1[i], + buf2[i], indic2[i], + buf3[i], indic3[i], + buf4[i], indic4[i], + buf5[i], indic5[i], + buf6[i], indic6[i], + buf7[i], indic7[i], + buf8[i], indic8[i], + buf9[i], indic9[i] + ); + } + + rc = DB_Statement_Fetch(&st, &res); + if (DB_ERROR(rc)) { + DB_Library_Error_Get(&err); + printf("st_fetch: %s\n", err); + } + + printf("Rc: %d; Res: %d processed, error iteration %d\n", + rc, res.rowsProcessed, res.errorIteration); + }; + } + + printf("End, rc = %d\n", rc); + + DB_Disconnect(&conn); + + return 0; +} diff --git a/utils/perfResults.txt b/utils/perfResults.txt new file mode 100644 index 0000000..622d904 --- /dev/null +++ b/utils/perfResults.txt @@ -0,0 +1,91 @@ +---- Base: +florian/florian@hera + +---- Table: +CREATE TABLE dummy (c1 NUMBER(35) NOT NULL PRIMARY KEY, + c2 VARCHAR2(16), + c3 NUMBER(10)); + +---- Query: +"INSERT INTO dummy (c1, c2, c3) VALUES (:1, :2, :3)" + +:1 range from 1 to N +:2 range from 'B1' to 'BN' +:3 range from 1 to N + +---- Time Results (seconds): + + N | Empty table | after 1 shot | after 2 shots | rows/sec +-------------------------------------------------------------------------------------------- + 10 | (ms) 2.19; 1.79; 3.69; 1.76 | | 4500 ~ 5600 + 100 | (ms) 6.8; 10.5; 8.0; | | 9500 ~ 14700 + 1 000 | (ms) 68.3; 80.7; 79.1; | | 12800 ~ 14600 +10 000 | 1.5; 1.2; 1.1 | 1.4; 1.4; 1.3 | 1.1; 1.1; 1.3 | 6600 ~ 9000 +50 000 | 7.1; 6.8; 7.1 | 6.4; 8.0; 7.3 | 9.3; 8.0; 6.9 | 5300 ~ 7800 +65 536 | 12.8; 12.6 | 11.5; 11.6; | 11.3; | 5120 ~ 5800 +-------------------------------------------------------------------------------------------- + + +---- Query: +"SELECT c1, c2, c3 FROM dummy" + +Select 100 000 rows in 2.7 sec. --> 35000 rows/sec +Select 100 000 rows in 2.3 sec. --> 43000 rows/sec + +---- Query: +"SELECT c1, c2, c3 FROM dummy WHERE c1 > 0 and c3 < 1234567" + +Select 100 000 rows in 9.5 sec. --> 10500 rows/sec +Select 100 000 rows in 9.6 sec. --> 10400 rows/sec + + +###################################################################################### + + +---- Base: +entr/entr@pbdme1 + + +---- Table: +TB_PERSONNE_PHYSIQUE & test_ens + +[ CREATE TABLE test_ens (CT_PERSONNE_PHYSIQUE NOT NULL NUMBER(35), + NUM_PP NOT NULL CHAR(7), DAT_DER_MAJ_BDM DATE, .......) ] + +---- Query: +"SELECT CT_PERSONNE_PHYSIQUE, NUM_PP, DAT_DER_MAJ_BDM FROM tb_personne_physique" + +Select 11000 rows in 2.7 sec. --> 4000 rows/sec +Select 11000 rows in 2.5 sec. --> 4400 rows/sec +Select 11000 rows in 2.4 sec. --> 4500 rows/sec + +Select 50000 rows in 11.6 sec. --> 4300 rows/sec +Select 50000 rows in 11.4 sec. --> 4400 rows/sec + + +---- Query: +"INSERT INTO test_ens (CT_PERSONNE_PHYSIQUE, NUM_PP, DAT_DER_MAJ_BDM) VALUES (:1, :2, :3)" +Input values taken from table "tb_personne_physique" as shown above. + + +---- Time Results (seconds): + + N | Empty table | after 1 shot | after 2 shots | rows/sec +-------------------------------------------------------------------------------------------- +10 000 | 1.1; 1.3; 1.2 | 1.3; | 1.2; | 7000 ~ 9000 +50 000 | 5.9; 5.9; 6.2 | 6.4; | 6.0; | 7800 ~ 8400 +-------------------------------------------------------------------------------------------- + +Insert N rows of 38 columns: + + N | | rows/sec +-------------------------------------------------------------------------------------------- + 100 | 0.10; 0.11; 0.10; | 877 ~ 980 + 500 | 0.47; 0.41; 0.42; | 1060 ~ 1219 + 1 000 | 0.87; 0.81; 0.83; | 1100 ~ 1200 + 2 000 | 7.93; 8.29; 8.23; | 1200 ~ 1260 +10 000 | 8.01; 7.98; 8.26; | 1200 ~ 1250 +15 000 | 15.8; 16.3; 16.4; | 914 ~ 949 +-------------------------------------------------------------------------------------------- + +Select 20000 rows in 38.6 sec. --> 518 rows/sec \ No newline at end of file diff --git a/utils/testEntr.c b/utils/testEntr.c new file mode 100644 index 0000000..c4f0f84 --- /dev/null +++ b/utils/testEntr.c @@ -0,0 +1,336 @@ +/*---------------------------------------------------------------------------------*/ +/* $RCSfile: testEntr.c,v $ */ +/*---------------------------------------------------------------------------------*/ +/* $Revision: 1.1 $ */ +/* $Name: $ */ +/* $Date: 2006/02/28 23:28:21 $ */ +/* $Author: agibert $ */ +/*---------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------*/ +/* This file is part of LibDataBase */ +/* */ +/* LibDataBase is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU Lesser General Public Licence as published by */ +/* the Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* LibDataBase is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with LibDataBase; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/*---------------------------------------------------------------------------------*/ + + + + + +#include +#include + +#include +#include "../lib/database.h" +#include "testEntr.h" +#include "testEntrColumns.h" + + +/* Globals */ +extern DBT_HostVar hv[]; +extern DBT_Indicator *indic[]; + +int totalRowsProcessed = 0; +int arraySize = 1; +int columnsCount = 3; +int showResult = 0; +int from = 0; +int count = 0; +int debugLevel = 0; +char *req = NULL; +const char *login = ""; +const char *pwd = ""; +const char *server = ""; + +DBT_Connection conn; +DBT_Statement st; +DBT_Result res; + + +/** + * Main. + */ +int main(int argc, char **argv) { + int i; + DBT_Status rc; + TOOLT_Counter *counter = NULL; + + + /* Parse arguments */ + parseArgs(argc, argv); + + req = createSelectRequest(columnsCount); + + + counter = TOOL_Counter_Alloc(1); + rc = DB_Library_Open(DBD_DEBUG | DBD_ERRMSG); + if (DB_ERROR(rc)) { + printf("Error: Could not open library (%s)\n", DB_Error_Message_Get()); + return 1; + } + + + /* Connect to Database */ + rc = DB_Connect(&conn, login, pwd, server); + if (DB_ERROR(rc)) { + printf("Error: Could not connect (%s)\n", DB_Error_Message_Get()); + return 1; + } + + + say("\n==== SELECT ===================================================\n"); + + /* Init data that are going to be selected then inserted */ + say("Setup data and HostVars\n"); + setupData(arraySize); + if (setupHostVars() == FALSE) + return 1; + + /* Init statement */ + rc = DB_Statement_Init(&conn, &st); + if (DB_ERROR(rc)) { + printf("Error: Could not init statement (err %d: %s)\n", rc, DB_Error_Message_Get()); + return 1; + } + + say("Preparing statement for query: '%s'\n", req); + rc = DB_Statement_Prepare(&st, req); + if (DB_ERROR(rc)) { + printf("Error: Could not prepare statement (err %d: %s)\n", rc, DB_Error_Message_Get()); + return 1; + } + + /* Associate nth hostvar to nth column (note: first column index is 1) */ + say("Define output vars\n"); + for (i=0; i < columnsCount; ++i) { + rc = DB_Statement_DefineVar(&st, arraySize, i+1, &hv[i]); + if (DB_ERROR(rc)) { + printf("Error: Could not define vars (%s)\n", DB_Error_Message_Get()); + return 1; + } + } + + say("Executing Statement (from row %d, count=%d)...\n", from, count); + TOOL_Counter_Start(counter, 0); + + /* Note: 'count' is not relevant here: the number of rows fetched will be equal + to the size of the array of defined values (set by DB_Statement_DefineVars). + IMPORTANT: However, if some hostvars are bound to placeholders (:1, :2, etc.) in a + SELECT statement with DB_Statement_BindVars(), 'count' must be equal to 1 ! + No array allowed. */ + rc = DB_Statement_Execute(&st, from, count, &res); + TOOL_Counter_Stop(counter, 0); + + + /* Display results of SELECT request */ + if (rc == DBS_OK || rc == DBS_END_OF_DATA) { + say("Result = %s; %d rows processed in %ld ms\n", ERROR_TO_STRING(rc), res.rowsProcessed, TOOL_Counter_Get(counter, 0)); + if (showResult) + displayValues(res.rowsProcessed); + } + else { + say("Error: %s", DB_Error_Message_Get()); + say("%d rows processed (error at iteration %d)\n", res.rowsProcessed, res.errorIteration); + } + + /* If you want to execute another SELECT request, you should cancel the current + cursor (to destroy pre-fetch rows) with: */ + if (DB_Statement_Fetch_Terminate(&st) != DBS_OK) + say("Error: Could not cancel pre-fetch cursor\n"); + + + + say("\n\n==== INSERT ===================================================\n"); + + free(req); + req = createInsertRequest(columnsCount); + + /* Note that although we use the same statement as for SELECT, we could use a new one. */ + say("Preparing statement for query: '%s'\n", req); + rc = DB_Statement_Prepare(&st, req); + if (DB_ERROR(rc)) { + printf("Error: Could not prepare statement (err %d: %s)\n", rc, DB_Error_Message_Get()); + return 1; + } + + /* Associate nth hostvar to nth placeholder (note: first placeholder index is 1) */ + say("Bind Vars\n"); + for (i=0; i < columnsCount; ++i) { + rc = DB_Statement_BindVar(&st, arraySize, i+1, &hv[i]); + if (DB_ERROR(rc)) { + printf("Error: Could not bind vars (%s)\n", DB_Error_Message_Get()); + return 1; + } + } + + /* Start transaction */ + say("Start Transaction\n"); + DB_Transaction_Start(&conn); + + say("Executing Statement (array size: %d; starting from row %d, %d by %d)...\n", arraySize, from, count, count); + TOOL_Counter_Start(counter, 0); + + while (from < arraySize) { + if (from + count > arraySize) + count = arraySize - from; + + rc = DB_Statement_Execute(&st, from, count, &res); + totalRowsProcessed += res.rowsProcessed; + + if (DB_ERROR(rc)) + break; + + from += count; + } + + TOOL_Counter_Stop(counter, 0); + + if (DB_ERROR(rc)) { + say("Error: %s", DB_Error_Message_Get()); + say("%d rows processed (error at iteration %d)\n", totalRowsProcessed, res.errorIteration); + } + else { + say("OK, %d rows processed in %ld ms\n", totalRowsProcessed, TOOL_Counter_Get(counter, 0)); + } + + /* End transaction */ + say("Committing Transaction\n\n"); + DB_Transaction_Commit(&conn); + + DB_Statement_Close(&st); + + /* End of work */ + if (req) + free(req); + TOOL_Counter_Free(counter); + + DB_Disconnect(&conn); + DB_Library_Close(); + say("End.\n"); + return 0; +} + + +/** + * Affichage sur la sortie standard. + */ +void say(const char *format, ...) { + char buffer[1024]; + va_list v; + + va_start(v, format); + vsnprintf(buffer, sizeof(buffer), format, v); + fprintf (stdout, "%s", buffer); + + va_end(v); +} + + +/** + * Arguments. + */ +void parseArgs(int argc, char **argv) { + int i = 0; + + for (i = 1; i < argc; ++i) { + if (! strcasecmp(argv[i], "--debuglevel")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + debugLevel = atoi(argv[i]); + DB_Debug_Level_Set(debugLevel); + } + else if (! strcasecmp(argv[i], "--from")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + from = atoi(argv[i]); + } + else if (! strcasecmp(argv[i], "--count")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + count = atoi(argv[i]); + } + else if (! strcasecmp(argv[i], "--db")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + splitDBSpec(argv[i], &login, &pwd, &server); + } + else if (! strcasecmp(argv[i], "--col")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + columnsCount = atoi(argv[i]); + } + else if (! strcasecmp(argv[i], "--show")) { + showResult = 1; + } + else if (! strcasecmp(argv[i], "--size")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + arraySize = atoi(argv[i]); + } + else if (! strcasecmp(argv[i], "--help") || ! strcasecmp(argv[i], "-h") || ! strcasecmp(argv[i], "-?")) { + usage(argv); + exit(1); + } + else { + usage(argv); + exit(1); + } + } +} + + +/** + * Usage. + */ +void usage(char **argv) { + char *b = basename(argv[0]); + printf(USAGE, b, b, b); +} + + +/** + * Splits a database specification in the format "login/password@server" into its + * basic components 'login', 'password' and 'server'. + * Note that the initial 'spec' string may be altered. + */ +void splitDBSpec(char *spec, const char **login_, const char **pwd_, const char **server_) { + char *p = NULL; + + *login_ = spec; + p = strchr(spec, '/'); + if (p == NULL) + return; + + *p = 0; + *pwd_ = ++p; + + p = strchr(p, '@'); + if (p == NULL) + return; + *p = 0; + *server_ = ++p; +} diff --git a/utils/testEntr.h b/utils/testEntr.h new file mode 100644 index 0000000..0b04279 --- /dev/null +++ b/utils/testEntr.h @@ -0,0 +1,65 @@ +/*---------------------------------------------------------------------------------*/ +/* $RCSfile: testEntr.h,v $ */ +/*---------------------------------------------------------------------------------*/ +/* $Revision: 1.1 $ */ +/* $Name: $ */ +/* $Date: 2006/02/28 23:28:21 $ */ +/* $Author: agibert $ */ +/*---------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------*/ +/* This file is part of LibDataBase */ +/* */ +/* LibDataBase is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU Lesser General Public Licence as published by */ +/* the Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* LibDataBase is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with LibDataBase; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/*---------------------------------------------------------------------------------*/ + + + + + +#ifndef TESTENTR_H +#define TESTENTR_H + + +#define USAGE "Usage: %s [--from ] [--count ] [--db ] [--show] [--size ] [--col ]\n\n\ +Selects columns from table TB_PERSONNE_PHYSIQUE then inserts them into table TEST_ENS.\n\ +Options:\n\ + --from:\tStarting row in the array from which retrieved data will be put (default: 0).\n\ + --count:\tRows count to retrieve and insert (default: 0).\n\ + --db:\t\tDatabase specification in the format: login/password@server.\n\ + --show:\tIf specified, the results of the SELECT are shown.\n\ + --col:\tColumns count to fetch and insert for each row (default: 3).\n\ + --size:\tTotal size of the array that will contain selected values (default: 1).\n\ +\n\ +Examples:\n\ +_ '%s --db entr/entr@pbdme1 --size 10000 --count 1000 --col 38' selects 10000 rows of 38\n\ + columns from table TB_PERSONNE_PHYSIQUE and inserts them 1000 by 1000 into table TEST_ENS.\n\ +_ '%s --db entr/entr@pbdme1 --size 50 --count 50 --col 4 --show' selects 50 rows of 4\n\ + columns from TB_PERSONNE_PHYSIQUE, displays values then inserts them 50 by 50 into TEST_ENS.\n" + + +#define TRUE 1 +#define FALSE 0 + +extern int strcasecmp(const char *, const char *); +extern char *strdup(const char *); + +void parseArgs(int argc, char **argv); +void usage(char **argv); +void say (const char *format, ...); +void splitDBSpec(char *spec, const char **login, const char **pwd, const char **server); + + +#endif diff --git a/utils/testEntrColumns.c b/utils/testEntrColumns.c new file mode 100644 index 0000000..39b661f --- /dev/null +++ b/utils/testEntrColumns.c @@ -0,0 +1,189 @@ +/*---------------------------------------------------------------------------------*/ +/* $RCSfile: testEntrColumns.c,v $ */ +/*---------------------------------------------------------------------------------*/ +/* $Revision: 1.1 $ */ +/* $Name: $ */ +/* $Date: 2006/02/28 23:28:21 $ */ +/* $Author: agibert $ */ +/*---------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------*/ +/* This file is part of LibDataBase */ +/* */ +/* LibDataBase is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU Lesser General Public Licence as published by */ +/* the Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* LibDataBase is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with LibDataBase; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/*---------------------------------------------------------------------------------*/ + + + + + +#include "../lib/database.h" +#include "testEntr.h" +#include "testEntrColumns.h" + + +/* Globals */ +extern int columnsCount; /* cf. testEntr.c */ +DBT_HostVar hv[MAX_COLUMNS]; /* One hostvar for each column */ +DBT_Indicator *indic[MAX_COLUMNS]; /* One array of indicator for each column */ + +const char *columnsNames[] = { + "CT_PERSONNE_PHYSIQUE", "NUM_PP", "DAT_DER_MAJ_BDM", "DAT_CRE_PP_BDM", "CT_CG_RDP", + "NUM_IDENT_CG_RDP", "DAT_CRE_CG_BDM_RDP", "CD_BQUE_RDP", "CD_GUI_CLI_RDP", + "CD_ACT_ECO", "CD_PAYS_NAIS", "CD_SOGETYPE", "CD_SIT_FAM", "CD_CMN_INSEE_NAIS", + "CD_PAYS_RM", "CD_PAYS_RF", "CD_DEPT_NAIS", "CD_ST_PROF", "NOM_PAT", "NOM_MAR", + "PNOM_OFF", "PNOM_SUPP", "RAISON_SOC", "CT_FOYER_MKT", "CD_CAT_PROF", "CT_ADRESSE", + "CD_SEXE", "CD_ST_INT_CHQ", "CD_ST_DECEDE", "CD_ST_COM_PP", "CD_ETA_PP", "CD_ST_TECH", + "CD_IND_PP_ANO", "CD_CAP_JUR", "CD_UNIC_PP", "ADR_EMAIL", "DAT_DER_MAJ_BLPP", "CD_SEG_MAR" +}; + +int columnsSizes[] = { + INTEGER_SIZE, 8, DATE_SIZE, DATE_SIZE, INTEGER_SIZE, INTEGER_SIZE, DATE_SIZE, 6, 6, 3, 3, + INTEGER_SIZE, 3, 3, 3, 3, 3, 3, 33, 33, 33, 33, 41, INTEGER_SIZE, 3, INTEGER_SIZE, 3, + INTEGER_SIZE, 3, INTEGER_SIZE, INTEGER_SIZE, INTEGER_SIZE, 2, INTEGER_SIZE, INTEGER_SIZE, + 81, DATE_SIZE, 6 +}; + +int columnsTypes[] = { + DBD_INTEGER, DBD_STRING, DBD_STRING, DBD_STRING, DBD_INTEGER, DBD_INTEGER, DBD_STRING, + DBD_STRING, DBD_STRING, DBD_STRING, DBD_STRING, DBD_INTEGER, DBD_STRING, DBD_STRING, + DBD_STRING, DBD_STRING, DBD_STRING, DBD_STRING, DBD_STRING, DBD_STRING, + DBD_STRING, DBD_STRING, DBD_STRING, DBD_INTEGER, DBD_STRING, DBD_INTEGER, DBD_STRING, + DBD_INTEGER, DBD_STRING, DBD_INTEGER, DBD_INTEGER, DBD_INTEGER, DBD_STRING, DBD_INTEGER, + DBD_INTEGER, DBD_STRING, DBD_STRING, DBD_STRING +}; + +void *columnsValues[MAX_COLUMNS]; + + +/** + * Initializes host variables. + * Associates an 'hostvar' with a type, size, array of values and array of indicators + * for each column. + */ +int setupHostVars(void) { + int i = 0; + DBT_Status rc; + + for (i = 0; i < columnsCount; ++i) { + rc = DB_HostVar_Setup(&hv[i], columnsTypes[i], columnsSizes[i], columnsValues[i], indic[i]); + if (rc != DBS_OK) { + say("Error: %s\n", DB_Error_Message_Get()); + return FALSE; + } + } + + return TRUE; +} + + +/** + * Setup arrays. + * n (IN): Rows count to allocate for each array. + */ +void setupData(int n) { + int i; + + for (i = 0; i < columnsCount; ++i) { + /* Allocate array of indicators for each column */ + indic[i] = malloc(n * sizeof(int)); + + /* Allocate arrays of values for each column */ + columnsValues[i] = malloc((unsigned) n * columnsSizes[i]); + } +} + + +/** + * Dynamically creates the SELECT request according to the number of columns involved. + */ +char *createSelectRequest(int columns) { + int i; + char *s = (char *) malloc(2000); + + strcpy(s, "SELECT "); + for (i = 0; i < columns; ++i) { + strcat(s, columnsNames[i]); + if (i < columns -1) + strcat(s, ", "); + } + strcat(s, " FROM tb_personne_physique"); + return s; +} + + +/** + * Dynamically creates the INSERT request according to the number of columns involved. + */ +char *createInsertRequest(int columns) { + int i; + char val[8]; + char *s = (char *) malloc(2000); + + strcpy(s, "INSERT INTO test_ens ("); + for (i = 0; i < columns; ++i) { + strcat(s, columnsNames[i]); + if (i < columns -1) + strcat(s, ", "); + } + strcat(s, ") VALUES ("); + + for (i = 0; i < columns; ++i) { + sprintf(val, ":%d", i+1); + strcat(s, val); + if (i < columns -1) + strcat(s, ", "); + } + strcat(s, ")"); + return s; +} + + +/** + * Dynamically displays values of each column according to their type. + */ +void displayValues(int rowsCount) { + int row; + int col; + + say("Columns %d to %d:\n", 1, columnsCount); + for (row = 0; row < rowsCount; row++) { + say("#%d\t", row); + for (col = 0; col < columnsCount; col++) { + if (indic[col][row] == -1) { + printf(" "); + } + else { + if (columnsTypes[col] == DBD_INTEGER) { + int v = ((int *)(columnsValues[col])) [row]; + printf("%d ", v); + /* indicator at -2 or > 0 means data have been truncated */ + if (indic[col][row] != 0) + printf(" "); + } + else if (columnsTypes[col] == DBD_STRING) { + char *v = & ((char *)(columnsValues[col])) [row * columnsSizes[col]]; + printf("%s ", v); + if (indic[col][row] != 0) + printf(" "); + } + else { + printf(" "); + } + } + } + printf("\n"); + } +} diff --git a/utils/testEntrColumns.h b/utils/testEntrColumns.h new file mode 100644 index 0000000..74e92df --- /dev/null +++ b/utils/testEntrColumns.h @@ -0,0 +1,48 @@ +/*---------------------------------------------------------------------------------*/ +/* $RCSfile: testEntrColumns.h,v $ */ +/*---------------------------------------------------------------------------------*/ +/* $Revision: 1.1 $ */ +/* $Name: $ */ +/* $Date: 2006/02/28 23:28:21 $ */ +/* $Author: agibert $ */ +/*---------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------*/ +/* This file is part of LibDataBase */ +/* */ +/* LibDataBase is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU Lesser General Public Licence as published by */ +/* the Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* LibDataBase is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with LibDataBase; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/*---------------------------------------------------------------------------------*/ + + + + + +#ifndef TESTENTRCOLUMNS_H +#define TESTENTRCOLUMNS_H + + +#define MAX_COLUMNS 38 +#define STRING_SIZE 20 +#define DATE_SIZE 20 +#define INTEGER_SIZE sizeof(int) + +int setupHostVars(void); +void setupData(int n); +char *createSelectRequest(int columns); +char *createInsertRequest(int columns); +void displayValues(int rowsCount); + + +#endif diff --git a/utils/testInsert.c b/utils/testInsert.c new file mode 100644 index 0000000..8bd0ab0 --- /dev/null +++ b/utils/testInsert.c @@ -0,0 +1,368 @@ +/*---------------------------------------------------------------------------------*/ +/* $RCSfile: testInsert.c,v $ */ +/*---------------------------------------------------------------------------------*/ +/* $Revision: 1.1 $ */ +/* $Name: $ */ +/* $Date: 2006/02/28 23:28:21 $ */ +/* $Author: agibert $ */ +/*---------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------*/ +/* This file is part of LibDataBase */ +/* */ +/* LibDataBase is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU Lesser General Public Licence as published by */ +/* the Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* LibDataBase is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with LibDataBase; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/*---------------------------------------------------------------------------------*/ + + + + + +#include +#include + +#include +#include "../lib/database.h" + + +/* Globals */ +#define DEFAULT_REQUEST "INSERT INTO dummy (c1, c2, c3) VALUES (:1, :2, :3)" +#define TRUE 1 +#define FALSE 0 +const char *USAGE = "Usage: %s [--req ] [--from ] [--count ] [--db ] [--size ] [--baseIndex ]\n\n\ +Executes an INSERT SQL request in a table which must have the following format:\n\ +\"CREATE TABLE dummy (c1 NUMBER(35) primary key, c2 VARCHAR2(16), c3 NUMBER(10))\".\n\ +Data to insert are taken from an array which elements are generated by the program (see\n\ +option --baseIndex).\n\ +\n\ +Options:\n\ + --req:\tExecutes specified request. If not specified, a default request is used:\n\ + \t\"INSERT INTO dummy (c1, c2, c3) VALUES (:1, :2, :3)\".\n\ + --from:\tStarting row in the array of input data (default: 0).\n\ + --count:\tRows count to use in the input array (1 to 65536) (Default: 0).\n\ + --size:\tTotal number of rows of the input array generated by the program (default: 1).\n\ + --db:\t\tDatabase specification in the format: login/password@oracleSID.\n\ + --baseIndex:\tStart index to use to create input data. Ex: if baseIndex = 10, first row\n\ + to insert will have columns values: 10, 'A10', 110; second row will have\n\ + 11, 'A11', 111; etc. (default: 1).\n\ +\n\ +Examples:\n\ +_ '%s --db \"login/pwd@srv\" --size 100 --count 20' will insert 5 times 20 rows in table dummy.\n\ +_ '%s --db \"login/pwd@srv\" --size 10 --count 4' will insert 2 times 4 rows then the 2\n\ + remaining rows.\n"; + + +extern int strcasecmp(const char *, const char *); +extern char *strdup(const char *); +void parseArgs(int argc, char **argv); +void usage(char **argv); +void say (const char *format, ...); +int setupHostVars(void); +void setupData(int n); +void splitDBSpec(char *spec, const char **login, const char **pwd, const char **server); + + +int arraySize = 1; +int baseIndex = 0; +int from = 0; +int count = 0; +int debugLevel = 0; +char *req = NULL; +const char *login = ""; +const char *pwd = ""; +const char *server = ""; +DBT_Connection conn; +DBT_Statement st; +DBT_Result res; + +DBT_HostVar hv1; +DBT_HostVar hv2; +DBT_HostVar hv3; + +int *dynInt1 = NULL; +char *dynBuf = NULL; +int *dynInt3 = NULL; + +DBT_Indicator *dynIndic1 = NULL; +DBT_Indicator *dynIndic2 = NULL; +DBT_Indicator *dynIndic3 = NULL; + + + +/** + * Main. + */ +int main(int argc, char **argv) { + int totalRowsProcessed = 0; + DBT_Status rc; + TOOLT_Counter *counter = NULL; + + + /* Parse arguments */ + parseArgs(argc, argv); + + if (req == NULL) { + req = strdup(DEFAULT_REQUEST); + } + + + counter = TOOL_Counter_Alloc(1); + rc = DB_Library_Open(DBD_DEBUG | DBD_ERRMSG); + if (DB_ERROR(rc)) { + printf("Error: Could not open library (%s)\n", DB_Error_Message_Get()); + return 1; + } + + + /* Connect to Database */ + rc = DB_Connect(&conn, login, pwd, server); + if (DB_ERROR(rc)) { + printf("Error: Could not connect (%s)\n", DB_Error_Message_Get()); + return 1; + } + + + /* Init data that are going to be inserted */ + say("Setup data and HostVars\n"); + setupData(arraySize); + if (setupHostVars() == FALSE) + return 1; + + + /* Init statement */ + rc = DB_Statement_Init(&conn, &st); + if (DB_ERROR(rc)) { + printf("Error: Could not init statement (err %d: %s)\n", rc, DB_Error_Message_Get()); + return 1; + } + + say("Preparing statement for query: '%s'\n", req); + rc = DB_Statement_Prepare(&st, req); + if (DB_ERROR(rc)) { + printf("Error: Could not prepare statement (err %d: %s)\n", rc, DB_Error_Message_Get()); + return 1; + } + + say("Bind Vars\n"); + rc = DB_Statement_BindVars(&st, arraySize, &hv1, &hv2, &hv3, NULL); + if (DB_ERROR(rc)) { + printf("Error: Could not bind vars (%s)\n", DB_Error_Message_Get()); + return 1; + } + + /* Start transaction */ + say("\nStart Transaction\n"); + DB_Transaction_Start(&conn); + + say("Executing Statement (array size: %d; starting from row %d, %d by %d)...\n", arraySize, from, count, count); + TOOL_Counter_Start(counter, 0); + + while (from < arraySize) { + if (from + count > arraySize) + count = arraySize - from; + + rc = DB_Statement_Execute(&st, from, count, &res); + totalRowsProcessed += res.rowsProcessed; + + if (DB_ERROR(rc)) + break; + + from += count; + } + + /* End transaction */ + TOOL_Counter_Stop(counter, 0); + + if (DB_ERROR(rc)) { + say("Error: %s", DB_Error_Message_Get()); + say("%d rows processed (error at iteration %d)\n", totalRowsProcessed, res.errorIteration); + } + else { + say("OK, %d rows processed in %ld ms\n", totalRowsProcessed, TOOL_Counter_Get(counter, 0)); + } + + /*DB_Transaction_Rollback(&conn);*/ + say("Committing Transaction\n\n"); + DB_Transaction_Commit(&conn); + + if (req) + free(req); + TOOL_Counter_Free(counter); + + DB_Disconnect(&conn); + DB_Library_Close(); + return 0; +} + + +/** + * Affichage sur la sortie standard. + */ +void say(const char *format, ...) { + char buffer[512]; + va_list v; + + va_start(v, format); + vsnprintf(buffer, sizeof(buffer), format, v); + fprintf (stdout, "%s", buffer); + + va_end(v); +} + + +/** + * Arguments. + */ +void parseArgs(int argc, char **argv) { + int i = 0; + + for (i = 1; i < argc; ++i) { + if (! strcasecmp(argv[i], "--debuglevel")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + debugLevel = atoi(argv[i]); + DB_Debug_Level_Set(debugLevel); + } + else if (! strcasecmp(argv[i], "--from")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + from = atoi(argv[i]); + } + else if (! strcasecmp(argv[i], "--count")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + count = atoi(argv[i]); + } + else if (! strcasecmp(argv[i], "--size")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + arraySize = atoi(argv[i]); + } + else if (! strcasecmp(argv[i], "--baseIndex")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + baseIndex = atoi(argv[i]); + } + else if (! strcasecmp(argv[i], "--req")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + req = strdup(argv[i]); + } + else if (! strcasecmp(argv[i], "--db")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + splitDBSpec(argv[i], &login, &pwd, &server); + } + else if (! strcasecmp(argv[i], "--help") || ! strcasecmp(argv[i], "-h") || ! strcasecmp(argv[i], "-?")) { + usage(argv); + exit(1); + } + else { + usage(argv); + exit(1); + } + } +} + + +/** + * Usage. + */ +void usage(char **argv) { + char *b = basename(argv[0]); + printf(USAGE, b, b, b); +} + + +/** + * Initializes host variables. + * Associates an 'hostvar' with a type, size, array of values and array of indicators. + */ +int setupHostVars(void) { + + if (DB_HostVar_Setup(&hv1, DBD_INTEGER, 0, dynInt1, dynIndic1) != DBS_OK || + DB_HostVar_Setup(&hv2, DBD_STRING, 20, dynBuf, dynIndic2) != DBS_OK || + DB_HostVar_Setup(&hv3, DBD_INTEGER, 0, dynInt3, dynIndic3) != DBS_OK) { + + say("Error: %s\n", DB_Error_Message_Get()); + return FALSE; + } + return TRUE; +} + + +/** + * Setup arrays of values and indicators. + * (IN) n: Rows count to allocate for each array. + */ +void setupData(int n) { + int i; + + dynInt1 = malloc(n * sizeof(int)); + dynBuf = malloc((unsigned) n * 20); + dynInt3 = malloc(n * sizeof(int)); + + dynIndic1 = malloc(n * sizeof(int)); + dynIndic2 = malloc(n * sizeof(int)); + dynIndic3 = malloc(n * sizeof(int)); + + for (i = 0; i < n; i++) { + int x = i + baseIndex; + dynIndic1[i] = 0; + dynIndic2[i] = 0; + dynIndic3[i] = 0; + + dynInt1[i] = x; + sprintf(dynBuf+20*i, "A%d", x); + dynInt3[i] = 100+x; + } +} + + +/** + * Splits a database specification in the format "login/password@server" into its + * basic components 'login', 'password' and 'server'. + * Note that the initial 'spec' string may be altered. + */ +void splitDBSpec(char *spec, const char **login_, const char **pwd_, const char **server_) { + char *p = NULL; + + *login_ = spec; + p = strchr(spec, '/'); + if (p == NULL) + return; + + *p = 0; + *pwd_ = ++p; + + p = strchr(p, '@'); + if (p == NULL) + return; + *p = 0; + *server_ = ++p; +} diff --git a/utils/testSelect.c b/utils/testSelect.c new file mode 100644 index 0000000..7a5541c --- /dev/null +++ b/utils/testSelect.c @@ -0,0 +1,272 @@ +/*---------------------------------------------------------------------------------*/ +/* $RCSfile: testSelect.c,v $ */ +/*---------------------------------------------------------------------------------*/ +/* $Revision: 1.1 $ */ +/* $Name: $ */ +/* $Date: 2006/02/28 23:28:21 $ */ +/* $Author: agibert $ */ +/*---------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------*/ +/* This file is part of LibDataBase */ +/* */ +/* LibDataBase is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU Lesser General Public Licence as published by */ +/* the Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* LibDataBase is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with LibDataBase; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/*---------------------------------------------------------------------------------*/ + + + + + +#include +#include +#include + +#include +#include + +int main(int argc, char **argv); +int parseArgs(int argc, char **argv, char **login, char **pwd, char **base, char **sql, int *tp); +int sqlAnalyse(const char *sql); +int execQuery(DBT_Connection *conn, const char *sql, int tp); + +int main(int argc, char **argv) { + DBT_Connection conn; + DBT_Status rco; + char *login = NULL; + char *pwd = NULL; + char *base = NULL; + char *sql = NULL; + int tp = 1; + int rc = 1; + + if (parseArgs(argc, argv, &login, &pwd, &base, &sql, &tp)) { + BDM_Trace(0, "testSelect", "main", "Usage : %s options\n\n\ +Les options sont :\n\ + -sql ou --sql-query : requête à exécuter\n\ + -ps ou --packet-size : nombre de lignes par fetch (1 par défaut)\n\ + -db ou --db-connection : paramètres de connexion à Oracle\n\ + --debug : niveau de trace", basename(argv[0])); + return rc; + } + + /* connexion Oracle */ + DB_Library_Open(0); + memset(&conn, 0, sizeof(conn)); + while (1) { + rco = DB_Connect(&conn, login, pwd, base); + if (DB_ERROR(rco)) break; + while (1) { + if (execQuery(&conn, sql, tp)) break; + if (1) break; + } + DB_Disconnect(&conn); + rc = 0; + if (1) break; + } + + DB_Library_Close(); + + return rc; +} + +int parseArgs(int argc, char **argv, char **login, char **pwd, char **base, char **sql, int *tp) { + int i = 1; + + while (i < argc) { + if (!strcmp(argv[i], "-sql") || !strcmp(argv[i], "--sql-query")) { + if (++i == argc) { + BDM_Trace(0, "testSelect", "parseArgs", "Paramètre attendu après %s", argv[i - 1]); + return 1; + } + if (*sql) BDM_Trace(1, "testSelect", "parseArgs", "Une seule requête SQL attendue : seule la dernière est prise en compte"); + *sql = argv[i++]; + } else if (!strcmp(argv[i], "-ps") || !strcmp(argv[i], "--packet-size")) { + if (++i == argc) { + BDM_Trace(0, "testSelect", "parseArgs", "Paramètre attendu après %s", argv[i - 1]); + return 1; + } + if (atoi(argv[i]) < 1) { + BDM_Trace(0, "testSelect", "parseArgs", "Le nombre de lignes par fetch doit être > 0"); + return 1; + } + *tp = atoi(argv[i++]); + } else if (!strcmp(argv[i], "-db") || !strcmp(argv[i], "--db-connection")) { + char *start, *end; + if (++i == argc) { + BDM_Trace(0, "testSelect", "parseArgs", "Paramètre attendu après %s", argv[i - 1]); + return 1; + } + start = argv[i++]; + end = start; + while (*end && *end != '/') ++end; + if (!*end) return 1; + *end = '\0'; + *login = start; + start = ++end; + while (*end && *end != '@') ++end; + *pwd = start; + if (*end == '@') { + *end = '\0'; + *base = end + 1; + } + } else if (!strncmp(argv[i], "--debug", 7)) { + int level; + level = atoi(argv[i++] + 7); + if (level < 0) { + BDM_Trace(0, "testSelect", "parseArgs", "Le niveau de trace doit être fixé par --debug : --debug2, --debug5, etc"); + return 1; + } + BDM_Trace_SetLevel(level, "testSelect"); + } else { + BDM_Trace(0, "testSelect", "parseArgs", "Option %s non reconnue", argv[i]); + return 1; + } + } + + if (!*sql) { + BDM_Trace(0, "testSelect", "parseArgs", "Option -sql obligatoire"); + return 1; + } + if (!*login) { + BDM_Trace(0, "testSelect", "parseArgs", "Option -db obligatoire"); + return 1; + } + + return 0; +} + +int sqlAnalyse(const char *sql) { + int colCount = 0; + int par = 0; + const char *ptr; + const char *sep = "() \t\n\r"; + + BDM_Trace(3, "testSelect", "sqlAnalyse", "Analyse de \"%s\"", sql); + + /* ptr : début de la 1ère colonne */ + ptr = sql; + while (*ptr && strchr(sep, *ptr) == NULL) ++ptr; + + while (*ptr) { + if (*ptr == '(') { + ++par; + ++ptr; + continue; + } + if (*ptr == ')') { + if (!par) { + BDM_Trace(0, "testSelect", "sqlAnalyse", ") rencontré sans ( : %s", ptr); + return 0; + } + --par; + ++ptr; + continue; + } + if (*ptr == ',' && !par) { + ++colCount; + ++ptr; + continue; + } + if (strchr(sep, *ptr)) { + char tmp[6]; + int i; + strncpy(tmp, ptr + 1, 5); + tmp[5] = '\0'; + for (i = 0; i < 5; ++i) + if (tmp[i] >= 'A' && tmp[i] <= 'Z') tmp[i] += 'a' - 'A'; + if (!strcmp(tmp, "from ")) { + ++colCount; + break; + } + ++ptr; + continue; + } + ++ptr; + } + + if (!*ptr) { + BDM_Trace(0, "testSelect", "sqlAnalyse", "FROM non trouvé dans la requête"); + return 0; + } + + if (!colCount) { + BDM_Trace(0, "testSelect", "sqlAnalyse", "Aucune colonne n'a été identifiée"); + return 0; + } + + BDM_Trace(2, "testSelect", "sqlAnalyse", "La requête devrait retourner %d colonnes", colCount); + + return colCount; +} + +int execQuery(DBT_Connection *conn, const char *sql, int tp) { + int colCount = sqlAnalyse(sql); + int idx; + DBT_HostVar *hv = NULL; + char *data = NULL; + const int max = 100 + 1; + DBT_Indicator *inull = NULL; + DBT_Status rc = DBS_OK; + DBT_Statement st; + DBT_Result res; + + /* nombre de colonnes */ + if (colCount == 0) return 1; + + while (1) { + BDM_Trace(3, "testSelect", "execQuery", "Préparation des variables pour %d colonnes x %d lignes", colCount, tp); + /* HostVar */ + hv = (DBT_HostVar *)malloc(sizeof(DBT_HostVar) * colCount); + memset(hv, 0, sizeof(DBT_HostVar) * colCount); + /* data */ + data = (char *)malloc((size_t)tp * max * colCount); + /* inull */ + inull = (DBT_Indicator *)malloc(sizeof(DBT_Indicator) * colCount * tp); + for (idx = 0; !DB_ERROR(rc) && idx < colCount; ++idx) + rc = DB_HostVar_Setup(&hv[idx], DBD_STRING, max, data + tp * max * idx, &inull[tp * idx]); + if (DB_ERROR(rc)) break; + rc = DB_Statement_Init(conn, &st); + if (DB_ERROR(rc)) break; + rc = DB_Statement_Prepare(&st, sql); + if (DB_ERROR(rc)) break; + for (idx = 0; !DB_ERROR(rc) && idx < colCount; ++idx) + rc = DB_Statement_DefineVar(&st, tp, idx + 1, &hv[idx]); + if (DB_ERROR(rc)) break; + BDM_Trace(3, "testSelect", "execQuery", "Variables initialisées"); + + rc = DB_Statement_ExecuteSelect(&st, &res); + while (rc == DBS_OK) { + int nl; + BDM_Trace(3, "testSelect", "execQuery", "Lecture de %d enregistrements", res.rowsProcessed); + for (nl = 0; nl < res.rowsProcessed; ++nl) { + for (idx = 0; idx < colCount; ++idx) + printf("%s%s", idx ? ";" : "", inull[idx * tp + nl] ? "" : data + max * (idx * tp + nl)); + printf("\n"); + } + if (st.isEOF) break; + rc = DB_Statement_Fetch(&st, &res); + } + DB_Statement_Close(&st); + if (1) break; + } + + free(inull); + free(data); + free(hv); + + if (DB_ERROR(rc)) return 1; + + return 0; +} diff --git a/utils/testUpdate.c b/utils/testUpdate.c new file mode 100644 index 0000000..29c855a --- /dev/null +++ b/utils/testUpdate.c @@ -0,0 +1,236 @@ +/*---------------------------------------------------------------------------------*/ +/* $RCSfile: testUpdate.c,v $ */ +/*---------------------------------------------------------------------------------*/ +/* $Revision: 1.1 $ */ +/* $Name: $ */ +/* $Date: 2006/02/28 23:28:21 $ */ +/* $Author: agibert $ */ +/*---------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------*/ +/* This file is part of LibDataBase */ +/* */ +/* LibDataBase is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU Lesser General Public Licence as published by */ +/* the Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* LibDataBase is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with LibDataBase; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/*---------------------------------------------------------------------------------*/ + + + + + +#include +#include + +#include +#include "../lib/database.h" + + +/* Globals */ +const char *USAGE = "Usage: %s --req --db \n\ +Executes an UPDATE, DELETE or any request that takes no variable argument nor produces\n\ +any output value (other than the number of rows processed).\n\ +Ex: _ \"CREATE TABLE tableX (col1 NUMBER(5) PRIMARY KEY, col2 VARCHAR2(10))\";\n\ + _ \"INSERT INTO tableX VALUES (1, 'A')\";\n\ + _ \"UPDATE tableX SET col1=col1+1, col2='ABC' WHERE col1 < 10\";\n\ + _ \"DELETE FROM tableX WHERE col2=1\";\n\ + _ \"DROP TABLE tableX\".\n\ +\n\ +Command line arguments:\n\ + --req The SQL request.\n\ + --db Database on which to operate. Format: \"login/pwd@server\"\n"; + + +extern int strcasecmp(const char *, const char *); +extern char *strdup(const char *); +void parseArgs(int argc, char **argv); +void usage(char **argv); +void say (const char *format, ...); +void splitDBSpec(char *spec, const char **login, const char **pwd, const char **server); + +int debugLevel = 0; +char *req = NULL; +const char *login = ""; +const char *pwd = ""; +const char *server = ""; +DBT_Connection conn; +DBT_Statement st; +DBT_Result res; + + +/** + * Main. + */ +int main(int argc, char **argv) { + DBT_Status rc; + TOOLT_Counter *counter = NULL; + + + /* Parse arguments */ + parseArgs(argc, argv); + if (req == NULL) { + usage(argv); + return 1; + } + + counter = TOOL_Counter_Alloc(1); + + rc = DB_Library_Open(DBD_DEBUG | DBD_ERRMSG); + if (DB_ERROR(rc)) { + printf("Error: Could not open library (%s)\n", DB_Error_Message_Get()); + return 1; + } + + + /* Connect to Database */ + say("Connecting to %s/%s@%s...\n", login, pwd, server); + rc = DB_Connect(&conn, login, pwd, server); + if (DB_ERROR(rc)) { + printf("Error: Could not connect (%s)\n", DB_Error_Message_Get()); + return 1; + } + + /* Init statement */ + rc = DB_Statement_Init(&conn, &st); + if (DB_ERROR(rc)) { + printf("Error: Could not init statement (err %d)\n", rc); + return 1; + } + + say("Preparing statement for query: '%s'\n", req); + rc = DB_Statement_Prepare(&st, req); + if (DB_ERROR(rc)) { + printf("Error: Could not prepare statement (err %d)\n", rc); + return 1; + } + + /* Start transaction */ + say("Start Transaction\n"); + DB_Transaction_Start(&conn); + + say("\nExecuting Statement...\n"); + TOOL_Counter_Start(counter, 0); + rc = DB_Statement_Execute(&st, 0, 1, &res); + TOOL_Counter_Stop(counter, 0); + + if (DB_ERROR(rc)) { + say("Error: %s", DB_Error_Message_Get()); + say("%d rows processed (error at iteration %d)\n", res.rowsProcessed, res.errorIteration); + } + else { + say("OK, %d rows processed in %ld ms\n", res.rowsProcessed, TOOL_Counter_Get(counter, 0)); + } + + + /*DB_Transaction_Rollback(&conn);*/ + + say("\nCommitting Transaction\n"); + DB_Transaction_Commit(&conn); + + if (req) + free(req); + TOOL_Counter_Free(counter); + + DB_Disconnect(&conn); + DB_Library_Close(); + say("End.\n"); + return 0; +} + + +/** + * Affichage sur la sortie standard. + */ +void say(const char *format, ...) { + char buffer[512]; + va_list v; + + va_start(v, format); + vsnprintf(buffer, sizeof(buffer), format, v); + fprintf (stdout, "%s", buffer); + + va_end(v); +} + + +/** + * Arguments. + */ +void parseArgs(int argc, char **argv) { + int i = 0; + + for (i = 1; i < argc; ++i) { + if (! strcasecmp(argv[i], "--debuglevel")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + debugLevel = atoi(argv[i]); + DB_Debug_Level_Set(debugLevel); + } + else if (! strcasecmp(argv[i], "--req")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + req = strdup(argv[i]); + } + else if (! strcasecmp(argv[i], "--db")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + splitDBSpec(argv[i], &login, &pwd, &server); + } + else if (! strcasecmp(argv[i], "--help") || ! strcasecmp(argv[i], "-h") || ! strcasecmp(argv[i], "-?")) { + usage(argv); + exit(1); + } + else { + usage(argv); + exit(1); + } + } +} + + +/** + * Usage. + */ +void usage(char **argv) { + printf(USAGE, basename(argv[0])); +} + + +/** + * Splits a database specification in the format "login/password@server" into its + * basic components 'login', 'password' and 'server'. + * Note that the initial 'spec' string may be altered. + */ +void splitDBSpec(char *spec, const char **login_, const char **pwd_, const char **server_) { + char *p = NULL; + + *login_ = spec; + p = strchr(spec, '/'); + if (p == NULL) + return; + + *p = 0; + *pwd_ = ++p; + + p = strchr(p, '@'); + if (p == NULL) + return; + *p = 0; + *server_ = ++p; +} diff --git a/utils/testUpdateArray.c b/utils/testUpdateArray.c new file mode 100644 index 0000000..ae5e4aa --- /dev/null +++ b/utils/testUpdateArray.c @@ -0,0 +1,338 @@ +/*---------------------------------------------------------------------------------*/ +/* $RCSfile: testUpdateArray.c,v $ */ +/*---------------------------------------------------------------------------------*/ +/* $Revision: 1.1 $ */ +/* $Name: $ */ +/* $Date: 2006/02/28 23:28:21 $ */ +/* $Author: agibert $ */ +/*---------------------------------------------------------------------------------*/ + +/*---------------------------------------------------------------------------------*/ +/* This file is part of LibDataBase */ +/* */ +/* LibDataBase is free software; you can redistribute it and/or modify */ +/* it under the terms of the GNU Lesser General Public Licence as published by */ +/* the Free Software Foundation; either version 2.1 of the License, or */ +/* (at your option) any later version. */ +/* */ +/* LibDataBase is distributed in the hope that it will be useful, */ +/* but WITHOUT ANY WARRANTY; without even the implied warranty of */ +/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */ +/* GNU Lesser General Public License for more details. */ +/* */ +/* You should have received a copy of the GNU Lesser General Public License */ +/* along with LibDataBase; if not, write to the Free Software */ +/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +/*---------------------------------------------------------------------------------*/ + + + + + +#include +#include + +#include +#include "../lib/database.h" + + +/* Globals */ +const char *USAGE = "Usage: %s --db [--req ]\n\ +Executes an UPDATE request using an array as comparison values. The request is:\n\ +\"update dummy set c1=:1 where c3=:2\".\n\ +The table 'dummy' should have the following format:\n\ +\"CREATE TABLE dummy (c1 NUMBER(35) primary key, c2 VARCHAR2(16), c3 NUMBER(10))\".\n\ +Try with the following data:\n\ +1 ABC 100\n\ +2 ABC 101\n\ +3 ABC 102\n\ +4 ABC 103\n\ +5 ABC 104\n\ +\n\ +Command line arguments:\n\ + --req Another SQL request, if you whish - Be careful that there are only 2 placeholders (:1 and :2).\n\ + --db Database on which to operate. Format: \"login/pwd@server\"\n"; + + +extern int strcasecmp(const char *, const char *); +extern char *strdup(const char *); +void parseArgs(int argc, char **argv); +void usage(char **argv); +void say (const char *format, ...); +void splitDBSpec(char *spec, const char **login, const char **pwd, const char **server); +int setupHostVars(void); +void setupData(int n); + + +int debugLevel = 0; +int arraySize = 3; +int baseIndex = 0; +char *req = NULL; +const char *login = ""; +const char *pwd = ""; +const char *server = ""; +DBT_Connection conn; +DBT_Statement st; +DBT_Result res; + +DBT_HostVar hv1; +DBT_HostVar hv2; +DBT_HostVar hv3; + +int *dynInt1 = NULL; +int *dynInt2 = NULL; +int *dynInt3 = NULL; + +DBT_Indicator *dynIndic1 = NULL; +DBT_Indicator *dynIndic2 = NULL; +DBT_Indicator *dynIndic3 = NULL; + + +/** + * Main. + */ +int main(int argc, char **argv) { + DBT_Status rc; + TOOLT_Counter *counter = NULL; + + + /* Parse arguments */ + parseArgs(argc, argv); + if (req == NULL) { + /*req = strdup("update dummy set c1=:1 where c3=:2");*/ + req = strdup("update dummy set c1=:1 where :2 = 0 and c3=:3"); + } + + counter = TOOL_Counter_Alloc(1); + + rc = DB_Library_Open(DBD_DEBUG | DBD_ERRMSG); + if (DB_ERROR(rc)) { + printf("Error: Could not open library (%s)\n", DB_Error_Message_Get()); + return 1; + } + + + /* Connect to Database */ + say("Connecting to %s/%s@%s...\n", login, pwd, server); + rc = DB_Connect(&conn, login, pwd, server); + if (DB_ERROR(rc)) { + printf("Error: Could not connect (%s)\n", DB_Error_Message_Get()); + return 1; + } + + + /* Init data that are going to be inserted */ + say("Setup data and HostVars\n"); + setupData(arraySize); + if (setupHostVars() == FALSE) + return 1; + + + /* Init statement */ + rc = DB_Statement_Init(&conn, &st); + if (DB_ERROR(rc)) { + printf("Error: Could not init statement (err %d)\n", rc); + return 1; + } + + say("Preparing statement for query: '%s'\n", req); + rc = DB_Statement_Prepare(&st, req); + if (DB_ERROR(rc)) { + printf("Error: Could not prepare statement (err %d)\n", rc); + return 1; + } + + say("Bind Vars\n"); + rc = DB_Statement_BindVars(&st, arraySize, &hv1, &hv2, &hv3, NULL); + if (DB_ERROR(rc)) { + printf("Error: Could not bind vars (%s)\n", DB_Error_Message_Get()); + return 1; + } + + + /* Start transaction */ + say("Start Transaction\n"); + DB_Transaction_Start(&conn); + + say("\nExecuting Statement...\n"); + TOOL_Counter_Start(counter, 0); + rc = DB_Statement_Execute(&st, 0, 3, &res); + TOOL_Counter_Stop(counter, 0); + + if (DB_ERROR(rc)) { + say("Error: %s", DB_Error_Message_Get()); + say("%d rows processed (error at iteration %d)\n", res.rowsProcessed, res.errorIteration); + } + else { + say("OK, %d rows processed in %ld ms\n", res.rowsProcessed, TOOL_Counter_Get(counter, 0)); + } + + + /*DB_Transaction_Rollback(&conn);*/ + + say("\nCommitting Transaction\n"); + DB_Transaction_Commit(&conn); + + if (req) + free(req); + TOOL_Counter_Free(counter); + + DB_Disconnect(&conn); + DB_Library_Close(); + say("End.\n"); + return 0; +} + + +/** + * Affichage sur la sortie standard. + */ +void say(const char *format, ...) { + char buffer[512]; + va_list v; + + va_start(v, format); + vsnprintf(buffer, sizeof(buffer), format, v); + fprintf (stdout, "%s", buffer); + + va_end(v); +} + + +/** + * Arguments. + */ +void parseArgs(int argc, char **argv) { + int i = 0; + + for (i = 1; i < argc; ++i) { + if (! strcasecmp(argv[i], "--debuglevel")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + debugLevel = atoi(argv[i]); + DB_Debug_Level_Set(debugLevel); + } + else if (! strcasecmp(argv[i], "--req")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + req = strdup(argv[i]); + } + else if (! strcasecmp(argv[i], "--db")) { + if (++i >= argc) { + usage(argv); + exit(1); + } + splitDBSpec(argv[i], &login, &pwd, &server); + } + else if (! strcasecmp(argv[i], "--help") || ! strcasecmp(argv[i], "-h") || ! strcasecmp(argv[i], "-?")) { + usage(argv); + exit(1); + } + else { + usage(argv); + exit(1); + } + } +} + + +/** + * Usage. + */ +void usage(char **argv) { + printf(USAGE, basename(argv[0])); +} + + +/** + * Splits a database specification in the format "login/password@server" into its + * basic components 'login', 'password' and 'server'. + * Note that the initial 'spec' string may be altered. + */ +void splitDBSpec(char *spec, const char **login_, const char **pwd_, const char **server_) { + char *p = NULL; + + *login_ = spec; + p = strchr(spec, '/'); + if (p == NULL) + return; + + *p = 0; + *pwd_ = ++p; + + p = strchr(p, '@'); + if (p == NULL) + return; + *p = 0; + *server_ = ++p; +} + + + +/** + * Initializes host variables. + * Associates an 'hostvar' with a type, size, array of values and array of indicators. + */ +int setupHostVars(void) { + + if (DB_HostVar_Setup(&hv1, DBD_INTEGER, 0, dynInt1, dynIndic1) != DBS_OK || + DB_HostVar_Setup(&hv2, DBD_INTEGER, 0, dynInt2, dynIndic2) != DBS_OK || + DB_HostVar_Setup(&hv3, DBD_INTEGER, 0, dynInt3, dynIndic3) != DBS_OK) { + + say("Error: %s\n", DB_Error_Message_Get()); + return FALSE; + } + return TRUE; +} + + +/** + * Setup arrays of values and indicators. + * (IN) n: Rows count to allocate for each array. + */ +void setupData(int n) { + int i; + + dynInt1 = malloc(n * sizeof(int)); + dynInt2 = malloc(n * sizeof(int)); + dynInt3 = malloc(n * sizeof(int)); + + dynIndic1 = malloc(n * sizeof(int)); + dynIndic2 = malloc(n * sizeof(int)); + dynIndic3 = malloc(n * sizeof(int)); + + /* Zeroe indicators */ + for (i = 0; i < n; i++) { + dynIndic1[i] = 0; + dynIndic2[i] = 0; + dynIndic3[i] = 0; + } + + /* These are the places to update : set c1=2001 where c3=101, etc. */ + /* + dynInt1[0] = 2001; + dynInt3[0] = 101; + + dynInt1[1] = 2002; + dynInt3[1] = 102; + + dynInt1[2] = 2003; + dynInt3[2] = 103; + */ + + dynInt1[0] = 91; + dynInt2[0] = 1; + dynInt3[0] = 101; + + dynInt1[1] = 92; + dynInt2[1] = 0; + dynInt3[1] = 101; + + dynInt1[2] = 93; + dynInt2[2] = 0; + dynInt3[2] = 103; +}