Mercurial > hg > orthanc-postgresql
changeset 0:1d7c4b961831
initial release
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AUTHORS Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,13 @@ +PostgreSQL plugin for Orthanc +============================= + + +Authors +------- + +* Sebastien Jodogne <s.jodogne@gmail.com> + Department of Medical Physics + University Hospital of Liege + Belgium + + Overall design and lead developer.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/CMakeLists.txt Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,136 @@ +# Orthanc - A Lightweight, RESTful DICOM Store +# Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics +# Department, University Hospital of Liege, Belgium +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 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 +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +cmake_minimum_required(VERSION 2.8) + +project(OrthancPostgreSQL) + +# Parameters of the build +set(STATIC_BUILD OFF CACHE BOOL "Static build of the third-party libraries (necessary for Windows)") +set(ALLOW_DOWNLOADS OFF CACHE BOOL "Allow CMake to download packages") + +# Advanced parameters to fine-tune linking against system libraries +set(USE_SYSTEM_JSONCPP ON CACHE BOOL "Use the system version of JsonCpp") +set(USE_SYSTEM_BOOST ON CACHE BOOL "Use the system version of Boost") +set(USE_SYSTEM_GOOGLE_TEST ON CACHE BOOL "Use the system version of Google Test") +set(USE_SYSTEM_LIBPQ ON CACHE BOOL "Use the system version of the PostgreSQL client library") + +# Distribution-specific settings +set(USE_GTEST_DEBIAN_SOURCE_PACKAGE OFF CACHE BOOL "Use the sources of Google Test shipped with libgtest-dev (Debian only)") +mark_as_advanced(USE_GTEST_DEBIAN_SOURCE_PACKAGE) + +# Force static build when cross-compiling +if (CMAKE_CROSSCOMPILING) + set(STATIC_BUILD ON) +endif() + +if (${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + link_libraries(uuid) + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pthread") +elseif (${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + link_libraries(rpcrt4 ws2_32 secur32) + if (CMAKE_COMPILER_IS_GNUCXX) + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-libgcc -static-libstdc++") + endif() +endif () + +if (CMAKE_COMPILER_IS_GNUCXX) + SET(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--version-script=${CMAKE_SOURCE_DIR}/Resources/VersionScript.map -Wl,--no-undefined") +endif() + + +include(CheckIncludeFiles) +include(CheckIncludeFileCXX) +include(CheckLibraryExists) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/AutoGeneratedCode.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/DownloadPackage.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/BoostConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/PostgreSQLConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/JsonCppConfiguration.cmake) +include(${CMAKE_SOURCE_DIR}/Resources/CMake/GoogleTestConfiguration.cmake) + + +# Check that the Orthanc SDK headers are available or download them +if (STATIC_BUILD) + set(ORTHANC_SDK_URL "http://orthanc.googlecode.com/hg") # TODO use 0.8.6 release + file(MAKE_DIRECTORY ${AUTOGENERATED_DIR}/orthanc) + file(DOWNLOAD "${ORTHANC_SDK_URL}/Plugins/Include/OrthancCPlugin.h" + "${AUTOGENERATED_DIR}/orthanc/OrthancCPlugin.h" SHOW_PROGRESS) + file(DOWNLOAD "${ORTHANC_SDK_URL}/Plugins/Include/OrthancCDatabasePlugin.h" + "${AUTOGENERATED_DIR}/orthanc/OrthancCDatabasePlugin.h" SHOW_PROGRESS) + file(DOWNLOAD "${ORTHANC_SDK_URL}/Plugins/Include/OrthancCppDatabasePlugin.h" + "${AUTOGENERATED_DIR}/orthanc/OrthancCppDatabasePlugin.h" SHOW_PROGRESS) + if (${MSVC}) + add_definitions(-D_CRT_SECURE_NO_WARNINGS=1) + file(DOWNLOAD "${ORTHANC_SDK_URL}/Resources/ThirdParty/VisualStudio/stdint.h" + "${AUTOGENERATED_DIR}/stdint.h" SHOW_PROGRESS) + endif() +else () + CHECK_INCLUDE_FILE_CXX(orthanc/OrthancCppDatabasePlugin.h HAVE_ORTHANC_H) + if (NOT HAVE_ORTHANC_H) + message(FATAL_ERROR "Please install the headers of the Orthanc plugins SDK") + endif() +endif() + + +# Embed the SQL files into the binaries +EmbedResources( + GLOBAL_PROPERTIES ${CMAKE_CURRENT_SOURCE_DIR}/Core/GlobalProperties.sql + POSTGRESQL_PREPARE ${CMAKE_CURRENT_SOURCE_DIR}/IndexPlugin/PostgreSQLPrepare.sql + POSTGRESQL_UPSERTS ${CMAKE_CURRENT_SOURCE_DIR}/IndexPlugin/PostgreSQLUpserts.sql + ) + +set(CORE_SOURCES + ${CMAKE_SOURCE_DIR}/Core/PostgreSQLConnection.cpp + ${CMAKE_SOURCE_DIR}/Core/PostgreSQLLargeObject.cpp + ${CMAKE_SOURCE_DIR}/Core/PostgreSQLResult.cpp + ${CMAKE_SOURCE_DIR}/Core/PostgreSQLStatement.cpp + ${CMAKE_SOURCE_DIR}/Core/PostgreSQLTransaction.cpp + ${CMAKE_SOURCE_DIR}/Core/Configuration.cpp + ${CMAKE_SOURCE_DIR}/Core/GlobalProperties.cpp + + ${LIBPQ_SOURCES} + ${BOOST_SOURCES} + ${JSONCPP_SOURCES} + ${AUTOGENERATED_SOURCES} + ) + +add_library(OrthancPostgreSQLStorage + SHARED + ${CORE_SOURCES} + ${CMAKE_SOURCE_DIR}/StoragePlugin/PostgreSQLStorageArea.cpp + ${CMAKE_SOURCE_DIR}/StoragePlugin/Plugin.cpp + ) + +add_library(OrthancPostgreSQLIndex + SHARED + ${CORE_SOURCES} + ${AUTOGENERATED_SOURCES} + ${CMAKE_SOURCE_DIR}/IndexPlugin/PostgreSQLWrapper.cpp + ${CMAKE_SOURCE_DIR}/IndexPlugin/Plugin.cpp + ) + +add_executable(UnitTests + ${CORE_SOURCES} + ${GTEST_SOURCES} + ${CMAKE_SOURCE_DIR}/IndexPlugin/PostgreSQLWrapper.cpp + ${CMAKE_SOURCE_DIR}/StoragePlugin/PostgreSQLStorageArea.cpp + ${CMAKE_SOURCE_DIR}/UnitTestsSources/UnitTestsMain.cpp + ${CMAKE_SOURCE_DIR}/UnitTestsSources/PostgreSQLTests.cpp + ${CMAKE_SOURCE_DIR}/UnitTestsSources/PostgreSQLWrapperTests.cpp + )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/COPYING Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/> + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + 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 +them 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. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey 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; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If 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 convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero 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 that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + 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. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +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. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + 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 +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + <one line to give the program's name and a brief idea of what it does.> + Copyright (C) <year> <name of author> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published by + the Free Software Foundation, either version 3 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 Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +<http://www.gnu.org/licenses/>.
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/Configuration.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,178 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "Configuration.h" + +#include "PostgreSQLException.h" + +#include <fstream> +#include <json/reader.h> +#include <memory> + + +// For UUID generation +extern "C" +{ +#ifdef WIN32 +#include <rpc.h> +#else +#include <uuid/uuid.h> +#endif +} + + +namespace OrthancPlugins +{ + bool ReadConfiguration(Json::Value& configuration, + OrthancPluginContext* context) + { + std::string path; + + { + char* pathTmp = OrthancPluginGetConfigurationPath(context); + if (pathTmp == NULL) + { + OrthancPluginLogError(context, "No configuration file is provided"); + return false; + } + + path = std::string(pathTmp); + + OrthancPluginFreeString(context, pathTmp); + } + + std::ifstream f(path.c_str()); + + Json::Reader reader; + if (!reader.parse(f, configuration) || + configuration.type() != Json::objectValue) + { + std::string s = "Unable to parse the configuration file: " + std::string(path); + OrthancPluginLogError(context, s.c_str()); + return false; + } + + return true; + } + + + std::string GetStringValue(const Json::Value& configuration, + const std::string& key, + const std::string& defaultValue) + { + if (configuration.type() != Json::objectValue || + !configuration.isMember(key) || + configuration[key].type() != Json::stringValue) + { + return defaultValue; + } + else + { + return configuration[key].asString(); + } + } + + + int GetIntegerValue(const Json::Value& configuration, + const std::string& key, + int defaultValue) + { + if (configuration.type() != Json::objectValue || + !configuration.isMember(key) || + configuration[key].type() != Json::intValue) + { + return defaultValue; + } + else + { + return configuration[key].asInt(); + } + } + + + PostgreSQLConnection* CreateConnection(OrthancPluginContext* context) + { + Json::Value configuration; + if (!ReadConfiguration(configuration, context)) + { + return NULL; + } + + std::auto_ptr<PostgreSQLConnection> connection(new PostgreSQLConnection); + + if (configuration.isMember("PostgreSQL")) + { + Json::Value c = configuration["PostgreSQL"]; + connection->SetHost(GetStringValue(c, "Host", "localhost")); + connection->SetPortNumber(GetIntegerValue(c, "Port", 5432)); + connection->SetDatabase(GetStringValue(c, "Database", "orthanc")); + connection->SetUsername(GetStringValue(c, "Username", "orthanc")); + connection->SetPassword(GetStringValue(c, "Password", "orthanc")); + } + + connection->Open(); + + return connection.release(); + } + + + std::string GenerateUuid() + { +#ifdef WIN32 + UUID uuid; + UuidCreate ( &uuid ); + + unsigned char * str; + UuidToStringA ( &uuid, &str ); + + std::string s( ( char* ) str ); + + RpcStringFreeA ( &str ); +#else + uuid_t uuid; + uuid_generate_random ( uuid ); + char s[37]; + uuid_unparse ( uuid, s ); +#endif + return s; + } + + + bool IsFlagInCommandLineArguments(OrthancPluginContext* context, + const std::string& flag) + { + uint32_t count = OrthancPluginGetCommandLineArgumentsCount(context); + + for (uint32_t i = 0; i < count; i++) + { + char* tmp = OrthancPluginGetCommandLineArgument(context, i); + std::string arg(tmp); + OrthancPluginFreeString(context, tmp); + + if (arg == flag) + { + return true; + } + } + + return false; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/Configuration.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,56 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "PostgreSQLConnection.h" + +#include <json/value.h> +#include <orthanc/OrthancCPlugin.h> + + +// This comes from the Orthanc source code +static const int32_t GlobalProperty_DatabaseSchemaVersion = 1; + +static const int32_t GlobalProperty_IndexLock = 1024; +static const int32_t GlobalProperty_StorageLock = 1025; + +static const std::string FLAG_UNLOCK = "--unlock"; + +namespace OrthancPlugins +{ + bool ReadConfiguration(Json::Value& configuration, + OrthancPluginContext* context); + + std::string GetStringValue(const Json::Value& configuration, + const std::string& key, + const std::string& defaultValue); + + int GetIntegerValue(const Json::Value& configuration, + const std::string& key, + int defaultValue); + + PostgreSQLConnection* CreateConnection(OrthancPluginContext* context); + + std::string GenerateUuid(); + + bool IsFlagInCommandLineArguments(OrthancPluginContext* context, + const std::string& flag); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/GlobalProperties.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,126 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "GlobalProperties.h" + +#include "Configuration.h" +#include "PostgreSQLException.h" +#include "PostgreSQLResult.h" +#include "PostgreSQLTransaction.h" + +#include "EmbeddedResources.h" + +namespace OrthancPlugins +{ + GlobalProperties::GlobalProperties(PostgreSQLConnection& connection, + int32_t lockKey) : + connection_(connection), + lockKey_(lockKey) + { + PostgreSQLTransaction transaction(connection_); + + if (!connection_.DoesTableExist("GlobalProperties")) + { + std::string query; + + EmbeddedResources::GetFileResource(query, EmbeddedResources::GLOBAL_PROPERTIES); + connection_.Execute(query); + } + + transaction.Commit(); + } + + + void GlobalProperties::Lock(bool allowUnlock) + { + PostgreSQLTransaction transaction(connection_); + + // Check the lock + if (!allowUnlock) + { + std::string lock = "0"; + if (LookupGlobalProperty(lock, lockKey_) && + lock != "0") + { + throw PostgreSQLException("The database is locked by another instance of Orthanc. " + "Use \"" + FLAG_UNLOCK + "\" to manually remove the lock."); + } + } + + // Lock the database + SetGlobalProperty(lockKey_, "1"); + + transaction.Commit(); + } + + + bool GlobalProperties::LookupGlobalProperty(std::string& target, + int32_t property) + { + if (lookupGlobalProperty_.get() == NULL) + { + lookupGlobalProperty_.reset + (new PostgreSQLStatement + (connection_, "SELECT value FROM GlobalProperties WHERE property=$1")); + lookupGlobalProperty_->DeclareInputInteger(0); + } + + lookupGlobalProperty_->BindInteger(0, static_cast<int>(property)); + + PostgreSQLResult result(*lookupGlobalProperty_); + if (result.IsDone()) + { + return false; + } + else + { + target = result.GetString(0); + return true; + } + } + + + void GlobalProperties::SetGlobalProperty(int32_t property, + const char* value) + { + if (setGlobalProperty_.get() == NULL) + { + // http://stackoverflow.com/a/1109198/881731 + setGlobalProperty_.reset + (new PostgreSQLStatement + (connection_, "SELECT ChangeGlobalProperty($1, $2)")); + setGlobalProperty_->DeclareInputInteger(0); + setGlobalProperty_->DeclareInputString(1); + } + + setGlobalProperty_->BindInteger(0, property); + setGlobalProperty_->BindString(1, value); + setGlobalProperty_->Run(); + } + + + void GlobalProperties::Unlock() + { + // Remove the lock + PostgreSQLTransaction transaction(connection_); + SetGlobalProperty(lockKey_, "0"); + transaction.Commit(); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/GlobalProperties.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,55 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "PostgreSQLConnection.h" +#include "PostgreSQLStatement.h" + +#include <stdint.h> +#include <memory> + +namespace OrthancPlugins +{ + class GlobalProperties + { + private: + PostgreSQLConnection& connection_; + int32_t lockKey_; + + std::auto_ptr<PostgreSQLStatement> lookupGlobalProperty_; + std::auto_ptr<PostgreSQLStatement> setGlobalProperty_; + + public: + GlobalProperties(PostgreSQLConnection& connection, + int32_t lockKey); + + void Lock(bool allowUnlock); + + void Unlock(); + + bool LookupGlobalProperty(std::string& target, + int32_t property); + + void SetGlobalProperty(int32_t property, + const char* value); + + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/GlobalProperties.sql Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,30 @@ +CREATE TABLE GlobalProperties( + property INTEGER PRIMARY KEY, + value TEXT + ); + + +-- Upsert functions ("insert or replace") +-- http://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#PLPGSQL-UPSERT-EXAMPLE +CREATE FUNCTION ChangeGlobalProperty(property_ INT, value_ TEXT) RETURNS VOID AS +$$ +BEGIN + LOOP + -- first try to update the property + UPDATE GlobalProperties SET value = value_ WHERE property = property_; + IF found THEN + RETURN; + END IF; + -- not there, so try to insert the property + -- if someone else inserts the same property concurrently, + -- we could get a unique-key failure + BEGIN + INSERT INTO GlobalProperties VALUES (property_, value_); + RETURN; + EXCEPTION WHEN unique_violation THEN + -- Do nothing, and loop to try the UPDATE again. + END; + END LOOP; +END; +$$ +LANGUAGE plpgsql;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PostgreSQLConnection.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,204 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "PostgreSQLConnection.h" + +#include "PostgreSQLException.h" +#include "PostgreSQLResult.h" +#include "PostgreSQLStatement.h" +#include "PostgreSQLTransaction.h" + +#include <boost/lexical_cast.hpp> + +// PostgreSQL includes +#include <libpq-fe.h> +#include <c.h> +#include <catalog/pg_type.h> + + +namespace OrthancPlugins +{ + void PostgreSQLConnection::Close() + { + if (pg_ != NULL) + { + PQfinish(reinterpret_cast<PGconn*>(pg_)); + pg_ = NULL; + } + } + + + PostgreSQLConnection::PostgreSQLConnection() + { + pg_ = NULL; + host_ = "localhost"; + port_ = 5432; + username_ = "postgres"; + password_ = "postgres"; + database_ = ""; + } + + + PostgreSQLConnection::PostgreSQLConnection(const PostgreSQLConnection& other) : + host_(other.host_), + port_(other.port_), + username_(other.username_), + password_(other.password_), + database_(other.database_), + pg_(NULL) + { + } + + + void PostgreSQLConnection::SetHost(const std::string& host) + { + Close(); + host_ = host; + } + + void PostgreSQLConnection::SetPortNumber(uint16_t port) + { + Close(); + port_ = port; + } + + void PostgreSQLConnection::SetUsername(const std::string& username) + { + Close(); + username_ = username; + } + + void PostgreSQLConnection::SetPassword(const std::string& password) + { + Close(); + password_ = password; + } + + void PostgreSQLConnection::SetDatabase(const std::string& database) + { + Close(); + database_ = database; + } + + void PostgreSQLConnection::Open() + { + if (pg_ != NULL) + { + // Already connected + return; + } + + std::string s = + std::string(" sslmode=disable") + // TODO WHY SSL DOES NOT WORK? ("SSL error: wrong version number") + " user=" + username_ + + " password=" + password_ + + " host=" + host_ + + " port=" + boost::lexical_cast<std::string>(port_); + + if (database_.size() > 0) + { + s += " dbname=" + database_; + } + + pg_ = PQconnectdb(s.c_str()); + + if (pg_ == NULL || + PQstatus(reinterpret_cast<PGconn*>(pg_)) != CONNECTION_OK) + { + std::string message; + + if (pg_) + { + message = PQerrorMessage(reinterpret_cast<PGconn*>(pg_)); + PQfinish(reinterpret_cast<PGconn*>(pg_)); + pg_ = NULL; + } + + throw PostgreSQLException(message); + } + } + + + void PostgreSQLConnection::Execute(const std::string& sql) + { + Open(); + + PGresult* result = PQexec(reinterpret_cast<PGconn*>(pg_), sql.c_str()); + if (result == NULL) + { + throw PostgreSQLException(PQerrorMessage(reinterpret_cast<PGconn*>(pg_))); + } + + bool ok = (PQresultStatus(result) == PGRES_COMMAND_OK || + PQresultStatus(result) == PGRES_TUPLES_OK); + + if (ok) + { + PQclear(result); + } + else + { + std::string message = PQresultErrorMessage(result); + PQclear(result); + throw PostgreSQLException(message); + } + } + + + bool PostgreSQLConnection::DoesTableExist(const char* name) + { + std::string lower(name); + std::transform(lower.begin(), lower.end(), lower.begin(), tolower); + + // http://stackoverflow.com/a/24089729/881731 + + PostgreSQLStatement statement(*this, + "SELECT 1 FROM pg_catalog.pg_class c " + "JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace " + "WHERE n.nspname = 'public' AND c.relkind='r' " + "AND c.relname=$1"); + + statement.DeclareInputString(0); + statement.BindString(0, lower); + + PostgreSQLResult result(statement); + return !result.IsDone(); + } + + + + void PostgreSQLConnection::ClearAll() + { + PostgreSQLTransaction transaction(*this); + + // Remove all the large objects + Execute("SELECT lo_unlink(loid) FROM (SELECT DISTINCT loid FROM pg_catalog.pg_largeobject) as loids;"); + + // http://stackoverflow.com/a/21247009/881731 + Execute("DROP SCHEMA public CASCADE;"); + Execute("CREATE SCHEMA public;"); + Execute("GRANT ALL ON SCHEMA public TO postgres;"); + Execute("GRANT ALL ON SCHEMA public TO public;"); + Execute("COMMENT ON SCHEMA public IS 'standard public schema';"); + + transaction.Commit(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PostgreSQLConnection.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,114 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#if defined(_WIN32) +#include <winsock2.h> +# if defined(_MSC_VER) +// http://msdn.microsoft.com/en-us/library/a3140177.aspx +# define htobe32(x) _byteswap_ulong(x) +# define htobe64(x) _byteswap_uint64(x) +# else // MinGW +# define htobe32(x) __builtin_bswap32(x) +# define htobe64(x) __builtin_bswap64(x) +# endif +#endif + +#include <string> +#include <boost/noncopyable.hpp> +#include <stdint.h> + +namespace OrthancPlugins +{ + class PostgreSQLConnection : public boost::noncopyable + { + private: + friend class PostgreSQLStatement; + friend class PostgreSQLLargeObject; + + std::string host_; + uint16_t port_; + std::string username_; + std::string password_; + std::string database_; + void* pg_; /* Object of type "PGconn*" */ + + void Close(); + + public: + PostgreSQLConnection(); + + PostgreSQLConnection(const PostgreSQLConnection& other); + + ~PostgreSQLConnection() + { + Close(); + } + + void SetHost(const std::string& host); + + const std::string& GetHost() const + { + return host_; + } + + void SetPortNumber(uint16_t port); + + uint16_t GetPortNumber() const + { + return port_; + } + + void SetUsername(const std::string& username); + + const std::string& GetUsername() const + { + return username_; + } + + void SetPassword(const std::string& password); + + const std::string& GetPassword() const + { + return password_; + } + + void SetDatabase(const std::string& database); + + void ResetDatabase() + { + SetDatabase(""); + } + + const std::string& GetDatabase() const + { + return database_; + } + + void Open(); + + void Execute(const std::string& sql); + + bool DoesTableExist(const char* name); + + void ClearAll(); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PostgreSQLException.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,41 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <stdexcept> +#include <string> + +namespace OrthancPlugins +{ + class PostgreSQLException : public std::runtime_error + { + public: + PostgreSQLException() : + std::runtime_error("Error in PostgreSQL") + { + } + + PostgreSQLException(const std::string& message) : + std::runtime_error("Error in PostgreSQL: " + message) + { + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PostgreSQLLargeObject.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,217 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +// http://www.postgresql.org/docs/9.1/static/lo-interfaces.html#AEN33102 + +#include "PostgreSQLLargeObject.h" + +#include "PostgreSQLException.h" + +#include <boost/lexical_cast.hpp> +#include <libpq/libpq-fs.h> + + +namespace OrthancPlugins +{ + void PostgreSQLLargeObject::Create() + { + PGconn* pg = reinterpret_cast<PGconn*>(connection_.pg_); + + oid_ = lo_creat(pg, INV_WRITE); + if (oid_ == 0) + { + throw PostgreSQLException("Cannot create a large object"); + } + } + + + void PostgreSQLLargeObject::Write(const void* data, + size_t size) + { + static int MAX_CHUNK_SIZE = 16 * 1024 * 1024; + + PGconn* pg = reinterpret_cast<PGconn*>(connection_.pg_); + + int fd = lo_open(pg, oid_, INV_WRITE); + if (fd < 0) + { + throw PostgreSQLException(); + } + + const char* position = reinterpret_cast<const char*>(data); + while (size > 0) + { + int chunk = (size > static_cast<size_t>(MAX_CHUNK_SIZE) ? MAX_CHUNK_SIZE : static_cast<int>(size)); + int nbytes = lo_write(pg, fd, position, chunk); + if (nbytes <= 0) + { + lo_close(pg, fd); + throw PostgreSQLException(); + } + + size -= nbytes; + position += nbytes; + } + + lo_close(pg, fd); + } + + + PostgreSQLLargeObject::PostgreSQLLargeObject(PostgreSQLConnection& connection, + const void* data, + size_t size) : + connection_(connection) + { + Create(); + Write(data, size); + } + + + PostgreSQLLargeObject::PostgreSQLLargeObject(PostgreSQLConnection& connection, + const std::string& s) : + connection_(connection) + { + Create(); + + if (s.size() != 0) + { + Write(s.c_str(), s.size()); + } + else + { + Write(NULL, 0); + } + } + + + class PostgreSQLLargeObject::Reader + { + private: + PGconn* pg_; + int fd_; + size_t size_; + + public: + Reader(PostgreSQLConnection& connection, + const std::string& oid) + { + pg_ = reinterpret_cast<PGconn*>(connection.pg_); + Oid id = boost::lexical_cast<Oid>(oid); + + fd_ = lo_open(pg_, id, INV_READ); + + if (fd_ < 0 || + lo_lseek(pg_, fd_, 0, SEEK_END) < 0) + { + throw PostgreSQLException("No such large object in the connection; Make sure you use a transaction"); + } + + // Get the size of the large object + int size = lo_tell(pg_, fd_); + if (size < 0) + { + throw PostgreSQLException("Internal error"); + } + size_ = static_cast<size_t>(size); + + // Go to the first byte of the object + lo_lseek(pg_, fd_, 0, SEEK_SET); + } + + ~Reader() + { + lo_close(pg_, fd_); + } + + size_t GetSize() const + { + return size_; + } + + void Read(char* target) + { + for (size_t position = 0; position < size_; ) + { + size_t remaining = size_ - position; + size_t nbytes = lo_read(pg_, fd_, target + position, remaining); + + if (nbytes < 0) + { + throw PostgreSQLException("Unable to read the large object in the database"); + } + + position += nbytes; + } + } + }; + + + void PostgreSQLLargeObject::Read(std::string& target, + PostgreSQLConnection& connection, + const std::string& oid) + { + Reader reader(connection, oid); + target.resize(reader.GetSize()); + + if (target.size() > 0) + { + reader.Read(&target[0]); + } + } + + + void PostgreSQLLargeObject::Read(void*& target, + size_t& size, + PostgreSQLConnection& connection, + const std::string& oid) + { + Reader reader(connection, oid); + size = reader.GetSize(); + + if (size == 0) + { + target = NULL; + } + else + { + target = malloc(size); + reader.Read(reinterpret_cast<char*>(target)); + } + } + + + std::string PostgreSQLLargeObject::GetOid() const + { + return boost::lexical_cast<std::string>(oid_); + } + + + void PostgreSQLLargeObject::Delete(PostgreSQLConnection& connection, + const std::string& oid) + { + PGconn* pg = reinterpret_cast<PGconn*>(connection.pg_); + Oid id = boost::lexical_cast<Oid>(oid); + + if (lo_unlink(pg, id) < 0) + { + throw PostgreSQLException("Unable to delete the large object from the database"); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PostgreSQLLargeObject.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,65 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "PostgreSQLConnection.h" + +#include <libpq-fe.h> + +namespace OrthancPlugins +{ + class PostgreSQLLargeObject : public boost::noncopyable + { + private: + class Reader; + + PostgreSQLConnection& connection_; + Oid oid_; + + void Create(); + + void Write(const void* data, + size_t size); + + public: + PostgreSQLLargeObject(PostgreSQLConnection& connection, + const void* data, + size_t size); + + PostgreSQLLargeObject(PostgreSQLConnection& connection, + const std::string& s); + + std::string GetOid() const; + + static void Read(std::string& target, + PostgreSQLConnection& connection, + const std::string& oid); + + static void Read(void*& target, + size_t& size, + PostgreSQLConnection& connection, + const std::string& oid); + + static void Delete(PostgreSQLConnection& connection, + const std::string& oid); + }; + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PostgreSQLResult.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,160 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "PostgreSQLResult.h" + +#include "PostgreSQLException.h" + +#include <cassert> +#include <boost/lexical_cast.hpp> + +// PostgreSQL includes +#include <libpq-fe.h> +#include <c.h> +#include <catalog/pg_type.h> + + +namespace OrthancPlugins +{ + void PostgreSQLResult::Clear() + { + if (result_ != NULL) + { + PQclear(reinterpret_cast<PGresult*>(result_)); + result_ = NULL; + } + } + + void PostgreSQLResult::CheckDone() + { + if (position_ >= PQntuples(reinterpret_cast<PGresult*>(result_))) + { + // We are at the end of the result set + Clear(); + } + } + + void PostgreSQLResult::CheckColumn(unsigned int column, unsigned int /*Oid*/ expectedType) const + { + if (IsDone()) + { + throw PostgreSQLException("Bad sequence of calls"); + } + + if (column >= static_cast<unsigned int>(PQnfields(reinterpret_cast<PGresult*>(result_)))) + { + throw PostgreSQLException("Parameter out of range"); + } + + if (expectedType != 0 && + expectedType != PQftype(reinterpret_cast<PGresult*>(result_), column)) + { + throw PostgreSQLException("Bad type of parameter"); + } + } + + PostgreSQLResult::PostgreSQLResult(PostgreSQLStatement& statement) : + position_(0), + connection_(statement.GetConnection()) + { + result_ = statement.Execute(); + assert(result_ != NULL); // An exception would have been thrown otherwise + + // This is the first call to "Step()" + if (PQresultStatus(reinterpret_cast<PGresult*>(result_)) != PGRES_TUPLES_OK) + { + throw PostgreSQLException("PostgreSQL: Step() applied to non-SELECT request"); + } + + CheckDone(); + } + + void PostgreSQLResult::Step() + { + position_++; + CheckDone(); + } + + bool PostgreSQLResult::IsNull(unsigned int column) const + { + CheckColumn(column, 0); + return PQgetisnull(reinterpret_cast<PGresult*>(result_), position_, column) != 0; + } + + int PostgreSQLResult::GetInteger(unsigned int column) const + { + CheckColumn(column, INT4OID); + assert(PQfsize(reinterpret_cast<PGresult*>(result_), column) == 4); + char *v = PQgetvalue(reinterpret_cast<PGresult*>(result_), position_, column); + return htobe32(*reinterpret_cast<int32_t*>(v)); + } + + int64_t PostgreSQLResult::GetInteger64(unsigned int column) const + { + CheckColumn(column, INT8OID); + assert(PQfsize(reinterpret_cast<PGresult*>(result_), column) == 8); + char *v = PQgetvalue(reinterpret_cast<PGresult*>(result_), position_, column); + return htobe64(*reinterpret_cast<int64_t*>(v)); + } + + std::string PostgreSQLResult::GetString(unsigned int column) const + { + CheckColumn(column, 0); + + Oid oid = PQftype(reinterpret_cast<PGresult*>(result_), column); + if (oid != TEXTOID && oid != VARCHAROID && oid != BYTEAOID) + { + throw PostgreSQLException("Bad type of parameter"); + } + + return std::string(PQgetvalue(reinterpret_cast<PGresult*>(result_), position_, column)); + } + + + void PostgreSQLResult::GetLargeObject(std::string& result, + unsigned int column) const + { + CheckColumn(column, OIDOID); + + Oid oid; + assert(PQfsize(reinterpret_cast<PGresult*>(result_), column) == sizeof(oid)); + + oid = *(const Oid*) PQgetvalue(reinterpret_cast<PGresult*>(result_), position_, column); + oid = ntohl(oid); + + PostgreSQLLargeObject::Read(result, connection_, boost::lexical_cast<std::string>(oid)); + } + + + void PostgreSQLResult::GetLargeObject(void*& result, + size_t& size, + unsigned int column) const + { + CheckColumn(column, OIDOID); + + Oid oid; + assert(PQfsize(reinterpret_cast<PGresult*>(result_), column) == sizeof(oid)); + + oid = *(const Oid*) PQgetvalue(reinterpret_cast<PGresult*>(result_), position_, column); + oid = ntohl(oid); + + PostgreSQLLargeObject::Read(result, size, connection_, boost::lexical_cast<std::string>(oid)); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PostgreSQLResult.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,70 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "PostgreSQLStatement.h" + +namespace OrthancPlugins +{ + class PostgreSQLResult : public boost::noncopyable + { + private: + void *result_; /* Object of type "PGresult*" */ + int position_; + PostgreSQLConnection& connection_; + + void Clear(); + + void CheckDone(); + + void CheckColumn(unsigned int column, /*Oid*/ unsigned int expectedType) const; + + public: + PostgreSQLResult(PostgreSQLStatement& statement); + + ~PostgreSQLResult() + { + Clear(); + } + + void Step(); + + bool IsDone() const + { + return result_ == NULL; + } + + bool IsNull(unsigned int column) const; + + int GetInteger(unsigned int column) const; + + int64_t GetInteger64(unsigned int column) const; + + std::string GetString(unsigned int column) const; + + void GetLargeObject(std::string& result, + unsigned int column) const; + + void GetLargeObject(void*& result, + size_t& size, + unsigned int column) const; + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PostgreSQLStatement.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,397 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "PostgreSQLStatement.h" + +#include "PostgreSQLException.h" +#include "Configuration.h" + +#include <cassert> + +// PostgreSQL includes +#include <libpq-fe.h> +#include <c.h> +#include <catalog/pg_type.h> + + +namespace OrthancPlugins +{ + class PostgreSQLStatement::Inputs : public boost::noncopyable + { + private: + std::vector<char*> values_; + std::vector<int> sizes_; + + static char* Allocate(const void* source, int size) + { + if (size == 0) + { + return NULL; + } + else + { + char* ptr = reinterpret_cast<char*>(malloc(size)); + + if (source != NULL) + { + memcpy(ptr, source, size); + } + + return ptr; + } + } + + void Resize(size_t size) + { + // Shrinking of the vector + for (size_t i = size; i < values_.size(); i++) + { + if (values_[i] != NULL) + free(values_[i]); + } + + values_.resize(size, NULL); + sizes_.resize(size, 0); + } + + void EnlargeForIndex(size_t index) + { + if (index >= values_.size()) + { + // The vector is too small + Resize(index + 1); + } + } + + public: + Inputs() + { + } + + ~Inputs() + { + Resize(0); + } + + void SetItem(size_t pos, const void* source, int size) + { + EnlargeForIndex(pos); + + if (sizes_[pos] == size) + { + if (source && size != 0) + { + memcpy(values_[pos], source, size); + } + } + else + { + if (values_[pos] != NULL) + { + free(values_[pos]); + } + + values_[pos] = Allocate(source, size); + sizes_[pos] = size; + } + } + + void SetItem(size_t pos, int size) + { + SetItem(pos, NULL, size); + } + + void* GetItem(size_t pos) const + { + if (pos >= values_.size()) + { + throw PostgreSQLException("Parameter out of range"); + } + + return values_[pos]; + } + + const std::vector<char*>& GetValues() const + { + return values_; + } + + const std::vector<int>& GetSizes() const + { + return sizes_; + } + }; + + + void PostgreSQLStatement::Prepare() + { + if (id_.size() > 0) + { + // Already prepared + return; + } + + for (size_t i = 0; i < oids_.size(); i++) + { + if (oids_[i] == 0) + { + // The type of an input parameter was not set + throw PostgreSQLException(); + } + } + + id_ = GenerateUuid(); + + const unsigned int* tmp = oids_.size() ? &oids_[0] : NULL; + + PGresult* result = PQprepare(reinterpret_cast<PGconn*>(connection_.pg_), + id_.c_str(), sql_.c_str(), oids_.size(), tmp); + + if (result == NULL) + { + id_.clear(); + throw PostgreSQLException(PQerrorMessage(reinterpret_cast<PGconn*>(connection_.pg_))); + } + + bool ok = (PQresultStatus(result) == PGRES_COMMAND_OK); + if (ok) + { + PQclear(result); + } + else + { + std::string message = PQresultErrorMessage(result); + PQclear(result); + id_.clear(); + throw PostgreSQLException(message); + } + } + + + void PostgreSQLStatement::Unprepare() + { + if (id_.size() > 0) + { + // "Although there is no libpq function for deleting a + // prepared statement, the SQL DEALLOCATE statement can be + // used for that purpose." + //connection_.Execute("DEALLOCATE " + id_); + } + + id_.clear(); + } + + + void PostgreSQLStatement::DeclareInputInternal(unsigned int param, + unsigned int /*Oid*/ type) + { + Unprepare(); + + if (oids_.size() <= param) + { + oids_.resize(param + 1, 0); + binary_.resize(param + 1); + } + + oids_[param] = type; + binary_[param] = (type == TEXTOID || type == BYTEAOID || type == OIDOID) ? 0 : 1; + } + + + void PostgreSQLStatement::DeclareInputInteger(unsigned int param) + { + DeclareInputInternal(param, INT4OID); + } + + + void PostgreSQLStatement::DeclareInputInteger64(unsigned int param) + { + DeclareInputInternal(param, INT8OID); + } + + + void PostgreSQLStatement::DeclareInputString(unsigned int param) + { + DeclareInputInternal(param, TEXTOID); + } + + + void PostgreSQLStatement::DeclareInputBinary(unsigned int param) + { + DeclareInputInternal(param, BYTEAOID); + } + + + void PostgreSQLStatement::DeclareInputLargeObject(unsigned int param) + { + DeclareInputInternal(param, OIDOID); + } + + + void* /* PGresult* */ PostgreSQLStatement::Execute() + { + Prepare(); + + PGresult* result; + + if (oids_.size() == 0) + { + // No parameter + result = PQexecPrepared(reinterpret_cast<PGconn*>(connection_.pg_), + id_.c_str(), 0, NULL, NULL, NULL, 1); + } + else + { + // At least 1 parameter + result = PQexecPrepared(reinterpret_cast<PGconn*>(connection_.pg_), + id_.c_str(), + oids_.size(), + &inputs_->GetValues()[0], + &inputs_->GetSizes()[0], + &binary_[0], + 1); + } + + if (result == NULL) + { + throw PostgreSQLException(PQerrorMessage(reinterpret_cast<PGconn*>(connection_.pg_))); + } + + return result; + } + + + PostgreSQLStatement::PostgreSQLStatement(PostgreSQLConnection& connection, + const std::string& sql) : + connection_(connection), + sql_(sql), + inputs_(new Inputs) + { + connection_.Open(); + } + + + void PostgreSQLStatement::Run() + { + PGresult* result = reinterpret_cast<PGresult*>(Execute()); + assert(result != NULL); // An exception would have been thrown otherwise + + bool ok = (PQresultStatus(result) == PGRES_COMMAND_OK || + PQresultStatus(result) == PGRES_TUPLES_OK); + if (ok) + { + PQclear(result); + } + else + { + std::string error = PQresultErrorMessage(result); + PQclear(result); + throw PostgreSQLException(error); + } + } + + + void PostgreSQLStatement::BindNull(unsigned int param) + { + if (param >= oids_.size()) + { + throw PostgreSQLException("Parameter out of range"); + } + + inputs_->SetItem(param, 0); + } + + + void PostgreSQLStatement::BindInteger(unsigned int param, int value) + { + if (param >= oids_.size()) + { + throw PostgreSQLException("Parameter out of range"); + } + + if (oids_[param] != INT4OID) + { + throw PostgreSQLException("Bad type of parameter"); + } + + assert(sizeof(int32_t) == 4); + int32_t v = htobe32(static_cast<int32_t>(value)); + inputs_->SetItem(param, &v, sizeof(int32_t)); + } + + + void PostgreSQLStatement::BindInteger64(unsigned int param, int64_t value) + { + if (param >= oids_.size()) + { + throw PostgreSQLException("Parameter out of range"); + } + + if (oids_[param] != INT8OID) + { + throw PostgreSQLException("Bad type of parameter"); + } + + assert(sizeof(int64_t) == 8); + int64_t v = htobe64(value); + inputs_->SetItem(param, &v, sizeof(int64_t)); + } + + + void PostgreSQLStatement::BindString(unsigned int param, const std::string& value) + { + if (param >= oids_.size()) + { + throw PostgreSQLException("Parameter out of range"); + } + + if (oids_[param] != TEXTOID && oids_[param] != BYTEAOID) + { + throw PostgreSQLException("Bad type of parameter"); + } + + if (value.size() == 0) + { + inputs_->SetItem(param, "", 1 /* end-of-string character */); + } + else + { + inputs_->SetItem(param, value.c_str(), + value.size() + 1); // "+1" for end-of-string character + } + } + + + void PostgreSQLStatement::BindLargeObject(unsigned int param, const PostgreSQLLargeObject& value) + { + if (param >= oids_.size()) + { + throw PostgreSQLException("Parameter out of range"); + } + + if (oids_[param] != OIDOID) + { + throw PostgreSQLException("Bad type of parameter"); + } + + inputs_->SetItem(param, value.GetOid().c_str(), + value.GetOid().size() + 1); // "+1" for end-of-string character + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PostgreSQLStatement.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,90 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "PostgreSQLConnection.h" +#include "PostgreSQLLargeObject.h" + +#include <vector> +#include <memory> +#include <boost/shared_ptr.hpp> + +namespace OrthancPlugins +{ + class PostgreSQLStatement : public boost::noncopyable + { + private: + class Inputs; + friend class PostgreSQLResult; + + PostgreSQLConnection& connection_; + std::string id_; + std::string sql_; + std::vector<unsigned int /*Oid*/> oids_; + std::vector<int> binary_; + boost::shared_ptr<Inputs> inputs_; + + void Prepare(); + + void Unprepare(); + + void DeclareInputInternal(unsigned int param, + unsigned int /*Oid*/ type); + + void* /* PGresult* */ Execute(); + + public: + PostgreSQLStatement(PostgreSQLConnection& connection, + const std::string& sql); + + ~PostgreSQLStatement() + { + Unprepare(); + } + + void DeclareInputInteger(unsigned int param); + + void DeclareInputInteger64(unsigned int param); + + void DeclareInputString(unsigned int param); + + void DeclareInputBinary(unsigned int param); + + void DeclareInputLargeObject(unsigned int param); + + void Run(); + + void BindNull(unsigned int param); + + void BindInteger(unsigned int param, int value); + + void BindInteger64(unsigned int param, int64_t value); + + void BindString(unsigned int param, const std::string& value); + + void BindLargeObject(unsigned int param, const PostgreSQLLargeObject& value); + + PostgreSQLConnection& GetConnection() const + { + return connection_; + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PostgreSQLTransaction.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,80 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "PostgreSQLTransaction.h" + +#include "PostgreSQLException.h" + +namespace OrthancPlugins +{ + PostgreSQLTransaction::PostgreSQLTransaction(PostgreSQLConnection& connection, + bool open) : + connection_(connection), + isOpen_(false) + { + if (open) + { + Begin(); + } + } + + PostgreSQLTransaction::~PostgreSQLTransaction() + { + if (isOpen_) + { + connection_.Execute("ABORT"); + } + } + + void PostgreSQLTransaction::Begin() + { + if (isOpen_) + { + throw PostgreSQLException("PostgreSQL: Beginning a transaction twice!"); + } + + connection_.Execute("BEGIN"); + isOpen_ = true; + } + + void PostgreSQLTransaction::Rollback() + { + if (!isOpen_) + { + throw PostgreSQLException("Attempting to rollback a nonexistent transaction. " + "Did you remember to call Begin()?"); + } + + connection_.Execute("ABORT"); + isOpen_ = false; + } + + void PostgreSQLTransaction::Commit() + { + if (!isOpen_) + { + throw PostgreSQLException("Attempting to roll back a nonexistent transaction. " + "Did you remember to call Begin()?"); + } + + connection_.Execute("COMMIT"); + isOpen_ = false; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Core/PostgreSQLTransaction.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,45 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "PostgreSQLConnection.h" + +namespace OrthancPlugins +{ + class PostgreSQLTransaction + { + private: + PostgreSQLConnection& connection_; + bool isOpen_; + + public: + explicit PostgreSQLTransaction(PostgreSQLConnection& connection, + bool open = true); + + ~PostgreSQLTransaction(); + + void Begin(); + + void Rollback(); + + void Commit(); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IndexPlugin/Plugin.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,100 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include <orthanc/OrthancCPlugin.h> + +#include "PostgreSQLWrapper.h" +#include "../Core/PostgreSQLException.h" +#include "../Core/Configuration.h" + + +static OrthancPluginContext* context_ = NULL; +static OrthancPlugins::PostgreSQLWrapper* backend_ = NULL; + + +extern "C" +{ + ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context) + { + context_ = context; + OrthancPluginLogWarning(context, "Using PostgreSQL index"); + + /* Check the version of the Orthanc core */ + if (OrthancPluginCheckVersion(context_) == 0) + { + char info[1024]; + sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", + context_->orthancVersion, + ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, + ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, + ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); + OrthancPluginLogError(context, info); + return -1; + } + + bool allowUnlock = OrthancPlugins::IsFlagInCommandLineArguments(context_, FLAG_UNLOCK); + + OrthancPluginSetDescription(context_, "Stores the Orthanc index into a PostgreSQL database."); + + try + { + /* Create the connection to PostgreSQL */ + std::auto_ptr<OrthancPlugins::PostgreSQLConnection> pg(OrthancPlugins::CreateConnection(context_)); + pg->Open(); + + /* Create the database back-end */ + backend_ = new OrthancPlugins::PostgreSQLWrapper(pg.release(), allowUnlock); + + /* Register the PostgreSQL index into Orthanc */ + OrthancPlugins::DatabaseBackendAdapter::Register(context, *backend_); + } + catch (std::runtime_error& e) + { + OrthancPluginLogError(context_, e.what()); + return -1; + } + + return 0; + } + + + ORTHANC_PLUGINS_API void OrthancPluginFinalize() + { + OrthancPluginLogWarning(context_, "PostgreSQL index is finalizing"); + + if (backend_ != NULL) + { + delete backend_; + backend_ = NULL; + } + } + + + ORTHANC_PLUGINS_API const char* OrthancPluginGetName() + { + return "postgresql-index"; + } + + + ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() + { + return "1.0"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IndexPlugin/PostgreSQLPrepare.sql Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,172 @@ +-- Table "GlobalProperties" is created by the +-- "OrthancPlugins::GlobalProperties" class + +CREATE TABLE Resources( + internalId BIGSERIAL NOT NULL PRIMARY KEY, + resourceType INTEGER NOT NULL, + publicId VARCHAR(64) NOT NULL, + parentId BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE + ); + +CREATE TABLE MainDicomTags( + id BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE, + tagGroup INTEGER, + tagElement INTEGER, + value BYTEA, + PRIMARY KEY(id, tagGroup, tagElement) + ); + +CREATE TABLE DicomIdentifiers( + id BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE, + tagGroup INTEGER, + tagElement INTEGER, + value BYTEA, + PRIMARY KEY(id, tagGroup, tagElement) + ); + +CREATE TABLE Metadata( + id BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE, + type INTEGER NOT NULL, + value TEXT, + PRIMARY KEY(id, type) + ); + +CREATE TABLE AttachedFiles( + id BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE, + fileType INTEGER, + uuid VARCHAR(64) NOT NULL, + compressedSize BIGINT, + uncompressedSize BIGINT, + compressionType INTEGER, + uncompressedHash VARCHAR(40), + compressedHash VARCHAR(40), + PRIMARY KEY(id, fileType) + ); + +CREATE TABLE Changes( + seq BIGSERIAL NOT NULL PRIMARY KEY, + changeType INTEGER, + internalId BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE, + resourceType INTEGER, + date VARCHAR(64) + ); + +CREATE TABLE ExportedResources( + seq BIGSERIAL NOT NULL PRIMARY KEY, + resourceType INTEGER, + publicId VARCHAR(64), + remoteModality TEXT, + patientId VARCHAR(64), + studyInstanceUid TEXT, + seriesInstanceUid TEXT, + sopInstanceUid TEXT, + date VARCHAR(64) + ); + +CREATE TABLE PatientRecyclingOrder( + seq BIGSERIAL NOT NULL PRIMARY KEY, + patientId BIGINT REFERENCES Resources(internalId) ON DELETE CASCADE + ); + +CREATE INDEX ChildrenIndex ON Resources(parentId); +CREATE INDEX PublicIndex ON Resources(publicId); +CREATE INDEX ResourceTypeIndex ON Resources(resourceType); +CREATE INDEX PatientRecyclingIndex ON PatientRecyclingOrder(patientId); + +CREATE INDEX MainDicomTagsIndex ON MainDicomTags(id); +CREATE INDEX DicomIdentifiersIndex1 ON DicomIdentifiers(id); +CREATE INDEX DicomIdentifiersIndex2 ON DicomIdentifiers(tagGroup, tagElement); +CREATE INDEX DicomIdentifiersIndexValues ON DicomIdentifiers(value); + +CREATE INDEX ChangesIndex ON Changes(internalId); + + +-- Differences with SQLite +CREATE TABLE DeletedFiles( + uuid VARCHAR(64) NOT NULL, -- 0 + fileType INTEGER, -- 1 + compressedSize BIGINT, -- 2 + uncompressedSize BIGINT, -- 3 + compressionType INTEGER, -- 4 + uncompressedHash VARCHAR(40), -- 5 + compressedHash VARCHAR(40) -- 6 + ); + +CREATE TABLE RemainingAncestor( + resourceType INTEGER NOT NULL, + publicId VARCHAR(64) NOT NULL + ); + +CREATE TABLE DeletedResources( + resourceType INTEGER NOT NULL, + publicId VARCHAR(64) NOT NULL + ); +-- End of differences + + +CREATE FUNCTION AttachedFileDeletedFunc() +RETURNS TRIGGER AS $body$ +BEGIN + INSERT INTO DeletedFiles VALUES + (old.uuid, old.filetype, old.compressedSize, + old.uncompressedSize, old.compressionType, + old.uncompressedHash, old.compressedHash); + RETURN NULL; +END; +$body$ LANGUAGE plpgsql; + +CREATE TRIGGER AttachedFileDeleted +AFTER DELETE ON AttachedFiles +FOR EACH ROW +EXECUTE PROCEDURE AttachedFileDeletedFunc(); + + +-- The following trigger combines 2 triggers from SQLite: +-- ResourceDeleted + ResourceDeletedParentCleaning +CREATE FUNCTION ResourceDeletedFunc() +RETURNS TRIGGER AS $body$ +BEGIN + --RAISE NOTICE 'Delete resource %', old.parentId; + INSERT INTO DeletedResources VALUES (old.resourceType, old.publicId); + + -- http://stackoverflow.com/a/11299968/881731 + IF EXISTS (SELECT 1 FROM Resources WHERE parentId = old.parentId) THEN + -- Signal that the deleted resource has a remaining parent + INSERT INTO RemainingAncestor + SELECT resourceType, publicId FROM Resources WHERE internalId = old.parentId; + ELSE + -- Delete a parent resource when its unique child is deleted + DELETE FROM Resources WHERE internalId = old.parentId; + END IF; + RETURN NULL; +END; +$body$ LANGUAGE plpgsql; + +CREATE TRIGGER ResourceDeleted +AFTER DELETE ON Resources +FOR EACH ROW +EXECUTE PROCEDURE ResourceDeletedFunc(); + + + +CREATE FUNCTION PatientAddedFunc() +RETURNS TRIGGER AS $body$ +BEGIN + -- The "0" corresponds to "OrthancPluginResourceType_Patient" + IF new.resourceType = 0 THEN + INSERT INTO PatientRecyclingOrder VALUES (DEFAULT, new.internalId); + END IF; + RETURN NULL; +END; +$body$ LANGUAGE plpgsql; + +CREATE TRIGGER PatientAdded +AFTER INSERT ON Resources +FOR EACH ROW +EXECUTE PROCEDURE PatientAddedFunc(); + + + +-- Set the version of the database schema +-- The "1" corresponds to the "GlobalProperty_DatabaseSchemaVersion" enumeration +INSERT INTO GlobalProperties VALUES (1, '5');
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IndexPlugin/PostgreSQLUpserts.sql Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,24 @@ +-- Upsert functions ("insert or replace") +-- http://www.postgresql.org/docs/current/static/plpgsql-control-structures.html#PLPGSQL-UPSERT-EXAMPLE +CREATE FUNCTION ChangeMetadata(id_ BIGINT, type_ INT, value_ TEXT) RETURNS VOID AS +$$ +BEGIN + LOOP + -- first try to update the property + UPDATE Metadata SET value = value_ WHERE id = id_ AND type = type_; + IF found THEN + RETURN; + END IF; + -- not there, so try to insert the property + -- if someone else inserts the same property concurrently, + -- we could get a unique-key failure + BEGIN + INSERT INTO Metadata VALUES (id_, type_, value_); + RETURN; + EXCEPTION WHEN unique_violation THEN + -- Do nothing, and loop to try the UPDATE again. + END; + END LOOP; +END; +$$ +LANGUAGE plpgsql;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IndexPlugin/PostgreSQLWrapper.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,1216 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "PostgreSQLWrapper.h" + +#include "EmbeddedResources.h" + +#include "../Core/Configuration.h" +#include "../Core/PostgreSQLException.h" +#include "../Core/PostgreSQLTransaction.h" + +#include <boost/lexical_cast.hpp> + +namespace OrthancPlugins +{ + PostgreSQLWrapper::PostgreSQLWrapper(PostgreSQLConnection* connection, + bool allowUnlock) : + connection_(connection), + globalProperties_(*connection, GlobalProperty_IndexLock) + { + globalProperties_.Lock(allowUnlock); + + Prepare(); + + + /** + * Below are the PostgreSQL precompiled statements that are used + * in more than 1 method of this class. + **/ + + getPublicId_.reset + (new PostgreSQLStatement + (*connection_, "SELECT publicId FROM Resources WHERE internalId=$1")); + getPublicId_->DeclareInputInteger64(0); + + clearDeletedFiles_.reset + (new PostgreSQLStatement + (*connection_, "DELETE FROM DeletedFiles")); + + clearDeletedResources_.reset + (new PostgreSQLStatement + (*connection_, "DELETE FROM DeletedResources")); + } + + + void PostgreSQLWrapper::SignalDeletedFilesAndResources() + { + if (getDeletedFiles_.get() == NULL || + getDeletedResources_.get() == NULL) + { + getDeletedFiles_.reset + (new PostgreSQLStatement + (*connection_, "SELECT * FROM DeletedFiles")); + + getDeletedResources_.reset + (new PostgreSQLStatement + (*connection_, "SELECT * FROM DeletedResources")); + } + + { + PostgreSQLResult result(*getDeletedFiles_); + + while (!result.IsDone()) + { + GetOutput().SignalDeletedAttachment(result.GetString(0).c_str(), + result.GetInteger(1), + result.GetInteger64(3), + result.GetString(5).c_str(), + result.GetInteger(4), + result.GetInteger64(2), + result.GetString(6).c_str()); + + result.Step(); + } + } + + { + PostgreSQLResult result(*getDeletedResources_); + + while (!result.IsDone()) + { + OrthancPluginResourceType type = static_cast<OrthancPluginResourceType>(result.GetInteger(0)); + GetOutput().SignalDeletedResource(result.GetString(1), type); + + result.Step(); + } + } + } + + + void PostgreSQLWrapper::Prepare() + { + PostgreSQLTransaction t(*connection_); + + if (!connection_->DoesTableExist("Resources")) + { + std::string query; + + EmbeddedResources::GetFileResource(query, EmbeddedResources::POSTGRESQL_PREPARE); + connection_->Execute(query); + + EmbeddedResources::GetFileResource(query, EmbeddedResources::POSTGRESQL_UPSERTS); + connection_->Execute(query); + } + + + // Check the version of the database + std::string version = "unknown"; + if (!LookupGlobalProperty(version, GlobalProperty_DatabaseSchemaVersion)) + { + throw PostgreSQLException("The database is corrupted. Drop it manually for Orthanc to recreate it"); + } + + bool ok = false; + + try + { + unsigned int v = boost::lexical_cast<unsigned int>(version); + ok = (v == 5); + } + catch (boost::bad_lexical_cast&) + { + } + + if (!ok) + { + std::string message = "Incompatible version of the Orthanc PostgreSQL database: " + version; + throw PostgreSQLException(message); + } + + t.Commit(); + } + + + PostgreSQLWrapper::~PostgreSQLWrapper() + { + globalProperties_.Unlock(); + } + + + void PostgreSQLWrapper::AddAttachment(int64_t id, + const OrthancPluginAttachment& attachment) + { + if (attachFile_.get() == NULL) + { + attachFile_.reset + (new PostgreSQLStatement + (*connection_, "INSERT INTO AttachedFiles VALUES($1, $2, $3, $4, $5, $6, $7, $8)")); + attachFile_->DeclareInputInteger64(0); + attachFile_->DeclareInputInteger(1); + attachFile_->DeclareInputString(2); + attachFile_->DeclareInputInteger64(3); + attachFile_->DeclareInputInteger64(4); + attachFile_->DeclareInputInteger(5); + attachFile_->DeclareInputString(6); + attachFile_->DeclareInputString(7); + } + + attachFile_->BindInteger64(0, id); + attachFile_->BindInteger(1, attachment.contentType); + attachFile_->BindString(2, attachment.uuid); + attachFile_->BindInteger64(3, attachment.compressedSize); + attachFile_->BindInteger64(4, attachment.uncompressedSize); + attachFile_->BindInteger(5, attachment.compressionType); + attachFile_->BindString(6, attachment.uncompressedHash); + attachFile_->BindString(7, attachment.compressedHash); + attachFile_->Run(); + } + + + void PostgreSQLWrapper::AttachChild(int64_t parent, + int64_t child) + { + if (attachChild_.get() == NULL) + { + attachChild_.reset + (new PostgreSQLStatement + (*connection_, "UPDATE Resources SET parentId = $1 WHERE internalId = $2")); + attachChild_->DeclareInputInteger64(0); + attachChild_->DeclareInputInteger64(1); + } + + attachChild_->BindInteger64(0, parent); + attachChild_->BindInteger64(1, child); + attachChild_->Run(); + } + + + void PostgreSQLWrapper::ClearTable(const std::string& tableName) + { + connection_->Execute("DELETE FROM " + tableName); + } + + + int64_t PostgreSQLWrapper::CreateResource(const char* publicId, + OrthancPluginResourceType type) + { + if (createResource_.get() == NULL) + { + createResource_.reset + (new PostgreSQLStatement + (*connection_, "INSERT INTO Resources VALUES(DEFAULT, $1, $2, NULL) RETURNING internalId")); + createResource_->DeclareInputInteger(0); + createResource_->DeclareInputString(1); + } + + createResource_->BindInteger(0, static_cast<int>(type)); + createResource_->BindString(1, publicId); + + PostgreSQLResult result(*createResource_); + if (result.IsDone()) + { + throw PostgreSQLException(); + } + + return result.GetInteger64(0); + } + + + void PostgreSQLWrapper::DeleteAttachment(int64_t id, + int32_t attachment) + { + clearDeletedFiles_->Run(); + clearDeletedResources_->Run(); + + if (deleteAttachment_.get() == NULL) + { + deleteAttachment_.reset + (new PostgreSQLStatement + (*connection_, "DELETE FROM AttachedFiles WHERE id=$1 AND fileType=$2")); + deleteAttachment_->DeclareInputInteger64(0); + deleteAttachment_->DeclareInputInteger(1); + } + + deleteAttachment_->BindInteger64(0, id); + deleteAttachment_->BindInteger(1, static_cast<int>(attachment)); + deleteAttachment_->Run(); + + SignalDeletedFilesAndResources(); + } + + + void PostgreSQLWrapper::DeleteMetadata(int64_t id, + int32_t type) + { + if (deleteMetadata_.get() == NULL) + { + deleteMetadata_.reset + (new PostgreSQLStatement + (*connection_, "DELETE FROM Metadata WHERE id=$1 and type=$2")); + deleteMetadata_->DeclareInputInteger64(0); + deleteMetadata_->DeclareInputInteger(1); + } + + deleteMetadata_->BindInteger64(0, id); + deleteMetadata_->BindInteger(1, static_cast<int>(type)); + deleteMetadata_->Run(); + } + + + void PostgreSQLWrapper::DeleteResource(int64_t id) + { + if (clearRemainingAncestor_.get() == NULL || + getRemainingAncestor_.get() == NULL) + { + clearRemainingAncestor_.reset + (new PostgreSQLStatement + (*connection_, "DELETE FROM RemainingAncestor")); + + getRemainingAncestor_.reset + (new PostgreSQLStatement + (*connection_, "SELECT * FROM RemainingAncestor")); + } + + clearDeletedFiles_->Run(); + clearDeletedResources_->Run(); + clearRemainingAncestor_->Run(); + + if (deleteResource_.get() == NULL) + { + deleteResource_.reset + (new PostgreSQLStatement + (*connection_, "DELETE FROM Resources WHERE internalId=$1")); + deleteResource_->DeclareInputInteger64(0); + } + + deleteResource_->BindInteger64(0, id); + deleteResource_->Run(); + + PostgreSQLResult result(*getRemainingAncestor_); + if (!result.IsDone()) + { + GetOutput().SignalRemainingAncestor(result.GetString(1), + static_cast<OrthancPluginResourceType>(result.GetInteger(0))); + + // There is at most 1 remaining ancestor + assert((result.Step(), result.IsDone())); + } + + SignalDeletedFilesAndResources(); + } + + + void PostgreSQLWrapper::GetAllPublicIds(std::list<std::string>& target, + OrthancPluginResourceType resourceType) + { + if (getAllPublicIds_.get() == NULL) + { + getAllPublicIds_.reset + (new PostgreSQLStatement(*connection_, + "SELECT publicId FROM Resources WHERE resourceType=$1")); + getAllPublicIds_->DeclareInputInteger(0); + } + + getAllPublicIds_->BindInteger(0, static_cast<int>(resourceType)); + PostgreSQLResult result(*getAllPublicIds_); + + target.clear(); + + while (!result.IsDone()) + { + target.push_back(result.GetString(0)); + result.Step(); + } + } + + + void PostgreSQLWrapper::GetChangesInternal(bool& done, + PostgreSQLStatement& s, + uint32_t maxResults) + { + PostgreSQLResult result(s); + uint32_t count = 0; + + while (count < maxResults && !result.IsDone()) + { + GetOutput().AnswerChange(result.GetInteger64(0), + result.GetInteger(1), + static_cast<OrthancPluginResourceType>(result.GetInteger(3)), + GetPublicId(result.GetInteger64(2)), + result.GetString(4)); + result.Step(); + count++; + } + + done = !(count == maxResults && !result.IsDone()); + } + + + void PostgreSQLWrapper::GetChanges(bool& done, + int64_t since, + uint32_t maxResults) + { + if (getChanges_.get() == NULL) + { + getChanges_.reset + (new PostgreSQLStatement + (*connection_, "SELECT * FROM Changes WHERE seq>$1 ORDER BY seq LIMIT $2")); + getChanges_->DeclareInputInteger64(0); + getChanges_->DeclareInputInteger(1); + } + + getChanges_->BindInteger64(0, since); + getChanges_->BindInteger(1, maxResults + 1); + GetChangesInternal(done, *getChanges_, maxResults); + } + + void PostgreSQLWrapper::GetLastChange() + { + if (getLastChange_.get() == NULL) + { + getLastChange_.reset + (new PostgreSQLStatement + (*connection_, "SELECT * FROM Changes ORDER BY seq DESC LIMIT 1")); + } + + bool done; // Ignored + GetChangesInternal(done, *getLastChange_, 1); + } + + + void PostgreSQLWrapper::GetChildrenInternalId(std::list<int64_t>& target, + int64_t id) + { + if (getChildrenInternalId_.get() == NULL) + { + getChildrenInternalId_.reset + (new PostgreSQLStatement(*connection_, + "SELECT a.internalId FROM Resources AS a, Resources AS b " + "WHERE a.parentId = b.internalId AND b.internalId = $1")); + getChildrenInternalId_->DeclareInputInteger64(0); + } + + getChildrenInternalId_->BindInteger64(0, id); + PostgreSQLResult result(*getChildrenInternalId_); + + target.clear(); + + while (!result.IsDone()) + { + target.push_back(result.GetInteger64(0)); + result.Step(); + } + } + + + + void PostgreSQLWrapper::GetChildrenPublicId(std::list<std::string>& target, + int64_t id) + { + if (getChildrenPublicId_.get() == NULL) + { + getChildrenPublicId_.reset + (new PostgreSQLStatement(*connection_, + "SELECT a.publicId FROM Resources AS a, Resources AS b " + "WHERE a.parentId = b.internalId AND b.internalId = $1")); + getChildrenPublicId_->DeclareInputInteger64(0); + } + + getChildrenPublicId_->BindInteger64(0, id); + PostgreSQLResult result(*getChildrenPublicId_); + + target.clear(); + + while (!result.IsDone()) + { + target.push_back(result.GetString(0)); + result.Step(); + } + } + + + void PostgreSQLWrapper::GetExportedResourcesInternal(bool& done, + PostgreSQLStatement& s, + uint32_t maxResults) + { + PostgreSQLResult result(s); + uint32_t count = 0; + + while (count < maxResults && !result.IsDone()) + { + int64_t seq = result.GetInteger64(0); + OrthancPluginResourceType resourceType = static_cast<OrthancPluginResourceType>(result.GetInteger(1)); + std::string publicId = result.GetString(2); + + GetOutput().AnswerExportedResource(seq, + resourceType, + publicId, + result.GetString(3), // modality + result.GetString(8), // date + result.GetString(4), // patient ID + result.GetString(5), // study instance UID + result.GetString(6), // series instance UID + result.GetString(7)); // sop instance UID + + result.Step(); + count++; + } + + done = !(count == maxResults && !result.IsDone()); + } + + void PostgreSQLWrapper::GetExportedResources(bool& done, + int64_t since, + uint32_t maxResults) + { + if (getExports_.get() == NULL) + { + getExports_.reset + (new PostgreSQLStatement + (*connection_, "SELECT * FROM ExportedResources WHERE seq>$1 ORDER BY seq LIMIT $2")); + getExports_->DeclareInputInteger64(0); + getExports_->DeclareInputInteger(1); + } + + getExports_->BindInteger64(0, since); + getExports_->BindInteger(1, maxResults + 1); + GetExportedResourcesInternal(done, *getExports_, maxResults); + } + + void PostgreSQLWrapper::GetLastExportedResource() + { + if (getLastExport_.get() == NULL) + { + getLastExport_.reset + (new PostgreSQLStatement + (*connection_, "SELECT * FROM ExportedResources ORDER BY seq DESC LIMIT 1")); + } + + bool done; // Ignored + GetExportedResourcesInternal(done, *getLastExport_, 1); + } + + + void PostgreSQLWrapper::GetMainDicomTags(int64_t id) + { + if (getMainDicomTags1_.get() == NULL || + getMainDicomTags2_.get() == NULL) + { + getMainDicomTags1_.reset + (new PostgreSQLStatement + (*connection_, "SELECT * FROM MainDicomTags WHERE id=$1")); + getMainDicomTags1_->DeclareInputInteger64(0); + + getMainDicomTags2_.reset + (new PostgreSQLStatement + (*connection_, "SELECT * FROM DicomIdentifiers WHERE id=$1")); + getMainDicomTags2_->DeclareInputInteger64(0); + } + + { + getMainDicomTags1_->BindInteger64(0, id); + PostgreSQLResult result(*getMainDicomTags1_); + + while (!result.IsDone()) + { + GetOutput().AnswerDicomTag(static_cast<uint16_t>(result.GetInteger(1)), + static_cast<uint16_t>(result.GetInteger(2)), + result.GetString(3)); + result.Step(); + } + } + + { + getMainDicomTags2_->BindInteger64(0, id); + PostgreSQLResult result(*getMainDicomTags2_); + + while (!result.IsDone()) + { + GetOutput().AnswerDicomTag(static_cast<uint16_t>(result.GetInteger(1)), + static_cast<uint16_t>(result.GetInteger(2)), + result.GetString(3)); + result.Step(); + } + } + } + + + std::string PostgreSQLWrapper::GetPublicId(int64_t resourceId) + { + getPublicId_->BindInteger64(0, resourceId); + + PostgreSQLResult result(*getPublicId_); + if (result.IsDone()) + { + throw PostgreSQLException("Unknown resource"); + } + + return result.GetString(0); + } + + + + uint64_t PostgreSQLWrapper::GetResourceCount(OrthancPluginResourceType resourceType) + { + if (getResourceCount_.get() == NULL) + { + getResourceCount_.reset + (new PostgreSQLStatement + (*connection_, "SELECT CAST(COUNT(*) AS BIGINT) FROM Resources WHERE resourceType=$1")); + getResourceCount_->DeclareInputInteger(0); + } + + getResourceCount_->BindInteger(0, static_cast<int>(resourceType)); + + PostgreSQLResult result(*getResourceCount_); + if (result.IsDone()) + { + throw PostgreSQLException(); + } + + if (result.IsNull(0)) + { + return 0; + } + else + { + return result.GetInteger64(0); + } + } + + + + OrthancPluginResourceType PostgreSQLWrapper::GetResourceType(int64_t resourceId) + { + if (getResourceType_.get() == NULL) + { + getResourceType_.reset + (new PostgreSQLStatement + (*connection_, "SELECT resourceType FROM Resources WHERE internalId=$1")); + getResourceType_->DeclareInputInteger64(0); + } + + getResourceType_->BindInteger64(0, resourceId); + + PostgreSQLResult result(*getResourceType_); + if (result.IsDone()) + { + throw PostgreSQLException("Unknown resource"); + } + + return static_cast<OrthancPluginResourceType>(result.GetInteger(0)); + } + + + uint64_t PostgreSQLWrapper::GetTotalCompressedSize() + { + if (getTotalCompressedSize_.get() == NULL) + { + getTotalCompressedSize_.reset + (new PostgreSQLStatement + (*connection_, "SELECT CAST(SUM(compressedSize) AS BIGINT) FROM AttachedFiles")); + } + + PostgreSQLResult result(*getTotalCompressedSize_); + if (result.IsDone()) + { + throw PostgreSQLException(); + } + + if (result.IsNull(0)) + { + return 0; + } + else + { + return result.GetInteger64(0); + } + } + + + uint64_t PostgreSQLWrapper::GetTotalUncompressedSize() + { + if (getTotalUncompressedSize_.get() == NULL) + { + getTotalUncompressedSize_.reset + (new PostgreSQLStatement + (*connection_, "SELECT CAST(SUM(uncompressedSize) AS BIGINT) FROM AttachedFiles")); + } + + PostgreSQLResult result(*getTotalUncompressedSize_); + if (result.IsDone()) + { + throw PostgreSQLException(); + } + + if (result.IsNull(0)) + { + return 0; + } + else + { + return result.GetInteger64(0); + } + } + + + bool PostgreSQLWrapper::IsExistingResource(int64_t internalId) + { + getPublicId_->BindInteger64(0, internalId); + PostgreSQLResult result(*getPublicId_); + return !result.IsDone(); + } + + + bool PostgreSQLWrapper::IsProtectedPatient(int64_t internalId) + { + if (isProtectedPatient_.get() == NULL) + { + isProtectedPatient_.reset + (new PostgreSQLStatement + (*connection_, "SELECT * FROM PatientRecyclingOrder WHERE patientId = $1")); + isProtectedPatient_->DeclareInputInteger64(0); + } + + isProtectedPatient_->BindInteger64(0, internalId); + PostgreSQLResult result(*isProtectedPatient_); + return result.IsDone(); + } + + + void PostgreSQLWrapper::ListAvailableMetadata(std::list<int32_t>& target, + int64_t id) + { + if (listMetadata_.get() == NULL) + { + listMetadata_.reset + (new PostgreSQLStatement + (*connection_, "SELECT type FROM Metadata WHERE id=$1")); + listMetadata_->DeclareInputInteger64(0); + } + + listMetadata_->BindInteger64(0, id); + PostgreSQLResult result(*listMetadata_); + + target.clear(); + + while (!result.IsDone()) + { + target.push_back(static_cast<int32_t>(result.GetInteger(0))); + result.Step(); + } + } + + + void PostgreSQLWrapper::ListAvailableAttachments(std::list<int32_t>& target, + int64_t id) + { + if (listAttachments_.get() == NULL) + { + listAttachments_.reset + (new PostgreSQLStatement + (*connection_, "SELECT fileType FROM AttachedFiles WHERE id=$1")); + listAttachments_->DeclareInputInteger64(0); + } + + listAttachments_->BindInteger64(0, id); + PostgreSQLResult result(*listAttachments_); + + target.clear(); + + while (!result.IsDone()) + { + target.push_back(static_cast<int32_t>(result.GetInteger(0))); + result.Step(); + } + } + + + void PostgreSQLWrapper::LogChange(const OrthancPluginChange& change) + { + if (logChange_.get() == NULL) + { + logChange_.reset + (new PostgreSQLStatement + (*connection_, "INSERT INTO Changes VALUES(DEFAULT, $1, $2, $3, $4)")); + logChange_->DeclareInputInteger(0); + logChange_->DeclareInputInteger64(1); + logChange_->DeclareInputInteger(2); + logChange_->DeclareInputString(3); + } + + int64_t id; + OrthancPluginResourceType type; + if (!LookupResource(id, type, change.publicId) || + type != change.resourceType) + { + throw PostgreSQLException(); + } + + logChange_->BindInteger(0, change.changeType); + logChange_->BindInteger64(1, id); + logChange_->BindInteger(2, change.resourceType); + logChange_->BindString(3, change.date); + logChange_->Run(); + } + + + + + void PostgreSQLWrapper::LogExportedResource(const OrthancPluginExportedResource& resource) + { + if (logExport_.get() == NULL) + { + logExport_.reset + (new PostgreSQLStatement + (*connection_, "INSERT INTO ExportedResources VALUES(DEFAULT, $1, $2, $3, $4, $5, $6, $7, $8)")); + logExport_->DeclareInputInteger(0); + logExport_->DeclareInputString(1); + logExport_->DeclareInputString(2); + logExport_->DeclareInputString(3); + logExport_->DeclareInputString(4); + logExport_->DeclareInputString(5); + logExport_->DeclareInputString(6); + logExport_->DeclareInputString(7); + } + + logExport_->BindInteger(0, resource.resourceType); + logExport_->BindString(1, resource.publicId); + logExport_->BindString(2, resource.modality); + logExport_->BindString(3, resource.patientId); + logExport_->BindString(4, resource.studyInstanceUid); + logExport_->BindString(5, resource.seriesInstanceUid); + logExport_->BindString(6, resource.sopInstanceUid); + logExport_->BindString(7, resource.date); + logExport_->Run(); + } + + + + + bool PostgreSQLWrapper::LookupAttachment(int64_t id, + int32_t contentType) + { + if (lookupAttachment_.get() == NULL) + { + lookupAttachment_.reset + (new PostgreSQLStatement + (*connection_, "SELECT uuid, uncompressedSize, compressionType, compressedSize, " + "uncompressedHash, compressedHash FROM AttachedFiles WHERE id=$1 AND fileType=$2")); + lookupAttachment_->DeclareInputInteger64(0); + lookupAttachment_->DeclareInputInteger(1); + } + + lookupAttachment_->BindInteger64(0, id); + lookupAttachment_->BindInteger(1, static_cast<int>(contentType)); + + PostgreSQLResult result(*lookupAttachment_); + if (!result.IsDone()) + { + GetOutput().AnswerAttachment(result.GetString(0), + contentType, + result.GetInteger64(1), + result.GetString(4), + result.GetInteger(2), + result.GetInteger64(3), + result.GetString(5)); + return true; + } + else + { + return false; + } + } + + + void PostgreSQLWrapper::LookupIdentifier(std::list<int64_t>& target, + uint16_t group, + uint16_t element, + const char* value) + { + if (lookupIdentifier1_.get() == NULL) + { + lookupIdentifier1_.reset + (new PostgreSQLStatement + (*connection_, "SELECT id FROM DicomIdentifiers WHERE tagGroup=$1 AND tagElement=$2 and value=$3")); + lookupIdentifier1_->DeclareInputInteger(0); + lookupIdentifier1_->DeclareInputInteger(1); + lookupIdentifier1_->DeclareInputBinary(2); + } + + + lookupIdentifier1_->BindInteger(0, group); + lookupIdentifier1_->BindInteger(1, element); + lookupIdentifier1_->BindString(2, value); + + PostgreSQLResult result(*lookupIdentifier1_); + target.clear(); + + while (!result.IsDone()) + { + target.push_back(result.GetInteger64(0)); + result.Step(); + } + } + + void PostgreSQLWrapper::LookupIdentifier(std::list<int64_t>& target, + const char* value) + { + if (lookupIdentifier2_.get() == NULL) + { + lookupIdentifier2_.reset + (new PostgreSQLStatement + (*connection_, "SELECT id FROM DicomIdentifiers WHERE value=$1")); + lookupIdentifier2_->DeclareInputBinary(0); + } + + lookupIdentifier2_->BindString(0, value); + + PostgreSQLResult result(*lookupIdentifier2_); + target.clear(); + + while (!result.IsDone()) + { + target.push_back(result.GetInteger64(0)); + result.Step(); + } + } + + + bool PostgreSQLWrapper::LookupMetadata(std::string& target, + int64_t id, + int32_t type) + { + if (lookupMetadata_.get() == NULL) + { + lookupMetadata_.reset + (new PostgreSQLStatement + (*connection_, "SELECT value FROM Metadata WHERE id=$1 and type=$2")); + lookupMetadata_->DeclareInputInteger64(0); + lookupMetadata_->DeclareInputInteger(1); + } + + lookupMetadata_->BindInteger64(0, id); + lookupMetadata_->BindInteger(1, static_cast<int>(type)); + + PostgreSQLResult result(*lookupMetadata_); + if (result.IsDone()) + { + return false; + } + else + { + target = result.GetString(0); + return true; + } + } + + + bool PostgreSQLWrapper::LookupParent(int64_t& parentId, + int64_t resourceId) + { + if (lookupParent_.get() == NULL) + { + lookupParent_.reset + (new PostgreSQLStatement + (*connection_, "SELECT parentId FROM Resources WHERE internalId=$1")); + lookupParent_->DeclareInputInteger64(0); + } + + lookupParent_->BindInteger64(0, resourceId); + + PostgreSQLResult result(*lookupParent_); + if (result.IsDone()) + { + throw PostgreSQLException("Unknown resource"); + } + + if (result.IsNull(0)) + { + return false; + } + else + { + parentId = result.GetInteger64(0); + return true; + } + } + + + bool PostgreSQLWrapper::LookupResource(int64_t& id, + OrthancPluginResourceType& type, + const char* publicId) + { + if (lookupResource_.get() == NULL) + { + lookupResource_.reset + (new PostgreSQLStatement + (*connection_, "SELECT internalId, resourceType FROM Resources WHERE publicId=$1")); + lookupResource_->DeclareInputString(0); + } + + lookupResource_->BindString(0, publicId); + + PostgreSQLResult result(*lookupResource_); + if (result.IsDone()) + { + return false; + } + else + { + id = result.GetInteger64(0); + type = static_cast<OrthancPluginResourceType>(result.GetInteger(1)); + return true; + } + } + + + bool PostgreSQLWrapper::SelectPatientToRecycle(int64_t& internalId) + { + if (selectPatientToRecycle_.get() == NULL) + { + selectPatientToRecycle_.reset + (new PostgreSQLStatement + (*connection_, "SELECT patientId FROM PatientRecyclingOrder ORDER BY seq ASC LIMIT 1")); + } + + PostgreSQLResult result(*selectPatientToRecycle_); + + if (result.IsDone()) + { + // No patient remaining or all the patients are protected + return false; + } + else + { + internalId = result.GetInteger64(0); + return true; + } + } + + + bool PostgreSQLWrapper::SelectPatientToRecycle(int64_t& internalId, + int64_t patientIdToAvoid) + { + if (selectPatientToRecycleAvoid_.get() == NULL) + { + selectPatientToRecycleAvoid_.reset + (new PostgreSQLStatement + (*connection_, "SELECT patientId FROM PatientRecyclingOrder WHERE patientId != $1 ORDER BY seq ASC LIMIT 1")); + selectPatientToRecycleAvoid_->DeclareInputInteger64(0); + } + + selectPatientToRecycleAvoid_->BindInteger64(0, patientIdToAvoid); + PostgreSQLResult result(*selectPatientToRecycleAvoid_); + + if (result.IsDone()) + { + // No patient remaining or all the patients are protected + return false; + } + else + { + internalId = result.GetInteger64(0); + return true; + } + } + + + static void SetTagInternal(PostgreSQLStatement& s, + int64_t id, + uint16_t group, + uint16_t element, + const char* value) + { + s.BindInteger64(0, id); + s.BindInteger(1, group); + s.BindInteger(2, element); + s.BindString(3, value); + s.Run(); + } + + + void PostgreSQLWrapper::SetMainDicomTag(int64_t id, + uint16_t group, + uint16_t element, + const char* value) + { + if (setMainDicomTags_.get() == NULL) + { + setMainDicomTags_.reset + (new PostgreSQLStatement + (*connection_, "INSERT INTO MainDicomTags VALUES($1, $2, $3, $4)")); + setMainDicomTags_->DeclareInputInteger64(0); + setMainDicomTags_->DeclareInputInteger(1); + setMainDicomTags_->DeclareInputInteger(2); + setMainDicomTags_->DeclareInputBinary(3); + } + + SetTagInternal(*setMainDicomTags_, id, group, element, value); + } + + void PostgreSQLWrapper::SetIdentifierTag(int64_t id, + uint16_t group, + uint16_t element, + const char* value) + { + if (setIdentifierTag_.get() == NULL) + { + setIdentifierTag_.reset + (new PostgreSQLStatement + (*connection_, "INSERT INTO DicomIdentifiers VALUES($1, $2, $3, $4)")); + setIdentifierTag_->DeclareInputInteger64(0); + setIdentifierTag_->DeclareInputInteger(1); + setIdentifierTag_->DeclareInputInteger(2); + setIdentifierTag_->DeclareInputBinary(3); + } + + SetTagInternal(*setIdentifierTag_, id, group, element, value); + } + + + void PostgreSQLWrapper::SetMetadata(int64_t id, + int32_t type, + const char* value) + { + if (setMetadata_.get() == NULL) + { + setMetadata_.reset + (new PostgreSQLStatement + (*connection_, "SELECT ChangeMetadata($1, $2, $3)")); + setMetadata_->DeclareInputInteger64(0); + setMetadata_->DeclareInputInteger(1); + setMetadata_->DeclareInputString(2); + } + + setMetadata_->BindInteger64(0, id); + setMetadata_->BindInteger(1, static_cast<int>(type)); + setMetadata_->BindString(2, value); + setMetadata_->Run(); + } + + + + void PostgreSQLWrapper::SetProtectedPatient(int64_t internalId, + bool isProtected) + { + if (protectPatient1_.get() == NULL || + protectPatient2_.get() == NULL) + { + protectPatient1_.reset + (new PostgreSQLStatement + (*connection_, "DELETE FROM PatientRecyclingOrder WHERE patientId=$1")); + protectPatient1_->DeclareInputInteger64(0); + + protectPatient2_.reset + (new PostgreSQLStatement + (*connection_, "INSERT INTO PatientRecyclingOrder VALUES(DEFAULT, $1)")); + protectPatient2_->DeclareInputInteger64(0); + } + + if (isProtected) + { + protectPatient1_->BindInteger64(0, internalId); + protectPatient1_->Run(); + } + else if (IsProtectedPatient(internalId)) + { + protectPatient2_->BindInteger64(0, internalId); + protectPatient2_->Run(); + } + else + { + // Nothing to do: The patient is already unprotected + } + } + + + + // For unit testing only! + void PostgreSQLWrapper::GetChildren(std::list<std::string>& childrenPublicIds, + int64_t id) + { + PostgreSQLStatement s(*connection_, "SELECT publicId FROM Resources WHERE parentId=$1"); + s.DeclareInputInteger64(0); + s.BindInteger64(0, id); + + PostgreSQLResult result(s); + + childrenPublicIds.clear(); + + while (!result.IsDone()) + { + childrenPublicIds.push_back(result.GetString(0)); + result.Step(); + } + } + + + + + // For unit testing only! + int64_t PostgreSQLWrapper::GetTableRecordCount(const std::string& table) + { + char buf[128]; + sprintf(buf, "SELECT CAST(COUNT(*) AS BIGINT) FROM %s", table.c_str()); + PostgreSQLStatement s(*connection_, buf); + + PostgreSQLResult result(s); + if (result.IsDone()) + { + throw PostgreSQLException(); + } + + if (result.IsNull(0)) + { + return 0; + } + else + { + return result.GetInteger64(0); + } + } + + + + // For unit testing only! + bool PostgreSQLWrapper::GetParentPublicId(std::string& target, + int64_t id) + { + PostgreSQLStatement s(*connection_, + "SELECT a.publicId FROM Resources AS a, Resources AS b " + "WHERE a.internalId = b.parentId AND b.internalId = $1"); + s.DeclareInputInteger64(0); + s.BindInteger64(0, id); + + PostgreSQLResult result(s); + + if (result.IsDone()) + { + return false; + } + else + { + target = result.GetString(0); + return true; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/IndexPlugin/PostgreSQLWrapper.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,276 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include <orthanc/OrthancCppDatabasePlugin.h> + +#include "../Core/GlobalProperties.h" +#include "../Core/PostgreSQLConnection.h" +#include "../Core/PostgreSQLStatement.h" +#include "../Core/PostgreSQLResult.h" +#include "../Core/PostgreSQLTransaction.h" + +#include <list> + +namespace OrthancPlugins +{ + class PostgreSQLWrapper : public IDatabaseBackend + { + private: + std::auto_ptr<PostgreSQLConnection> connection_; + std::auto_ptr<PostgreSQLTransaction> transaction_; + GlobalProperties globalProperties_; + + std::auto_ptr<PostgreSQLStatement> attachFile_; + std::auto_ptr<PostgreSQLStatement> attachChild_; + std::auto_ptr<PostgreSQLStatement> createResource_; + std::auto_ptr<PostgreSQLStatement> deleteAttachment_; + std::auto_ptr<PostgreSQLStatement> deleteMetadata_; + std::auto_ptr<PostgreSQLStatement> deleteResource_; + std::auto_ptr<PostgreSQLStatement> getAllMetadata_; + std::auto_ptr<PostgreSQLStatement> getAllPublicIds_; + std::auto_ptr<PostgreSQLStatement> getChanges_; + std::auto_ptr<PostgreSQLStatement> getLastChange_; + std::auto_ptr<PostgreSQLStatement> getChildrenInternalId_; + std::auto_ptr<PostgreSQLStatement> getChildrenPublicId_; + std::auto_ptr<PostgreSQLStatement> getExports_; + std::auto_ptr<PostgreSQLStatement> getLastExport_; + std::auto_ptr<PostgreSQLStatement> getMainDicomTags1_; + std::auto_ptr<PostgreSQLStatement> getMainDicomTags2_; + std::auto_ptr<PostgreSQLStatement> getPublicId_; + std::auto_ptr<PostgreSQLStatement> getResourceCount_; + std::auto_ptr<PostgreSQLStatement> getResourceType_; + std::auto_ptr<PostgreSQLStatement> getTotalCompressedSize_; + std::auto_ptr<PostgreSQLStatement> getTotalUncompressedSize_; + std::auto_ptr<PostgreSQLStatement> isProtectedPatient_; + std::auto_ptr<PostgreSQLStatement> listMetadata_; + std::auto_ptr<PostgreSQLStatement> listAttachments_; + std::auto_ptr<PostgreSQLStatement> logChange_; + std::auto_ptr<PostgreSQLStatement> logExport_; + std::auto_ptr<PostgreSQLStatement> lookupAttachment_; + std::auto_ptr<PostgreSQLStatement> lookupIdentifier1_; + std::auto_ptr<PostgreSQLStatement> lookupIdentifier2_; + std::auto_ptr<PostgreSQLStatement> lookupMetadata_; + std::auto_ptr<PostgreSQLStatement> lookupParent_; + std::auto_ptr<PostgreSQLStatement> lookupResource_; + std::auto_ptr<PostgreSQLStatement> selectPatientToRecycle_; + std::auto_ptr<PostgreSQLStatement> selectPatientToRecycleAvoid_; + std::auto_ptr<PostgreSQLStatement> setMainDicomTags_; + std::auto_ptr<PostgreSQLStatement> setIdentifierTag_; + std::auto_ptr<PostgreSQLStatement> setMetadata_; + std::auto_ptr<PostgreSQLStatement> protectPatient1_; + std::auto_ptr<PostgreSQLStatement> protectPatient2_; + + std::auto_ptr<PostgreSQLStatement> clearDeletedFiles_; + std::auto_ptr<PostgreSQLStatement> clearDeletedResources_; + std::auto_ptr<PostgreSQLStatement> clearRemainingAncestor_; + std::auto_ptr<PostgreSQLStatement> getDeletedFiles_; + std::auto_ptr<PostgreSQLStatement> getDeletedResources_; + std::auto_ptr<PostgreSQLStatement> getRemainingAncestor_; + + void Prepare(); + + void SignalDeletedFilesAndResources(); + + void GetChangesInternal(bool& done, + PostgreSQLStatement& s, + uint32_t maxResults); + + void GetExportedResourcesInternal(bool& done, + PostgreSQLStatement& s, + uint32_t maxResults); + + void ClearTable(const std::string& tableName); + + public: + PostgreSQLWrapper(PostgreSQLConnection* connection, // Takes the ownership of the connection + bool allowUnlock); + + virtual ~PostgreSQLWrapper(); + + virtual void Open() + { + connection_->Open(); + } + + virtual void Close() + { + transaction_.reset(NULL); + } + + virtual void AddAttachment(int64_t id, + const OrthancPluginAttachment& attachment); + + virtual void AttachChild(int64_t parent, + int64_t child); + + virtual void ClearChanges() + { + ClearTable("Changes"); + } + + virtual void ClearExportedResources() + { + ClearTable("ExportedResources"); + } + + virtual int64_t CreateResource(const char* publicId, + OrthancPluginResourceType type); + + virtual void DeleteAttachment(int64_t id, + int32_t attachment); + + virtual void DeleteMetadata(int64_t id, + int32_t type); + + virtual void DeleteResource(int64_t id); + + virtual void GetAllPublicIds(std::list<std::string>& target, + OrthancPluginResourceType resourceType); + + virtual void GetChanges(bool& done /*out*/, + int64_t since, + uint32_t maxResults); + + virtual void GetChildrenInternalId(std::list<int64_t>& result, + int64_t id); + + virtual void GetChildrenPublicId(std::list<std::string>& result, + int64_t id); + + virtual void GetExportedResources(bool& done /*out*/, + int64_t since, + uint32_t maxResults); + + virtual void GetLastChange(); + + virtual void GetLastExportedResource(); + + virtual void GetMainDicomTags(int64_t id); + + virtual std::string GetPublicId(int64_t resourceId); + + virtual uint64_t GetResourceCount(OrthancPluginResourceType resourceType); + + virtual OrthancPluginResourceType GetResourceType(int64_t resourceId); + + virtual uint64_t GetTotalCompressedSize(); + + virtual uint64_t GetTotalUncompressedSize(); + + virtual bool IsExistingResource(int64_t internalId); + + virtual bool IsProtectedPatient(int64_t internalId); + + virtual void ListAvailableMetadata(std::list<int32_t>& target, + int64_t id); + + virtual void ListAvailableAttachments(std::list<int32_t>& result, + int64_t id); + + virtual void LogChange(const OrthancPluginChange& change); + + virtual void LogExportedResource(const OrthancPluginExportedResource& resource); + + virtual bool LookupAttachment(int64_t id, + int32_t contentType); + + virtual bool LookupGlobalProperty(std::string& target, + int32_t property) + { + return globalProperties_.LookupGlobalProperty(target, property); + } + + virtual void LookupIdentifier(std::list<int64_t>& result, + uint16_t group, + uint16_t element, + const char* value); + + virtual void LookupIdentifier(std::list<int64_t>& result, + const char* value); + + virtual bool LookupMetadata(std::string& target, + int64_t id, + int32_t type); + + virtual bool LookupParent(int64_t& parentId, + int64_t resourceId); + + virtual bool LookupResource(int64_t& id /*out*/, + OrthancPluginResourceType& type /*out*/, + const char* publicId); + + virtual bool SelectPatientToRecycle(int64_t& internalId); + + virtual bool SelectPatientToRecycle(int64_t& internalId, + int64_t patientIdToAvoid); + + virtual void SetGlobalProperty(int32_t property, + const char* value) + { + return globalProperties_.SetGlobalProperty(property, value); + } + + virtual void SetMainDicomTag(int64_t id, + uint16_t group, + uint16_t element, + const char* value); + + virtual void SetIdentifierTag(int64_t id, + uint16_t group, + uint16_t element, + const char* value); + + virtual void SetMetadata(int64_t id, + int32_t type, + const char* value); + + virtual void SetProtectedPatient(int64_t internalId, + bool isProtected); + + virtual void StartTransaction() + { + transaction_.reset(new PostgreSQLTransaction(*connection_)); + } + + virtual void RollbackTransaction() + { + transaction_.reset(NULL); + } + + virtual void CommitTransaction() + { + transaction_->Commit(); + transaction_.reset(NULL); + } + + // For unit tests only! + void GetChildren(std::list<std::string>& childrenPublicIds, + int64_t id); + + // For unit tests only! + int64_t GetTableRecordCount(const std::string& table); + + // For unit tests only! + bool GetParentPublicId(std::string& result, + int64_t id); + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/NEWS Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,4 @@ +Version 1.0.0 (2015/02/06) +========================== + +* Initial release
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/README Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,44 @@ +PostgreSQL plugins for Orthanc +============================== + + +General Information +------------------- + +This repository contains the source code of 2 plugins for Orthanc, the +lightweight, RESTful DICOM server. These 2 plugins enable Orthanc to +store its files and its index as PostgreSQL databases. + + +Supported Platforms +------------------- + +Currently, the supported platforms are: + +* Linux 32bit. +* Linux 64bit. +* Windows 32bit. + + +Licensing +--------- + +The PostgreSQL plugins for Orthanc are licensed under the AGPL license. + +We also kindly ask scientific works and clinical studies that make +use of Orthanc to cite Orthanc in their associated publications. +Similarly, we ask open-source and closed-source products that make +use of Orthanc to warn us about this use. You can cite our work +using the following BibTeX entry: + +@inproceedings{Jodogne:ISBI2013, + author = {Jodogne, S. and Bernard, C. and Devillers, M. and Lenaerts, E. and Coucke, P.}, + title = {Orthanc -- {A} Lightweight, {REST}ful {DICOM} Server for Healthcare and Medical Research}, + booktitle={Biomedical Imaging ({ISBI}), {IEEE} 10th International Symposium on}, + year={2013}, + pages={190-193}, + ISSN={1945-7928}, + month=apr, + url={http://ieeexplore.ieee.org/xpl/articleDetails.jsp?tp=&arnumber=6556444}, + address={San Francisco, {CA}, {USA}} +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/AutoGeneratedCode.cmake Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,59 @@ +# Orthanc - A Lightweight, RESTful DICOM Store +# Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics +# Department, University Hospital of Liege, Belgium +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 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 +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +set(AUTOGENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/AUTOGENERATED") +set(AUTOGENERATED_SOURCES) + +file(MAKE_DIRECTORY ${AUTOGENERATED_DIR}) +include_directories(${AUTOGENERATED_DIR}) + +macro(EmbedResources) + # Convert a semicolon separated list to a whitespace separated string + set(SCRIPT_ARGUMENTS) + set(DEPENDENCIES) + set(IS_PATH_NAME false) + foreach(arg ${ARGN}) + if (${IS_PATH_NAME}) + list(APPEND SCRIPT_ARGUMENTS "${arg}") + list(APPEND DEPENDENCIES "${arg}") + set(IS_PATH_NAME false) + else() + list(APPEND SCRIPT_ARGUMENTS "${arg}") + set(IS_PATH_NAME true) + endif() + endforeach() + + set(TARGET_BASE "${AUTOGENERATED_DIR}/EmbeddedResources") + add_custom_command( + OUTPUT + "${TARGET_BASE}.h" + "${TARGET_BASE}.cpp" + COMMAND + python + "${CMAKE_CURRENT_SOURCE_DIR}/Resources/EmbedResources.py" + "${AUTOGENERATED_DIR}/EmbeddedResources" + ${SCRIPT_ARGUMENTS} + DEPENDS + "${CMAKE_CURRENT_SOURCE_DIR}/Resources/EmbedResources.py" + ${DEPENDENCIES} + ) + + list(APPEND AUTOGENERATED_SOURCES + "${AUTOGENERATED_DIR}/EmbeddedResources.cpp" + ) +endmacro()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/BoostConfiguration.cmake Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,74 @@ +# Orthanc - A Lightweight, RESTful DICOM Store +# Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics +# Department, University Hospital of Liege, Belgium +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 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 +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +if (STATIC_BUILD OR NOT USE_SYSTEM_BOOST) + set(BOOST_STATIC 1) +else() + include(FindBoost) + set(BOOST_STATIC 0) + find_package(Boost COMPONENTS ) + + if (NOT Boost_FOUND) + message(FATAL_ERROR "Unable to locate Boost on this system") + endif() + + include_directories(${Boost_INCLUDE_DIRS}) + link_libraries(${Boost_LIBRARIES}) +endif() + + +if (BOOST_STATIC) + # Parameters for Boost 1.55.0 + set(BOOST_NAME boost_1_55_0) + set(BOOST_BCP_SUFFIX bcpdigest-0.7.4) + set(BOOST_MD5 "409f7a0e4fb1f5659d07114f3133b67b") + set(BOOST_FILESYSTEM_SOURCES_DIR "${BOOST_NAME}/libs/filesystem/src") + + set(BOOST_SOURCES_DIR ${CMAKE_BINARY_DIR}/${BOOST_NAME}) + DownloadPackage( + "${BOOST_MD5}" + "http://www.montefiore.ulg.ac.be/~jodogne/Orthanc/ThirdPartyDownloads/${BOOST_NAME}_${BOOST_BCP_SUFFIX}.tar.gz" + "${BOOST_SOURCES_DIR}" + ) + + add_definitions( + # Static build of Boost + -DBOOST_ALL_NO_LIB + -DBOOST_ALL_NOLIB + -DBOOST_DATE_TIME_NO_LIB + -DBOOST_THREAD_BUILD_LIB + -DBOOST_PROGRAM_OPTIONS_NO_LIB + -DBOOST_REGEX_NO_LIB + -DBOOST_SYSTEM_NO_LIB + -DBOOST_LOCALE_NO_LIB + ) + + if (${CMAKE_COMPILER_IS_GNUCXX}) + add_definitions(-isystem ${BOOST_SOURCES_DIR}) + endif() + + include_directories( + ${BOOST_SOURCES_DIR} + ) + + list(APPEND BOOST_SOURCES + ${BOOST_SOURCES_DIR}/libs/system/src/error_code.cpp + ) + + source_group(ThirdParty\\Boost REGULAR_EXPRESSION ${BOOST_SOURCES_DIR}/.*) +endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/DownloadPackage.cmake Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,156 @@ +# Orthanc - A Lightweight, RESTful DICOM Store +# Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics +# Department, University Hospital of Liege, Belgium +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 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 +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +macro(GetUrlFilename TargetVariable Url) + string(REGEX REPLACE "^.*/" "" ${TargetVariable} "${Url}") +endmacro() + + +macro(GetUrlExtension TargetVariable Url) + #string(REGEX REPLACE "^.*/[^.]*\\." "" TMP "${Url}") + string(REGEX REPLACE "^.*\\." "" TMP "${Url}") + string(TOLOWER "${TMP}" "${TargetVariable}") +endmacro() + + +## +## Check the existence of the required decompression tools +## + +if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") + find_program(ZIP_EXECUTABLE 7z + PATHS + "$ENV{ProgramFiles}/7-Zip" + "$ENV{ProgramW6432}/7-Zip" + ) + + if (${ZIP_EXECUTABLE} MATCHES "ZIP_EXECUTABLE-NOTFOUND") + message(FATAL_ERROR "Please install the '7-zip' software (http://www.7-zip.org/)") + endif() + +else() + find_program(UNZIP_EXECUTABLE unzip) + if (${UNZIP_EXECUTABLE} MATCHES "UNZIP_EXECUTABLE-NOTFOUND") + message(FATAL_ERROR "Please install the 'unzip' package") + endif() + + find_program(TAR_EXECUTABLE tar) + if (${TAR_EXECUTABLE} MATCHES "TAR_EXECUTABLE-NOTFOUND") + message(FATAL_ERROR "Please install the 'tar' package") + endif() +endif() + + +macro(DownloadPackage MD5 Url TargetDirectory) + if (NOT IS_DIRECTORY "${TargetDirectory}") + GetUrlFilename(TMP_FILENAME "${Url}") + + set(TMP_PATH "${CMAKE_SOURCE_DIR}/ThirdPartyDownloads/${TMP_FILENAME}") + if (NOT EXISTS "${TMP_PATH}") + message("Downloading ${Url}") + + # This fixes issue 6: "I think cmake shouldn't download the + # packages which are not in the system, it should stop and let + # user know." + # https://code.google.com/p/orthanc/issues/detail?id=6 + if (NOT STATIC_BUILD AND NOT ALLOW_DOWNLOADS) + message(FATAL_ERROR "CMake is not allowed to download from Internet. Please set the ALLOW_DOWNLOADS option to ON") + endif() + + file(DOWNLOAD "${Url}" "${TMP_PATH}" SHOW_PROGRESS EXPECTED_MD5 "${MD5}") + else() + message("Using local copy of ${Url}") + endif() + + GetUrlExtension(TMP_EXTENSION "${Url}") + #message(${TMP_EXTENSION}) + message("Uncompressing ${TMP_FILENAME}") + + if ("${CMAKE_HOST_SYSTEM_NAME}" STREQUAL "Windows") + # How to silently extract files using 7-zip + # http://superuser.com/questions/331148/7zip-command-line-extract-silently-quietly + + if (("${TMP_EXTENSION}" STREQUAL "gz") OR ("${TMP_EXTENSION}" STREQUAL "tgz")) + execute_process( + COMMAND ${ZIP_EXECUTABLE} e -y ${TMP_PATH} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE Failure + OUTPUT_QUIET + ) + + if (Failure) + message(FATAL_ERROR "Error while running the uncompression tool") + endif() + + if ("${TMP_EXTENSION}" STREQUAL "tgz") + string(REGEX REPLACE ".tgz$" ".tar" TMP_FILENAME2 "${TMP_FILENAME}") + else() + string(REGEX REPLACE ".gz$" "" TMP_FILENAME2 "${TMP_FILENAME}") + endif() + + execute_process( + COMMAND ${ZIP_EXECUTABLE} x -y ${TMP_FILENAME2} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE Failure + OUTPUT_QUIET + ) + elseif ("${TMP_EXTENSION}" STREQUAL "zip") + execute_process( + COMMAND ${ZIP_EXECUTABLE} x -y ${TMP_PATH} + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE Failure + OUTPUT_QUIET + ) + else() + message(FATAL_ERROR "Support your platform here") + endif() + + else() + if ("${TMP_EXTENSION}" STREQUAL "zip") + execute_process( + COMMAND sh -c "${UNZIP_EXECUTABLE} -q ${TMP_PATH}" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE Failure + ) + elseif (("${TMP_EXTENSION}" STREQUAL "gz") OR ("${TMP_EXTENSION}" STREQUAL "tgz")) + #message("tar xvfz ${TMP_PATH}") + execute_process( + COMMAND sh -c "${TAR_EXECUTABLE} xfz ${TMP_PATH}" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE Failure + ) + elseif ("${TMP_EXTENSION}" STREQUAL "bz2") + execute_process( + COMMAND sh -c "${TAR_EXECUTABLE} xfj ${TMP_PATH}" + WORKING_DIRECTORY ${CMAKE_BINARY_DIR} + RESULT_VARIABLE Failure + ) + else() + message(FATAL_ERROR "Unknown package format.") + endif() + endif() + + if (Failure) + message(FATAL_ERROR "Error while running the uncompression tool") + endif() + + if (NOT IS_DIRECTORY "${TargetDirectory}") + message(FATAL_ERROR "The package was not uncompressed at the proper location. Check the CMake instructions.") + endif() + endif() +endmacro()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/FindPostgreSQL.cmake Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,177 @@ +# Fixed by SJ +# http://stackoverflow.com/questions/13920383/findpostgresql-cmake-wont-work-on-ubuntu + + +# - Find the PostgreSQL installation. +# In Windows, we make the assumption that, if the PostgreSQL files are installed, the default directory +# will be C:\Program Files\PostgreSQL. +# +# This module defines +# PostgreSQL_LIBRARIES - the PostgreSQL libraries needed for linking +# PostgreSQL_INCLUDE_DIRS - the directories of the PostgreSQL headers +# PostgreSQL_VERSION_STRING - the version of PostgreSQL found (since CMake 2.8.8) + +#============================================================================= +# Copyright 2004-2009 Kitware, Inc. +# +# Distributed under the OSI-approved BSD License (the "License"); +# see accompanying file Copyright.txt for details. +# +# This software is distributed WITHOUT ANY WARRANTY; without even the +# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +# See the License for more information. +#============================================================================= +# (To distribute this file outside of CMake, substitute the full +# License text for the above reference.) + +# ---------------------------------------------------------------------------- +# History: +# This module is derived from the module originally found in the VTK source tree. +# +# ---------------------------------------------------------------------------- +# Note: +# PostgreSQL_ADDITIONAL_VERSIONS is a variable that can be used to set the +# version mumber of the implementation of PostgreSQL. +# In Windows the default installation of PostgreSQL uses that as part of the path. +# E.g C:\Program Files\PostgreSQL\8.4. +# Currently, the following version numbers are known to this module: +# "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0" +# +# To use this variable just do something like this: +# set(PostgreSQL_ADDITIONAL_VERSIONS "9.2" "8.4.4") +# before calling FIND_PACKAGE(PostgreSQL) in your CMakeLists.txt file. +# This will mean that the versions you set here will be found first in the order +# specified before the default ones are searched. +# +# ---------------------------------------------------------------------------- +# You may need to manually set: +# PostgreSQL_INCLUDE_DIR - the path to where the PostgreSQL include files are. +# PostgreSQL_LIBRARY_DIR - The path to where the PostgreSQL library files are. +# If FindPostgreSQL.cmake cannot find the include files or the library files. +# +# ---------------------------------------------------------------------------- +# The following variables are set if PostgreSQL is found: +# PostgreSQL_FOUND - Set to true when PostgreSQL is found. +# PostgreSQL_INCLUDE_DIRS - Include directories for PostgreSQL +# PostgreSQL_LIBRARY_DIRS - Link directories for PostgreSQL libraries +# PostgreSQL_LIBRARIES - The PostgreSQL libraries. +# +# ---------------------------------------------------------------------------- +# If you have installed PostgreSQL in a non-standard location. +# (Please note that in the following comments, it is assumed that <Your Path> +# points to the root directory of the include directory of PostgreSQL.) +# Then you have three options. +# 1) After CMake runs, set PostgreSQL_INCLUDE_DIR to <Your Path>/include and +# PostgreSQL_LIBRARY_DIR to wherever the library pq (or libpq in windows) is +# 2) Use CMAKE_INCLUDE_PATH to set a path to <Your Path>/PostgreSQL<-version>. This will allow find_path() +# to locate PostgreSQL_INCLUDE_DIR by utilizing the PATH_SUFFIXES option. e.g. In your CMakeLists.txt file +# SET(CMAKE_INCLUDE_PATH ${CMAKE_INCLUDE_PATH} "<Your Path>/include") +# 3) Set an environment variable called ${PostgreSQL_ROOT} that points to the root of where you have +# installed PostgreSQL, e.g. <Your Path>. +# +# ---------------------------------------------------------------------------- + +set(PostgreSQL_INCLUDE_PATH_DESCRIPTION "top-level directory containing the PostgreSQL include directories. E.g /usr/local/include/PostgreSQL/8.4 or C:/Program Files/PostgreSQL/8.4/include") +set(PostgreSQL_INCLUDE_DIR_MESSAGE "Set the PostgreSQL_INCLUDE_DIR cmake cache entry to the ${PostgreSQL_INCLUDE_PATH_DESCRIPTION}") +set(PostgreSQL_LIBRARY_PATH_DESCRIPTION "top-level directory containing the PostgreSQL libraries.") +set(PostgreSQL_LIBRARY_DIR_MESSAGE "Set the PostgreSQL_LIBRARY_DIR cmake cache entry to the ${PostgreSQL_LIBRARY_PATH_DESCRIPTION}") +set(PostgreSQL_ROOT_DIR_MESSAGE "Set the PostgreSQL_ROOT system variable to where PostgreSQL is found on the machine E.g C:/Program Files/PostgreSQL/8.4") + + +set(PostgreSQL_ROOT_DIRECTORIES $ENV{PostgreSQL_ROOT}) +if(PostgreSQL_ROOT_DIRECTORIES) + file(TO_CMAKE_PATH ${PostgreSQL_ROOT_DIRECTORIES} PostgreSQL_ROOT_DIRECTORIES) +endif(PostgreSQL_ROOT_DIRECTORIES) + +set(PostgreSQL_KNOWN_VERSIONS ${PostgreSQL_ADDITIONAL_VERSIONS} + "9.1" "9.0" "8.4" "8.3" "8.2" "8.1" "8.0") + +# Define additional search paths for root directories. +if ( WIN32 ) + foreach (suffix ${PostgreSQL_KNOWN_VERSIONS} ) + set(PostgreSQL_ADDITIONAL_SEARCH_PATHS ${PostgreSQL_ADDITIONAL_SEARCH_PATHS} "C:/Program Files/PostgreSQL/${suffix}" ) + endforeach(suffix) +endif( WIN32 ) +set( PostgreSQL_ROOT_DIRECTORIES + ${PostgreSQL_ROOT_DIRECTORIES} + ${PostgreSQL_ROOT} + ${PostgreSQL_ADDITIONAL_SEARCH_PATHS} +) + +# +# Look for an installation. +# +find_path(PostgreSQL_INCLUDE_DIR + NAMES libpq-fe.h + PATHS + # Look in other places. + ${PostgreSQL_ROOT_DIRECTORIES} + PATH_SUFFIXES + pgsql + postgresql + include + # Help the user find it if we cannot. + DOC "The ${PostgreSQL_INCLUDE_DIR_MESSAGE}" +) + +find_path(PostgreSQL_TYPE_INCLUDE_DIR + NAMES catalog/pg_type.h + PATHS + # Look in other places. + ${PostgreSQL_ROOT_DIRECTORIES} + PATH_SUFFIXES + postgresql # Fix by SJ: http://stackoverflow.com/questions/13920383/findpostgresql-cmake-wont-work-on-ubuntu + pgsql/server + postgresql/server + include/server + # Help the user find it if we cannot. + DOC "The ${PostgreSQL_INCLUDE_DIR_MESSAGE}" +) + +# The PostgreSQL library. +set (PostgreSQL_LIBRARY_TO_FIND pq) +# Setting some more prefixes for the library +set (PostgreSQL_LIB_PREFIX "") +if ( WIN32 ) + set (PostgreSQL_LIB_PREFIX ${PostgreSQL_LIB_PREFIX} "lib") + set ( PostgreSQL_LIBRARY_TO_FIND ${PostgreSQL_LIB_PREFIX}${PostgreSQL_LIBRARY_TO_FIND}) +endif() + +find_library( PostgreSQL_LIBRARY + NAMES ${PostgreSQL_LIBRARY_TO_FIND} + PATHS + ${PostgreSQL_ROOT_DIRECTORIES} + PATH_SUFFIXES + lib +) +get_filename_component(PostgreSQL_LIBRARY_DIR ${PostgreSQL_LIBRARY} PATH) + +if (PostgreSQL_INCLUDE_DIR AND EXISTS "${PostgreSQL_INCLUDE_DIR}/pg_config.h") + file(STRINGS "${PostgreSQL_INCLUDE_DIR}/pg_config.h" pgsql_version_str + REGEX "^#define[\t ]+PG_VERSION[\t ]+\".*\"") + + string(REGEX REPLACE "^#define[\t ]+PG_VERSION[\t ]+\"([^\"]*)\".*" "\\1" + PostgreSQL_VERSION_STRING "${pgsql_version_str}") + unset(pgsql_version_str) +endif() + +# Did we find anything? +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(PostgreSQL + REQUIRED_VARS PostgreSQL_LIBRARY PostgreSQL_INCLUDE_DIR PostgreSQL_TYPE_INCLUDE_DIR + VERSION_VAR PostgreSQL_VERSION_STRING) +set( PostgreSQL_FOUND ${POSTGRESQL_FOUND}) + +# Now try to get the include and library path. +if(PostgreSQL_FOUND) + + set(PostgreSQL_INCLUDE_DIRS ${PostgreSQL_INCLUDE_DIR} ${PostgreSQL_TYPE_INCLUDE_DIR} ) + set(PostgreSQL_LIBRARY_DIRS ${PostgreSQL_LIBRARY_DIR} ) + set(PostgreSQL_LIBRARIES ${PostgreSQL_LIBRARY_TO_FIND}) + + #message("Final PostgreSQL include dir: ${PostgreSQL_INCLUDE_DIRS}") + #message("Final PostgreSQL library dir: ${PostgreSQL_LIBRARY_DIRS}") + #message("Final PostgreSQL libraries: ${PostgreSQL_LIBRARIES}") +endif(PostgreSQL_FOUND) + +mark_as_advanced(PostgreSQL_INCLUDE_DIR PostgreSQL_TYPE_INCLUDE_DIR PostgreSQL_LIBRARY )
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/GoogleTestConfiguration.cmake Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,57 @@ +# Orthanc - A Lightweight, RESTful DICOM Store +# Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics +# Department, University Hospital of Liege, Belgium +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 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 +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +if (USE_GTEST_DEBIAN_SOURCE_PACKAGE) + set(GTEST_SOURCES /usr/src/gtest/src/gtest-all.cc) + include_directories(/usr/src/gtest) + + if (NOT EXISTS /usr/include/gtest/gtest.h OR + NOT EXISTS ${GTEST_SOURCES}) + message(FATAL_ERROR "Please install the libgtest-dev package") + endif() + +elseif (STATIC_BUILD OR NOT USE_SYSTEM_GOOGLE_TEST) + set(GTEST_SOURCES_DIR ${CMAKE_BINARY_DIR}/gtest-1.7.0) + DownloadPackage( + "2d6ec8ccdf5c46b05ba54a9fd1d130d7" + "http://www.montefiore.ulg.ac.be/~jodogne/Orthanc/ThirdPartyDownloads/gtest-1.7.0.zip" + "${GTEST_SOURCES_DIR}") + + include_directories( + ${GTEST_SOURCES_DIR}/include + ${GTEST_SOURCES_DIR} + ) + + set(GTEST_SOURCES + ${GTEST_SOURCES_DIR}/src/gtest-all.cc + ) + + # https://code.google.com/p/googletest/issues/detail?id=412 + if (MSVC) # VS2012 does not support tuples correctly yet + add_definitions(/D _VARIADIC_MAX=10) + endif() + +else() + include(FindGTest) + if (NOT GTEST_FOUND) + message(FATAL_ERROR "Unable to find GoogleTest") + endif() + + include_directories(${GTEST_INCLUDE_DIRS}) + link_libraries(${GTEST_LIBRARIES}) +endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/JsonCppConfiguration.cmake Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,47 @@ +# Orthanc - A Lightweight, RESTful DICOM Store +# Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics +# Department, University Hospital of Liege, Belgium +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 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 +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +if (STATIC_BUILD OR NOT USE_SYSTEM_JSONCPP) + set(JSONCPP_SOURCES_DIR ${CMAKE_BINARY_DIR}/jsoncpp-src-0.6.0-rc2) + DownloadPackage( + "363e2f4cbd3aeb63bf4e571f377400fb" + "http://www.montefiore.ulg.ac.be/~jodogne/Orthanc/ThirdPartyDownloads/jsoncpp-src-0.6.0-rc2.tar.gz" + "${JSONCPP_SOURCES_DIR}") + + list(APPEND JSONCPP_SOURCES + ${JSONCPP_SOURCES_DIR}/src/lib_json/json_reader.cpp + ${JSONCPP_SOURCES_DIR}/src/lib_json/json_value.cpp + ${JSONCPP_SOURCES_DIR}/src/lib_json/json_writer.cpp + ) + + include_directories( + ${JSONCPP_SOURCES_DIR}/include + ) + + source_group(ThirdParty\\JsonCpp REGULAR_EXPRESSION ${JSONCPP_SOURCES_DIR}/.*) + +else() + CHECK_INCLUDE_FILE_CXX(jsoncpp/json/reader.h HAVE_JSONCPP_H) + if (NOT HAVE_JSONCPP_H) + message(FATAL_ERROR "Please install the libjsoncpp-dev package") + endif() + + include_directories(/usr/include/jsoncpp) + link_libraries(jsoncpp) + +endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/CMake/PostgreSQLConfiguration.cmake Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,183 @@ +# Orthanc - A Lightweight, RESTful DICOM Store +# Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics +# Department, University Hospital of Liege, Belgium +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 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 +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +##################################################################### +## PostgreSQL +##################################################################### + +if (STATIC_BUILD OR NOT USE_SYSTEM_LIBPQ) + SET(PQ_SOURCES_DIR ${CMAKE_BINARY_DIR}/postgresql-9.4.0) + DownloadPackage( + "349552802c809c4e8b09d8045a437787" + "http://www.montefiore.ulg.ac.be/~jodogne/Orthanc/ThirdPartyDownloads/postgresql-9.4.0.tar.gz" + "${PQ_SOURCES_DIR}") + + if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + set(PQ_CONFIG_H ${PQ_SOURCES_DIR}/src/include/pg_config.h.win32) + + if (${MSVC}) + configure_file( + ${PQ_SOURCES_DIR}/src/include/pg_config.h.win32 + ${AUTOGENERATED_DIR}/pg_config.h + COPY_ONLY) + + configure_file( + ${PQ_SOURCES_DIR}/src/include/pg_config_ext.h.win32 + ${AUTOGENERATED_DIR}/pg_config_ext.h + COPY_ONLY) + + else() + if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(PQ_CONFIG_H ${CMAKE_SOURCE_DIR}/Resources/Platforms/pg_config-windows64.h) + else() + set(PQ_CONFIG_H ${CMAKE_SOURCE_DIR}/Resources/Platforms/pg_config-windows32.h) + endif() + endif() + + add_definitions( + -DEXEC_BACKEND + ) + + configure_file( + ${PQ_SOURCES_DIR}/src/include/port/win32.h + ${AUTOGENERATED_DIR}/pg_config_os.h + COPY_ONLY) + + else() + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -pthread") + + if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8") + set(PQ_CONFIG_H ${CMAKE_SOURCE_DIR}/Resources/Platforms/pg_config-linux64.h) + else() + set(PQ_CONFIG_H ${CMAKE_SOURCE_DIR}/Resources/Platforms/pg_config-linux32.h) + endif() + + add_definitions( + -D_GNU_SOURCE + -D_THREAD_SAFE + -D_POSIX_PTHREAD_SEMANTICS + ) + + configure_file( + ${PQ_SOURCES_DIR}/src/include/port/linux.h + ${AUTOGENERATED_DIR}/pg_config_os.h + COPY_ONLY) + endif() + + + configure_file( + ${PQ_CONFIG_H} + ${AUTOGENERATED_DIR}/pg_config.h + COPY_ONLY + ) + + configure_file( + ${CMAKE_SOURCE_DIR}/Resources/Platforms/pg_config_ext.h + ${AUTOGENERATED_DIR}/pg_config_ext.h + COPY_ONLY + ) + + file(WRITE + ${AUTOGENERATED_DIR}/pg_config_paths.h + "") + + add_definitions( + -D_REENTRANT + -DFRONTEND + -DUNSAFE_STAT_OK + -DSYSCONFDIR="" + ) + + include_directories( + ${PQ_SOURCES_DIR}/src/include + ${PQ_SOURCES_DIR}/src/include/libpq + ${PQ_SOURCES_DIR}/src/interfaces/libpq + ) + + set(LIBPQ_SOURCES + ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-auth.c + ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-connect.c + ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-exec.c + ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-lobj.c + ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-misc.c + ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-print.c + ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-protocol2.c + ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-protocol3.c + ${PQ_SOURCES_DIR}/src/interfaces/libpq/fe-secure.c + ${PQ_SOURCES_DIR}/src/interfaces/libpq/libpq-events.c + ${PQ_SOURCES_DIR}/src/interfaces/libpq/pqexpbuffer.c + + # libpgport C files we always use + ${PQ_SOURCES_DIR}/src/port/chklocale.c + ${PQ_SOURCES_DIR}/src/port/inet_net_ntop.c + ${PQ_SOURCES_DIR}/src/port/noblock.c + ${PQ_SOURCES_DIR}/src/port/pgstrcasecmp.c + ${PQ_SOURCES_DIR}/src/port/pqsignal.c + ${PQ_SOURCES_DIR}/src/port/thread.c + + ${PQ_SOURCES_DIR}/src/backend/libpq/ip.c + ${PQ_SOURCES_DIR}/src/backend/libpq/md5.c + ${PQ_SOURCES_DIR}/src/backend/utils/mb/encnames.c + ${PQ_SOURCES_DIR}/src/backend/utils/mb/wchar.c + ${PQ_SOURCES_DIR}/src/port/strlcpy.c + ) + + if(${CMAKE_SYSTEM_NAME} STREQUAL "Windows") + include_directories( + ${PQ_SOURCES_DIR}/src/include/port/win32 + ${PQ_SOURCES_DIR}/src/port + ) + + LIST(APPEND LIBPQ_SOURCES + # libpgport C files that are needed if identified by configure + ${PQ_SOURCES_DIR}/src/interfaces/libpq/pthread-win32.c + ${PQ_SOURCES_DIR}/src/interfaces/libpq/win32.c + ${PQ_SOURCES_DIR}/src/port/crypt.c + ${PQ_SOURCES_DIR}/src/port/inet_aton.c + ${PQ_SOURCES_DIR}/src/port/open.c + ${PQ_SOURCES_DIR}/src/port/pgsleep.c + ${PQ_SOURCES_DIR}/src/port/snprintf.c + ${PQ_SOURCES_DIR}/src/port/system.c + ${PQ_SOURCES_DIR}/src/port/win32error.c + ${PQ_SOURCES_DIR}/src/port/win32setlocale.c + ${PQ_SOURCES_DIR}/src/port/getaddrinfo.c + ) + endif() + + if (${CMAKE_COMPILER_IS_GNUCXX}) + LIST(APPEND LIBPQ_SOURCES + ${PQ_SOURCES_DIR}/src/port/getpeereid.c + ) + elseif (${MSVC}) + include_directories( + ${PQ_SOURCES_DIR}/src/include/port/win32_msvc + ) + + LIST(APPEND LIBPQ_SOURCES + ${PQ_SOURCES_DIR}/src/port/dirent.c + ${PQ_SOURCES_DIR}/src/port/dirmod.c + ) + endif() + + source_group(ThirdParty\\PostgreSQL REGULAR_EXPRESSION ${PQ_SOURCES_DIR}/.*) + +else() + include(${CMAKE_SOURCE_DIR}/Resources/CMake/FindPostgreSQL.cmake) + include_directories(${PostgreSQL_INCLUDE_DIR}) + link_libraries(${PostgreSQL_LIBRARY}) +endif()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/EmbedResources.py Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,391 @@ +# Orthanc - A Lightweight, RESTful DICOM Store +# Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics +# Department, University Hospital of Liege, Belgium +# +# This program is free software: you can redistribute it and/or +# modify it under the terms of the GNU Affero General Public License +# as published by the Free Software Foundation, either version 3 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 +# Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + + +import sys +import os +import os.path +import pprint +import re + +UPCASE_CHECK = True +ARGS = [] +for i in range(len(sys.argv)): + if not sys.argv[i].startswith('--'): + ARGS.append(sys.argv[i]) + elif sys.argv[i].lower() == '--no-upcase-check': + UPCASE_CHECK = False + +if len(ARGS) < 2 or len(ARGS) % 2 != 0: + print ('Usage:') + print ('python %s [--no-upcase-check] <TargetBaseFilename> [ <Name> <Source> ]*' % sys.argv[0]) + exit(-1) + +TARGET_BASE_FILENAME = ARGS[1] +SOURCES = ARGS[2:] + +try: + # Make sure the destination directory exists + os.makedirs(os.path.normpath(os.path.join(TARGET_BASE_FILENAME, '..'))) +except: + pass + + +##################################################################### +## Read each resource file +##################################################################### + +def CheckNoUpcase(s): + global UPCASE_CHECK + if (UPCASE_CHECK and + re.search('[A-Z]', s) != None): + raise Exception("Path in a directory with an upcase letter: %s" % s) + +resources = {} + +counter = 0 +i = 0 +while i < len(SOURCES): + resourceName = SOURCES[i].upper() + pathName = SOURCES[i + 1] + + if not os.path.exists(pathName): + raise Exception("Non existing path: %s" % pathName) + + if resourceName in resources: + raise Exception("Twice the same resource: " + resourceName) + + if os.path.isdir(pathName): + # The resource is a directory: Recursively explore its files + content = {} + for root, dirs, files in os.walk(pathName): + base = os.path.relpath(root, pathName) + + # Fix issue #24 (Build fails on OSX when directory has .DS_Store files): + # Ignore folders whose name starts with a dot (".") + if base.find('/.') != -1: + print('Ignoring folder: %s' % root) + continue + + for f in files: + if f.find('~') == -1: # Ignore Emacs backup files + if base == '.': + r = f + else: + r = os.path.join(base, f) + + CheckNoUpcase(r) + r = '/' + r.replace('\\', '/') + if r in content: + raise Exception("Twice the same filename (check case): " + r) + + content[r] = { + 'Filename' : os.path.join(root, f), + 'Index' : counter + } + counter += 1 + + resources[resourceName] = { + 'Type' : 'Directory', + 'Files' : content + } + + elif os.path.isfile(pathName): + resources[resourceName] = { + 'Type' : 'File', + 'Index' : counter, + 'Filename' : pathName + } + counter += 1 + + else: + raise Exception("Not a regular file, nor a directory: " + pathName) + + i += 2 + +#pprint.pprint(resources) + + +##################################################################### +## Write .h header +##################################################################### + +header = open(TARGET_BASE_FILENAME + '.h', 'w') + +header.write(""" +#pragma once + +#include <string> +#include <list> + +namespace OrthancPlugins +{ + namespace EmbeddedResources + { + enum FileResourceId + { +""") + +isFirst = True +for name in resources: + if resources[name]['Type'] == 'File': + if isFirst: + isFirst = False + else: + header.write(',\n') + header.write(' %s' % name) + +header.write(""" + }; + + enum DirectoryResourceId + { +""") + +isFirst = True +for name in resources: + if resources[name]['Type'] == 'Directory': + if isFirst: + isFirst = False + else: + header.write(',\n') + header.write(' %s' % name) + +header.write(""" + }; + + const void* GetFileResourceBuffer(FileResourceId id); + size_t GetFileResourceSize(FileResourceId id); + void GetFileResource(std::string& result, FileResourceId id); + + const void* GetDirectoryResourceBuffer(DirectoryResourceId id, const char* path); + size_t GetDirectoryResourceSize(DirectoryResourceId id, const char* path); + void GetDirectoryResource(std::string& result, DirectoryResourceId id, const char* path); + + void ListResources(std::list<std::string>& result, DirectoryResourceId id); + } +} +""") +header.close() + + + +##################################################################### +## Write the resource content in the .cpp source +##################################################################### + +PYTHON_MAJOR_VERSION = sys.version_info[0] + +def WriteResource(cpp, item): + cpp.write(' static const uint8_t resource%dBuffer[] = {' % item['Index']) + + f = open(item['Filename'], "rb") + content = f.read() + f.close() + + # http://stackoverflow.com/a/1035360 + pos = 0 + for b in content: + if PYTHON_MAJOR_VERSION == 2: + c = ord(b[0]) + else: + c = b + + if pos > 0: + cpp.write(', ') + + if (pos % 16) == 0: + cpp.write('\n ') + + if c < 0: + raise Exception("Internal error") + + cpp.write("0x%02x" % c) + pos += 1 + + cpp.write(' };\n') + cpp.write(' static const size_t resource%dSize = %d;\n' % (item['Index'], pos)) + + +cpp = open(TARGET_BASE_FILENAME + '.cpp', 'w') + +cpp.write(""" +#include "%s.h" + +#include <stdexcept> +#include <stdint.h> +#include <string.h> + +namespace OrthancPlugins +{ + namespace EmbeddedResources + { +""" % (os.path.basename(TARGET_BASE_FILENAME))) + + +for name in resources: + if resources[name]['Type'] == 'File': + WriteResource(cpp, resources[name]) + else: + for f in resources[name]['Files']: + WriteResource(cpp, resources[name]['Files'][f]) + + + +##################################################################### +## Write the accessors to the file resources in .cpp +##################################################################### + +cpp.write(""" + const void* GetFileResourceBuffer(FileResourceId id) + { + switch (id) + { +""") +for name in resources: + if resources[name]['Type'] == 'File': + cpp.write(' case %s:\n' % name) + cpp.write(' return resource%dBuffer;\n' % resources[name]['Index']) + +cpp.write(""" + default: + throw std::runtime_error("Parameter out of range"); + } + } + + size_t GetFileResourceSize(FileResourceId id) + { + switch (id) + { +""") + +for name in resources: + if resources[name]['Type'] == 'File': + cpp.write(' case %s:\n' % name) + cpp.write(' return resource%dSize;\n' % resources[name]['Index']) + +cpp.write(""" + default: + throw std::runtime_error("Parameter out of range"); + } + } +""") + + + +##################################################################### +## Write the accessors to the directory resources in .cpp +##################################################################### + +cpp.write(""" + const void* GetDirectoryResourceBuffer(DirectoryResourceId id, const char* path) + { + switch (id) + { +""") + +for name in resources: + if resources[name]['Type'] == 'Directory': + cpp.write(' case %s:\n' % name) + isFirst = True + for path in resources[name]['Files']: + cpp.write(' if (!strcmp(path, "%s"))\n' % path) + cpp.write(' return resource%dBuffer;\n' % resources[name]['Files'][path]['Index']) + cpp.write(' throw std::runtime_error("Unknown path in a directory resource");\n\n') + +cpp.write(""" default: + throw std::runtime_error("Parameter out of range"); + } + } + + size_t GetDirectoryResourceSize(DirectoryResourceId id, const char* path) + { + switch (id) + { +""") + +for name in resources: + if resources[name]['Type'] == 'Directory': + cpp.write(' case %s:\n' % name) + isFirst = True + for path in resources[name]['Files']: + cpp.write(' if (!strcmp(path, "%s"))\n' % path) + cpp.write(' return resource%dSize;\n' % resources[name]['Files'][path]['Index']) + cpp.write(' throw std::runtime_error("Unknown path in a directory resource");\n\n') + +cpp.write(""" default: + throw std::runtime_error("Parameter out of range"); + } + } +""") + + + + +##################################################################### +## List the resources in a directory +##################################################################### + +cpp.write(""" + void ListResources(std::list<std::string>& result, DirectoryResourceId id) + { + result.clear(); + + switch (id) + { +""") + +for name in resources: + if resources[name]['Type'] == 'Directory': + cpp.write(' case %s:\n' % name) + for path in sorted(resources[name]['Files']): + cpp.write(' result.push_back("%s");\n' % path) + cpp.write(' break;\n\n') + +cpp.write(""" default: + throw std::runtime_error("Parameter out of range"); + } + } +""") + + + + +##################################################################### +## Write the convenience wrappers in .cpp +##################################################################### + +cpp.write(""" + void GetFileResource(std::string& result, FileResourceId id) + { + size_t size = GetFileResourceSize(id); + result.resize(size); + if (size > 0) + memcpy(&result[0], GetFileResourceBuffer(id), size); + } + + void GetDirectoryResource(std::string& result, DirectoryResourceId id, const char* path) + { + size_t size = GetDirectoryResourceSize(id, path); + result.resize(size); + if (size > 0) + memcpy(&result[0], GetDirectoryResourceBuffer(id, path), size); + } + } +} +""") +cpp.close()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/Platforms/pg_config-linux32.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,863 @@ +/* src/include/pg_config.h. Generated from pg_config.h.in by configure. */ +/* src/include/pg_config.h.in. Generated from configure.in by autoheader. */ + +/* Define to the type of arg 1 of 'accept' */ +#define ACCEPT_TYPE_ARG1 int + +/* Define to the type of arg 2 of 'accept' */ +#define ACCEPT_TYPE_ARG2 struct sockaddr * + +/* Define to the type of arg 3 of 'accept' */ +#define ACCEPT_TYPE_ARG3 size_t + +/* Define to the return type of 'accept' */ +#define ACCEPT_TYPE_RETURN int + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* The normal alignment of `double', in bytes. */ +#define ALIGNOF_DOUBLE 4 + +/* The normal alignment of `int', in bytes. */ +#define ALIGNOF_INT 4 + +/* The normal alignment of `long', in bytes. */ +#define ALIGNOF_LONG 4 + +/* The normal alignment of `long long int', in bytes. */ +#define ALIGNOF_LONG_LONG_INT 4 + +/* The normal alignment of `short', in bytes. */ +#define ALIGNOF_SHORT 2 + +/* Size of a disk block --- this also limits the size of a tuple. You can set + it bigger if you need bigger tuples (although TOAST should reduce the need + to have large tuples, since fields can be spread across multiple tuples). + BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is + currently 2^15 (32768). This is determined by the 15-bit widths of the + lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h). + Changing BLCKSZ requires an initdb. */ +#define BLCKSZ 8192 + +/* Define to the default TCP port number on which the server listens and to + which clients will try to connect. This can be overridden at run-time, but + it's convenient if your clients have the right default compiled in. + (--with-pgport=PORTNUM) */ +#define DEF_PGPORT 5432 + +/* Define to the default TCP port number as a string constant. */ +#define DEF_PGPORT_STR "5432" + +/* Define to build with GSSAPI support. (--with-gssapi) */ +/* #undef ENABLE_GSS */ + +/* Define to 1 if you want National Language Support. (--enable-nls) */ +/* #undef ENABLE_NLS */ + +/* Define to 1 to build client libraries as thread-safe code. + (--enable-thread-safety) */ +#define ENABLE_THREAD_SAFETY 1 + +/* Define to nothing if C supports flexible array members, and to 1 if it does + not. That way, with a declaration like `struct s { int n; double + d[FLEXIBLE_ARRAY_MEMBER]; };', the struct hack can be used with pre-C99 + compilers. When computing the size of such an object, don't use 'sizeof + (struct s)' as it overestimates the size. Use 'offsetof (struct s, d)' + instead. Don't use 'offsetof (struct s, d[0])', as this doesn't work with + MSVC and with C++ compilers. */ +#define FLEXIBLE_ARRAY_MEMBER /**/ + +/* float4 values are passed by value if 'true', by reference if 'false' */ +#define FLOAT4PASSBYVAL true + +/* float8, int8, and related values are passed by value if 'true', by + reference if 'false' */ +#define FLOAT8PASSBYVAL false + +/* Define to 1 if getpwuid_r() takes a 5th argument. */ +#define GETPWUID_R_5ARG 1 + +/* Define to 1 if gettimeofday() takes only 1 argument. */ +/* #undef GETTIMEOFDAY_1ARG */ + +#ifdef GETTIMEOFDAY_1ARG +# define gettimeofday(a,b) gettimeofday(a) +#endif + +/* Define to 1 if you have the `append_history' function. */ +/* #undef HAVE_APPEND_HISTORY */ + +/* Define to 1 if you have the `cbrt' function. */ +#define HAVE_CBRT 1 + +/* Define to 1 if you have the `class' function. */ +/* #undef HAVE_CLASS */ + +/* Define to 1 if you have the <crtdefs.h> header file. */ +/* #undef HAVE_CRTDEFS_H */ + +/* Define to 1 if you have the `crypt' function. */ +#define HAVE_CRYPT 1 + +/* Define to 1 if you have the <crypt.h> header file. */ +#define HAVE_CRYPT_H 1 + +/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you + don't. */ +#define HAVE_DECL_FDATASYNC 1 + +/* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you + don't. */ +#define HAVE_DECL_F_FULLFSYNC 0 + +/* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you + don't. */ +#define HAVE_DECL_POSIX_FADVISE 1 + +/* Define to 1 if you have the declaration of `snprintf', and to 0 if you + don't. */ +#define HAVE_DECL_SNPRINTF 1 + +/* Define to 1 if you have the declaration of `strlcat', and to 0 if you + don't. */ +#define HAVE_DECL_STRLCAT 0 + +/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you + don't. */ +#define HAVE_DECL_STRLCPY 0 + +/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you + don't. */ +#define HAVE_DECL_SYS_SIGLIST 1 + +/* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you + don't. */ +#define HAVE_DECL_VSNPRINTF 1 + +/* Define to 1 if you have the <dld.h> header file. */ +/* #undef HAVE_DLD_H */ + +/* Define to 1 if you have the `dlopen' function. */ +#define HAVE_DLOPEN 1 + +/* Define to 1 if you have the <editline/history.h> header file. */ +/* #undef HAVE_EDITLINE_HISTORY_H */ + +/* Define to 1 if you have the <editline/readline.h> header file. */ +/* #undef HAVE_EDITLINE_READLINE_H */ + +/* Define to 1 if you have the `fdatasync' function. */ +#define HAVE_FDATASYNC 1 + +/* Define to 1 if you have the `fls' function. */ +/* #undef HAVE_FLS */ + +/* Define to 1 if you have the `fpclass' function. */ +/* #undef HAVE_FPCLASS */ + +/* Define to 1 if you have the `fp_class' function. */ +/* #undef HAVE_FP_CLASS */ + +/* Define to 1 if you have the `fp_class_d' function. */ +/* #undef HAVE_FP_CLASS_D */ + +/* Define to 1 if you have the <fp_class.h> header file. */ +/* #undef HAVE_FP_CLASS_H */ + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#define HAVE_FSEEKO 1 + +/* Define to 1 if your compiler understands __func__. */ +#define HAVE_FUNCNAME__FUNC 1 + +/* Define to 1 if your compiler understands __FUNCTION__. */ +/* #undef HAVE_FUNCNAME__FUNCTION */ + +/* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */ +#define HAVE_GCC_INT_ATOMICS 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `gethostbyname_r' function. */ +#define HAVE_GETHOSTBYNAME_R 1 + +/* Define to 1 if you have the `getifaddrs' function. */ +#define HAVE_GETIFADDRS 1 + +/* Define to 1 if you have the `getopt' function. */ +#define HAVE_GETOPT 1 + +/* Define to 1 if you have the <getopt.h> header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the `getopt_long' function. */ +#define HAVE_GETOPT_LONG 1 + +/* Define to 1 if you have the `getpeereid' function. */ +/* #undef HAVE_GETPEEREID */ + +/* Define to 1 if you have the `getpeerucred' function. */ +/* #undef HAVE_GETPEERUCRED */ + +/* Define to 1 if you have the `getpwuid_r' function. */ +#define HAVE_GETPWUID_R 1 + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the `getrusage' function. */ +#define HAVE_GETRUSAGE 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +/* #undef HAVE_GETTIMEOFDAY */ + +/* Define to 1 if you have the <gssapi/gssapi.h> header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the <gssapi.h> header file. */ +/* #undef HAVE_GSSAPI_H */ + +/* Define to 1 if you have the <history.h> header file. */ +/* #undef HAVE_HISTORY_H */ + +/* Define to 1 if you have the `history_truncate_file' function. */ +/* #undef HAVE_HISTORY_TRUNCATE_FILE */ + +/* Define to 1 if you have the <ieeefp.h> header file. */ +/* #undef HAVE_IEEEFP_H */ + +/* Define to 1 if you have the <ifaddrs.h> header file. */ +#define HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `inet_aton' function. */ +#define HAVE_INET_ATON 1 + +/* Define to 1 if the system has the type `int64'. */ +/* #undef HAVE_INT64 */ + +/* Define to 1 if the system has the type `int8'. */ +/* #undef HAVE_INT8 */ + +/* Define to 1 if the system has the type `intptr_t'. */ +#define HAVE_INTPTR_T 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the global variable 'int opterr'. */ +#define HAVE_INT_OPTERR 1 + +/* Define to 1 if you have the global variable 'int optreset'. */ +/* #undef HAVE_INT_OPTRESET */ + +/* Define to 1 if you have the global variable 'int timezone'. */ +#define HAVE_INT_TIMEZONE 1 + +/* Define to 1 if you have support for IPv6. */ +#define HAVE_IPV6 1 + +/* Define to 1 if you have isinf(). */ +#define HAVE_ISINF 1 + +/* Define to 1 if you have the <langinfo.h> header file. */ +#define HAVE_LANGINFO_H 1 + +/* Define to 1 if you have the <ldap.h> header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +/* #undef HAVE_LIBCRYPTO */ + +/* Define to 1 if you have the `ldap' library (-lldap). */ +/* #undef HAVE_LIBLDAP */ + +/* Define to 1 if you have the `ldap_r' library (-lldap_r). */ +/* #undef HAVE_LIBLDAP_R */ + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `pam' library (-lpam). */ +/* #undef HAVE_LIBPAM */ + +/* Define if you have a function readline library */ +/* #undef HAVE_LIBREADLINE */ + +/* Define to 1 if you have the `selinux' library (-lselinux). */ +/* #undef HAVE_LIBSELINUX */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ + +/* Define to 1 if you have the `wldap32' library (-lwldap32). */ +/* #undef HAVE_LIBWLDAP32 */ + +/* Define to 1 if you have the `xml2' library (-lxml2). */ +/* #undef HAVE_LIBXML2 */ + +/* Define to 1 if you have the `xslt' library (-lxslt). */ +/* #undef HAVE_LIBXSLT */ + +/* Define to 1 if you have the `z' library (-lz). */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if constants of type 'long long int' should have the suffix LL. + */ +#define HAVE_LL_CONSTANTS 1 + +/* Define to 1 if the system has the type `locale_t'. */ +#define HAVE_LOCALE_T 1 + +/* Define to 1 if `long int' works and is 64 bits. */ +/* #undef HAVE_LONG_INT_64 */ + +/* Define to 1 if the system has the type `long long int'. */ +#define HAVE_LONG_LONG_INT 1 + +/* Define to 1 if `long long int' works and is 64 bits. */ +#define HAVE_LONG_LONG_INT_64 1 + +/* Define to 1 if you have the `mbstowcs_l' function. */ +/* #undef HAVE_MBSTOWCS_L */ + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if the system has the type `MINIDUMP_TYPE'. */ +/* #undef HAVE_MINIDUMP_TYPE */ + +/* Define to 1 if you have the `mkdtemp' function. */ +#define HAVE_MKDTEMP 1 + +/* Define to 1 if you have the <netinet/in.h> header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the <netinet/tcp.h> header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the <net/if.h> header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if you have the <ossp/uuid.h> header file. */ +/* #undef HAVE_OSSP_UUID_H */ + +/* Define to 1 if you have the <pam/pam_appl.h> header file. */ +/* #undef HAVE_PAM_PAM_APPL_H */ + +/* Define to 1 if you have the `poll' function. */ +#define HAVE_POLL 1 + +/* Define to 1 if you have the <poll.h> header file. */ +#define HAVE_POLL_H 1 + +/* Define to 1 if you have the `posix_fadvise' function. */ +#define HAVE_POSIX_FADVISE 1 + +/* Define to 1 if you have the POSIX signal interface. */ +#define HAVE_POSIX_SIGNALS 1 + +/* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */ +/* #undef HAVE_PPC_LWARX_MUTEX_HINT */ + +/* Define to 1 if you have the `pstat' function. */ +/* #undef HAVE_PSTAT */ + +/* Define to 1 if the PS_STRINGS thing exists. */ +/* #undef HAVE_PS_STRINGS */ + +/* Define if you have POSIX threads libraries and header files. */ +/* #undef HAVE_PTHREAD */ + +/* Define to 1 if you have the <pwd.h> header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `random' function. */ +#define HAVE_RANDOM 1 + +/* Define to 1 if you have the <readline.h> header file. */ +/* #undef HAVE_READLINE_H */ + +/* Define to 1 if you have the <readline/history.h> header file. */ +/* #undef HAVE_READLINE_HISTORY_H */ + +/* Define to 1 if you have the <readline/readline.h> header file. */ +/* #undef HAVE_READLINE_READLINE_H */ + +/* Define to 1 if you have the `readlink' function. */ +#define HAVE_READLINK 1 + +/* Define to 1 if you have the `rint' function. */ +#define HAVE_RINT 1 + +/* Define to 1 if you have the global variable + 'rl_completion_append_character'. */ +/* #undef HAVE_RL_COMPLETION_APPEND_CHARACTER */ + +/* Define to 1 if you have the `rl_completion_matches' function. */ +/* #undef HAVE_RL_COMPLETION_MATCHES */ + +/* Define to 1 if you have the `rl_filename_completion_function' function. */ +/* #undef HAVE_RL_FILENAME_COMPLETION_FUNCTION */ + +/* Define to 1 if you have the <security/pam_appl.h> header file. */ +/* #undef HAVE_SECURITY_PAM_APPL_H */ + +/* Define to 1 if you have the `setproctitle' function. */ +/* #undef HAVE_SETPROCTITLE */ + +/* Define to 1 if you have the `setsid' function. */ +#define HAVE_SETSID 1 + +/* Define to 1 if you have the `shm_open' function. */ +#define HAVE_SHM_OPEN 1 + +/* Define to 1 if you have the `sigprocmask' function. */ +#define HAVE_SIGPROCMASK 1 + +/* Define to 1 if you have sigsetjmp(). */ +#define HAVE_SIGSETJMP 1 + +/* Define to 1 if the system has the type `sig_atomic_t'. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Define to 1 if you have spinlocks. */ +#define HAVE_SPINLOCKS 1 + +/* Define to 1 if you have the `srandom' function. */ +#define HAVE_SRANDOM 1 + +/* Define to 1 if you have the `SSL_get_current_compression' function. */ +/* #undef HAVE_SSL_GET_CURRENT_COMPRESSION */ + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcat' function. */ +/* #undef HAVE_STRLCAT */ + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef HAVE_STRLCPY */ + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* Define to 1 if you have the `strtoq' function. */ +/* #undef HAVE_STRTOQ */ + +/* Define to 1 if you have the `strtoull' function. */ +#define HAVE_STRTOULL 1 + +/* Define to 1 if you have the `strtouq' function. */ +/* #undef HAVE_STRTOUQ */ + +/* Define to 1 if the system has the type `struct addrinfo'. */ +#define HAVE_STRUCT_ADDRINFO 1 + +/* Define to 1 if the system has the type `struct cmsgcred'. */ +/* #undef HAVE_STRUCT_CMSGCRED */ + +/* Define to 1 if the system has the type `struct option'. */ +#define HAVE_STRUCT_OPTION 1 + +/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */ +/* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */ + +/* Define to 1 if the system has the type `struct sockaddr_storage'. */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */ +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1 + +/* Define to 1 if `ss_len' is a member of `struct sockaddr_storage'. */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */ + +/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */ + +/* Define to 1 if `__ss_len' is a member of `struct sockaddr_storage'. */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN */ + +/* Define to 1 if `tm_zone' is a member of `struct tm'. */ +#define HAVE_STRUCT_TM_TM_ZONE 1 + +/* Define to 1 if you have the `symlink' function. */ +#define HAVE_SYMLINK 1 + +/* Define to 1 if you have the `sync_file_range' function. */ +#define HAVE_SYNC_FILE_RANGE 1 + +/* Define to 1 if you have the syslog interface. */ +#define HAVE_SYSLOG 1 + +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the <sys/ipc.h> header file. */ +#define HAVE_SYS_IPC_H 1 + +/* Define to 1 if you have the <sys/poll.h> header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the <sys/pstat.h> header file. */ +/* #undef HAVE_SYS_PSTAT_H */ + +/* Define to 1 if you have the <sys/resource.h> header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the <sys/select.h> header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the <sys/sem.h> header file. */ +#define HAVE_SYS_SEM_H 1 + +/* Define to 1 if you have the <sys/shm.h> header file. */ +#define HAVE_SYS_SHM_H 1 + +/* Define to 1 if you have the <sys/socket.h> header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the <sys/sockio.h> header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/tas.h> header file. */ +/* #undef HAVE_SYS_TAS_H */ + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <sys/ucred.h> header file. */ +/* #undef HAVE_SYS_UCRED_H */ + +/* Define to 1 if you have the <sys/un.h> header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the <termios.h> header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use + `HAVE_STRUCT_TM_TM_ZONE' instead. */ +#define HAVE_TM_ZONE 1 + +/* Define to 1 if you have the `towlower' function. */ +#define HAVE_TOWLOWER 1 + +/* Define to 1 if you have the external array `tzname'. */ +#define HAVE_TZNAME 1 + +/* Define to 1 if you have the <ucred.h> header file. */ +/* #undef HAVE_UCRED_H */ + +/* Define to 1 if the system has the type `uint64'. */ +/* #undef HAVE_UINT64 */ + +/* Define to 1 if the system has the type `uint8'. */ +/* #undef HAVE_UINT8 */ + +/* Define to 1 if the system has the type `uintptr_t'. */ +#define HAVE_UINTPTR_T 1 + +/* Define to 1 if the system has the type `union semun'. */ +/* #undef HAVE_UNION_SEMUN */ + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have unix sockets. */ +#define HAVE_UNIX_SOCKETS 1 + +/* Define to 1 if you have the `unsetenv' function. */ +#define HAVE_UNSETENV 1 + +/* Define to 1 if the system has the type `unsigned long long int'. */ +#define HAVE_UNSIGNED_LONG_LONG_INT 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the `utimes' function. */ +#define HAVE_UTIMES 1 + +/* Define to 1 if you have the <utime.h> header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if you have BSD UUID support. */ +/* #undef HAVE_UUID_BSD */ + +/* Define to 1 if you have E2FS UUID support. */ +/* #undef HAVE_UUID_E2FS */ + +/* Define to 1 if you have the <uuid.h> header file. */ +/* #undef HAVE_UUID_H */ + +/* Define to 1 if you have OSSP UUID support. */ +/* #undef HAVE_UUID_OSSP */ + +/* Define to 1 if you have the <uuid/uuid.h> header file. */ +/* #undef HAVE_UUID_UUID_H */ + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the <wchar.h> header file. */ +#define HAVE_WCHAR_H 1 + +/* Define to 1 if you have the `wcstombs' function. */ +#define HAVE_WCSTOMBS 1 + +/* Define to 1 if you have the `wcstombs_l' function. */ +/* #undef HAVE_WCSTOMBS_L */ + +/* Define to 1 if you have the <wctype.h> header file. */ +#define HAVE_WCTYPE_H 1 + +/* Define to 1 if you have the <winldap.h> header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if your compiler understands __builtin_constant_p. */ +#define HAVE__BUILTIN_CONSTANT_P 1 + +/* Define to 1 if your compiler understands __builtin_types_compatible_p. */ +#define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1 + +/* Define to 1 if your compiler understands __builtin_unreachable. */ +#define HAVE__BUILTIN_UNREACHABLE 1 + +/* Define to 1 if your compiler understands _Static_assert. */ +#define HAVE__STATIC_ASSERT 1 + +/* Define to 1 if your compiler understands __VA_ARGS__ in macros. */ +#define HAVE__VA_ARGS 1 + +/* Define to the appropriate snprintf format for 64-bit ints. */ +#define INT64_FORMAT "%lld" + +/* Define to 1 if `locale_t' requires <xlocale.h>. */ +/* #undef LOCALE_T_IN_XLOCALE */ + +/* Define as the maximum alignment requirement of any C data type. */ +#define MAXIMUM_ALIGNOF 4 + +/* Define bytes to use libc memset(). */ +#define MEMSET_LOOP_LIMIT 1024 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "pgsql-bugs@postgresql.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "PostgreSQL" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "PostgreSQL 9.4.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "postgresql" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "9.4.0" + +/* Define to the name of a signed 64-bit integer type. */ +#define PG_INT64_TYPE long long int + +/* Define to the name of the default PostgreSQL service principal in Kerberos + (GSSAPI). (--with-krb-srvnam=NAME) */ +#define PG_KRB_SRVNAM "postgres" + +/* PostgreSQL major version as a string */ +#define PG_MAJORVERSION "9.4" + +/* Define to 1 if "static inline" works without unwanted warnings from + compilations where static inline functions are defined but not called. */ +#define PG_USE_INLINE 1 + +/* PostgreSQL version as a string */ +#define PG_VERSION "9.4.0" + +/* PostgreSQL version as a number */ +#define PG_VERSION_NUM 90400 + +/* A string containing the version number, platform, and C compiler */ +#define PG_VERSION_STR "PostgreSQL 9.4.0 on i686-pc-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2, 32-bit" + +/* Define to 1 to allow profiling output to be saved separately for each + process. */ +/* #undef PROFILE_PID_DIR */ + +/* Define to the necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef PTHREAD_CREATE_JOINABLE */ + +/* RELSEG_SIZE is the maximum number of blocks allowed in one disk file. Thus, + the maximum size of a single file is RELSEG_SIZE * BLCKSZ; relations bigger + than that are divided into multiple files. RELSEG_SIZE * BLCKSZ must be + less than your OS' limit on file size. This is often 2 GB or 4GB in a + 32-bit operating system, unless you have large file support enabled. By + default, we make the limit 1 GB to avoid any possible integer-overflow + problems within the OS. A limit smaller than necessary only means we divide + a large relation into more chunks than necessary, so it seems best to err + in the direction of a small limit. A power-of-2 value is recommended to + save a few cycles in md.c, but is not absolutely required. Changing + RELSEG_SIZE requires an initdb. */ +#define RELSEG_SIZE 131072 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `void *', as computed by sizeof. */ +#define SIZEOF_VOID_P 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if strerror_r() returns a int. */ +/* #undef STRERROR_R_INT */ + +/* Define to 1 if your <sys/time.h> declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Define to the appropriate snprintf format for unsigned 64-bit ints. */ +#define UINT64_FORMAT "%llu" + +/* Define to 1 to build with assertion checks. (--enable-cassert) */ +/* #undef USE_ASSERT_CHECKING */ + +/* Define to 1 to build with Bonjour support. (--with-bonjour) */ +/* #undef USE_BONJOUR */ + +/* Define to 1 if you want float4 values to be passed by value. + (--enable-float4-byval) */ +#define USE_FLOAT4_BYVAL 1 + +/* Define to 1 if you want float8, int8, etc values to be passed by value. + (--enable-float8-byval) */ +/* #undef USE_FLOAT8_BYVAL */ + +/* Define to 1 if you want 64-bit integer timestamp and interval support. + (--enable-integer-datetimes) */ +#define USE_INTEGER_DATETIMES 1 + +/* Define to 1 to build with LDAP support. (--with-ldap) */ +/* #undef USE_LDAP */ + +/* Define to 1 to build with XML support. (--with-libxml) */ +/* #undef USE_LIBXML */ + +/* Define to 1 to use XSLT support when building contrib/xml2. + (--with-libxslt) */ +/* #undef USE_LIBXSLT */ + +/* Define to select named POSIX semaphores. */ +/* #undef USE_NAMED_POSIX_SEMAPHORES */ + +/* Define to 1 to build with PAM support. (--with-pam) */ +/* #undef USE_PAM */ + +/* Use replacement snprintf() functions. */ +/* #undef USE_REPL_SNPRINTF */ + +/* Define to build with (Open)SSL support. (--with-openssl) */ +/* #undef USE_SSL */ + +/* Define to select SysV-style semaphores. */ +#define USE_SYSV_SEMAPHORES 1 + +/* Define to select SysV-style shared memory. */ +#define USE_SYSV_SHARED_MEMORY 1 + +/* Define to select unnamed POSIX semaphores. */ +/* #undef USE_UNNAMED_POSIX_SEMAPHORES */ + +/* Define to select Win32-style semaphores. */ +/* #undef USE_WIN32_SEMAPHORES */ + +/* Define to select Win32-style shared memory. */ +/* #undef USE_WIN32_SHARED_MEMORY */ + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Size of a WAL file block. This need have no particular relation to BLCKSZ. + XLOG_BLCKSZ must be a power of 2, and if your system supports O_DIRECT I/O, + XLOG_BLCKSZ must be a multiple of the alignment requirement for direct-I/O + buffers, else direct I/O may fail. Changing XLOG_BLCKSZ requires an initdb. + */ +#define XLOG_BLCKSZ 8192 + +/* XLOG_SEG_SIZE is the size of a single WAL file. This must be a power of 2 + and larger than XLOG_BLCKSZ (preferably, a great deal larger than + XLOG_BLCKSZ). Changing XLOG_SEG_SIZE requires an initdb. */ +#define XLOG_SEG_SIZE (16 * 1024 * 1024) + + + +/* Number of bits in a file offset, on hosts where this is settable. */ +#define _FILE_OFFSET_BITS 64 + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +/* #undef _LARGEFILE_SOURCE */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to the type of a signed integer type wide enough to hold a pointer, + if such a type exists, and if the system does not define it. */ +/* #undef intptr_t */ + +/* Define to empty if the C compiler does not understand signed types. */ +/* #undef signed */ + +/* Define to the type of an unsigned integer type wide enough to hold a + pointer, if such a type exists, and if the system does not define it. */ +/* #undef uintptr_t */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/Platforms/pg_config-linux64.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,863 @@ +/* src/include/pg_config.h. Generated from pg_config.h.in by configure. */ +/* src/include/pg_config.h.in. Generated from configure.in by autoheader. */ + +/* Define to the type of arg 1 of 'accept' */ +#define ACCEPT_TYPE_ARG1 int + +/* Define to the type of arg 2 of 'accept' */ +#define ACCEPT_TYPE_ARG2 struct sockaddr * + +/* Define to the type of arg 3 of 'accept' */ +#define ACCEPT_TYPE_ARG3 socklen_t + +/* Define to the return type of 'accept' */ +#define ACCEPT_TYPE_RETURN int + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* The normal alignment of `double', in bytes. */ +#define ALIGNOF_DOUBLE 8 + +/* The normal alignment of `int', in bytes. */ +#define ALIGNOF_INT 4 + +/* The normal alignment of `long', in bytes. */ +#define ALIGNOF_LONG 8 + +/* The normal alignment of `long long int', in bytes. */ +/* #undef ALIGNOF_LONG_LONG_INT */ + +/* The normal alignment of `short', in bytes. */ +#define ALIGNOF_SHORT 2 + +/* Size of a disk block --- this also limits the size of a tuple. You can set + it bigger if you need bigger tuples (although TOAST should reduce the need + to have large tuples, since fields can be spread across multiple tuples). + BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is + currently 2^15 (32768). This is determined by the 15-bit widths of the + lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h). + Changing BLCKSZ requires an initdb. */ +#define BLCKSZ 8192 + +/* Define to the default TCP port number on which the server listens and to + which clients will try to connect. This can be overridden at run-time, but + it's convenient if your clients have the right default compiled in. + (--with-pgport=PORTNUM) */ +#define DEF_PGPORT 5432 + +/* Define to the default TCP port number as a string constant. */ +#define DEF_PGPORT_STR "5432" + +/* Define to build with GSSAPI support. (--with-gssapi) */ +/* #undef ENABLE_GSS */ + +/* Define to 1 if you want National Language Support. (--enable-nls) */ +/* #undef ENABLE_NLS */ + +/* Define to 1 to build client libraries as thread-safe code. + (--enable-thread-safety) */ +#define ENABLE_THREAD_SAFETY 1 + +/* Define to nothing if C supports flexible array members, and to 1 if it does + not. That way, with a declaration like `struct s { int n; double + d[FLEXIBLE_ARRAY_MEMBER]; };', the struct hack can be used with pre-C99 + compilers. When computing the size of such an object, don't use 'sizeof + (struct s)' as it overestimates the size. Use 'offsetof (struct s, d)' + instead. Don't use 'offsetof (struct s, d[0])', as this doesn't work with + MSVC and with C++ compilers. */ +#define FLEXIBLE_ARRAY_MEMBER /**/ + +/* float4 values are passed by value if 'true', by reference if 'false' */ +#define FLOAT4PASSBYVAL true + +/* float8, int8, and related values are passed by value if 'true', by + reference if 'false' */ +#define FLOAT8PASSBYVAL true + +/* Define to 1 if getpwuid_r() takes a 5th argument. */ +#define GETPWUID_R_5ARG 1 + +/* Define to 1 if gettimeofday() takes only 1 argument. */ +/* #undef GETTIMEOFDAY_1ARG */ + +#ifdef GETTIMEOFDAY_1ARG +# define gettimeofday(a,b) gettimeofday(a) +#endif + +/* Define to 1 if you have the `append_history' function. */ +/* #undef HAVE_APPEND_HISTORY */ + +/* Define to 1 if you have the `cbrt' function. */ +#define HAVE_CBRT 1 + +/* Define to 1 if you have the `class' function. */ +/* #undef HAVE_CLASS */ + +/* Define to 1 if you have the <crtdefs.h> header file. */ +/* #undef HAVE_CRTDEFS_H */ + +/* Define to 1 if you have the `crypt' function. */ +#define HAVE_CRYPT 1 + +/* Define to 1 if you have the <crypt.h> header file. */ +#define HAVE_CRYPT_H 1 + +/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you + don't. */ +#define HAVE_DECL_FDATASYNC 1 + +/* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you + don't. */ +#define HAVE_DECL_F_FULLFSYNC 0 + +/* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you + don't. */ +#define HAVE_DECL_POSIX_FADVISE 1 + +/* Define to 1 if you have the declaration of `snprintf', and to 0 if you + don't. */ +#define HAVE_DECL_SNPRINTF 1 + +/* Define to 1 if you have the declaration of `strlcat', and to 0 if you + don't. */ +#define HAVE_DECL_STRLCAT 0 + +/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you + don't. */ +#define HAVE_DECL_STRLCPY 0 + +/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you + don't. */ +#define HAVE_DECL_SYS_SIGLIST 1 + +/* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you + don't. */ +#define HAVE_DECL_VSNPRINTF 1 + +/* Define to 1 if you have the <dld.h> header file. */ +/* #undef HAVE_DLD_H */ + +/* Define to 1 if you have the `dlopen' function. */ +#define HAVE_DLOPEN 1 + +/* Define to 1 if you have the <editline/history.h> header file. */ +/* #undef HAVE_EDITLINE_HISTORY_H */ + +/* Define to 1 if you have the <editline/readline.h> header file. */ +/* #undef HAVE_EDITLINE_READLINE_H */ + +/* Define to 1 if you have the `fdatasync' function. */ +#define HAVE_FDATASYNC 1 + +/* Define to 1 if you have the `fls' function. */ +/* #undef HAVE_FLS */ + +/* Define to 1 if you have the `fpclass' function. */ +/* #undef HAVE_FPCLASS */ + +/* Define to 1 if you have the `fp_class' function. */ +/* #undef HAVE_FP_CLASS */ + +/* Define to 1 if you have the `fp_class_d' function. */ +/* #undef HAVE_FP_CLASS_D */ + +/* Define to 1 if you have the <fp_class.h> header file. */ +/* #undef HAVE_FP_CLASS_H */ + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#define HAVE_FSEEKO 1 + +/* Define to 1 if your compiler understands __func__. */ +#define HAVE_FUNCNAME__FUNC 1 + +/* Define to 1 if your compiler understands __FUNCTION__. */ +/* #undef HAVE_FUNCNAME__FUNCTION */ + +/* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */ +#define HAVE_GCC_INT_ATOMICS 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +#define HAVE_GETADDRINFO 1 + +/* Define to 1 if you have the `gethostbyname_r' function. */ +#define HAVE_GETHOSTBYNAME_R 1 + +/* Define to 1 if you have the `getifaddrs' function. */ +#define HAVE_GETIFADDRS 1 + +/* Define to 1 if you have the `getopt' function. */ +#define HAVE_GETOPT 1 + +/* Define to 1 if you have the <getopt.h> header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the `getopt_long' function. */ +#define HAVE_GETOPT_LONG 1 + +/* Define to 1 if you have the `getpeereid' function. */ +/* #undef HAVE_GETPEEREID */ + +/* Define to 1 if you have the `getpeerucred' function. */ +/* #undef HAVE_GETPEERUCRED */ + +/* Define to 1 if you have the `getpwuid_r' function. */ +#define HAVE_GETPWUID_R 1 + +/* Define to 1 if you have the `getrlimit' function. */ +#define HAVE_GETRLIMIT 1 + +/* Define to 1 if you have the `getrusage' function. */ +#define HAVE_GETRUSAGE 1 + +/* Define to 1 if you have the `gettimeofday' function. */ +/* #undef HAVE_GETTIMEOFDAY */ + +/* Define to 1 if you have the <gssapi/gssapi.h> header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the <gssapi.h> header file. */ +/* #undef HAVE_GSSAPI_H */ + +/* Define to 1 if you have the <history.h> header file. */ +/* #undef HAVE_HISTORY_H */ + +/* Define to 1 if you have the `history_truncate_file' function. */ +/* #undef HAVE_HISTORY_TRUNCATE_FILE */ + +/* Define to 1 if you have the <ieeefp.h> header file. */ +/* #undef HAVE_IEEEFP_H */ + +/* Define to 1 if you have the <ifaddrs.h> header file. */ +#define HAVE_IFADDRS_H 1 + +/* Define to 1 if you have the `inet_aton' function. */ +#define HAVE_INET_ATON 1 + +/* Define to 1 if the system has the type `int64'. */ +/* #undef HAVE_INT64 */ + +/* Define to 1 if the system has the type `int8'. */ +/* #undef HAVE_INT8 */ + +/* Define to 1 if the system has the type `intptr_t'. */ +#define HAVE_INTPTR_T 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the global variable 'int opterr'. */ +#define HAVE_INT_OPTERR 1 + +/* Define to 1 if you have the global variable 'int optreset'. */ +/* #undef HAVE_INT_OPTRESET */ + +/* Define to 1 if you have the global variable 'int timezone'. */ +#define HAVE_INT_TIMEZONE 1 + +/* Define to 1 if you have support for IPv6. */ +#define HAVE_IPV6 1 + +/* Define to 1 if you have isinf(). */ +#define HAVE_ISINF 1 + +/* Define to 1 if you have the <langinfo.h> header file. */ +#define HAVE_LANGINFO_H 1 + +/* Define to 1 if you have the <ldap.h> header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +/* #undef HAVE_LIBCRYPTO */ + +/* Define to 1 if you have the `ldap' library (-lldap). */ +/* #undef HAVE_LIBLDAP */ + +/* Define to 1 if you have the `ldap_r' library (-lldap_r). */ +/* #undef HAVE_LIBLDAP_R */ + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `pam' library (-lpam). */ +/* #undef HAVE_LIBPAM */ + +/* Define if you have a function readline library */ +/* #undef HAVE_LIBREADLINE */ + +/* Define to 1 if you have the `selinux' library (-lselinux). */ +/* #undef HAVE_LIBSELINUX */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ + +/* Define to 1 if you have the `wldap32' library (-lwldap32). */ +/* #undef HAVE_LIBWLDAP32 */ + +/* Define to 1 if you have the `xml2' library (-lxml2). */ +/* #undef HAVE_LIBXML2 */ + +/* Define to 1 if you have the `xslt' library (-lxslt). */ +/* #undef HAVE_LIBXSLT */ + +/* Define to 1 if you have the `z' library (-lz). */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if constants of type 'long long int' should have the suffix LL. + */ +/* #undef HAVE_LL_CONSTANTS */ + +/* Define to 1 if the system has the type `locale_t'. */ +#define HAVE_LOCALE_T 1 + +/* Define to 1 if `long int' works and is 64 bits. */ +#define HAVE_LONG_INT_64 1 + +/* Define to 1 if the system has the type `long long int'. */ +#define HAVE_LONG_LONG_INT 1 + +/* Define to 1 if `long long int' works and is 64 bits. */ +/* #undef HAVE_LONG_LONG_INT_64 */ + +/* Define to 1 if you have the `mbstowcs_l' function. */ +/* #undef HAVE_MBSTOWCS_L */ + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if the system has the type `MINIDUMP_TYPE'. */ +/* #undef HAVE_MINIDUMP_TYPE */ + +/* Define to 1 if you have the `mkdtemp' function. */ +#define HAVE_MKDTEMP 1 + +/* Define to 1 if you have the <netinet/in.h> header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the <netinet/tcp.h> header file. */ +#define HAVE_NETINET_TCP_H 1 + +/* Define to 1 if you have the <net/if.h> header file. */ +#define HAVE_NET_IF_H 1 + +/* Define to 1 if you have the <ossp/uuid.h> header file. */ +/* #undef HAVE_OSSP_UUID_H */ + +/* Define to 1 if you have the <pam/pam_appl.h> header file. */ +/* #undef HAVE_PAM_PAM_APPL_H */ + +/* Define to 1 if you have the `poll' function. */ +#define HAVE_POLL 1 + +/* Define to 1 if you have the <poll.h> header file. */ +#define HAVE_POLL_H 1 + +/* Define to 1 if you have the `posix_fadvise' function. */ +#define HAVE_POSIX_FADVISE 1 + +/* Define to 1 if you have the POSIX signal interface. */ +#define HAVE_POSIX_SIGNALS 1 + +/* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */ +/* #undef HAVE_PPC_LWARX_MUTEX_HINT */ + +/* Define to 1 if you have the `pstat' function. */ +/* #undef HAVE_PSTAT */ + +/* Define to 1 if the PS_STRINGS thing exists. */ +/* #undef HAVE_PS_STRINGS */ + +/* Define if you have POSIX threads libraries and header files. */ +/* #undef HAVE_PTHREAD */ + +/* Define to 1 if you have the <pwd.h> header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `random' function. */ +#define HAVE_RANDOM 1 + +/* Define to 1 if you have the <readline.h> header file. */ +/* #undef HAVE_READLINE_H */ + +/* Define to 1 if you have the <readline/history.h> header file. */ +/* #undef HAVE_READLINE_HISTORY_H */ + +/* Define to 1 if you have the <readline/readline.h> header file. */ +/* #undef HAVE_READLINE_READLINE_H */ + +/* Define to 1 if you have the `readlink' function. */ +#define HAVE_READLINK 1 + +/* Define to 1 if you have the `rint' function. */ +#define HAVE_RINT 1 + +/* Define to 1 if you have the global variable + 'rl_completion_append_character'. */ +/* #undef HAVE_RL_COMPLETION_APPEND_CHARACTER */ + +/* Define to 1 if you have the `rl_completion_matches' function. */ +/* #undef HAVE_RL_COMPLETION_MATCHES */ + +/* Define to 1 if you have the `rl_filename_completion_function' function. */ +/* #undef HAVE_RL_FILENAME_COMPLETION_FUNCTION */ + +/* Define to 1 if you have the <security/pam_appl.h> header file. */ +/* #undef HAVE_SECURITY_PAM_APPL_H */ + +/* Define to 1 if you have the `setproctitle' function. */ +/* #undef HAVE_SETPROCTITLE */ + +/* Define to 1 if you have the `setsid' function. */ +#define HAVE_SETSID 1 + +/* Define to 1 if you have the `shm_open' function. */ +#define HAVE_SHM_OPEN 1 + +/* Define to 1 if you have the `sigprocmask' function. */ +#define HAVE_SIGPROCMASK 1 + +/* Define to 1 if you have sigsetjmp(). */ +#define HAVE_SIGSETJMP 1 + +/* Define to 1 if the system has the type `sig_atomic_t'. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if you have the `snprintf' function. */ +#define HAVE_SNPRINTF 1 + +/* Define to 1 if you have spinlocks. */ +#define HAVE_SPINLOCKS 1 + +/* Define to 1 if you have the `srandom' function. */ +#define HAVE_SRANDOM 1 + +/* Define to 1 if you have the `SSL_get_current_compression' function. */ +/* #undef HAVE_SSL_GET_CURRENT_COMPRESSION */ + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strerror_r' function. */ +#define HAVE_STRERROR_R 1 + +/* Define to 1 if you have the <strings.h> header file. */ +#define HAVE_STRINGS_H 1 + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcat' function. */ +/* #undef HAVE_STRLCAT */ + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef HAVE_STRLCPY */ + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* Define to 1 if you have the `strtoq' function. */ +/* #undef HAVE_STRTOQ */ + +/* Define to 1 if you have the `strtoull' function. */ +#define HAVE_STRTOULL 1 + +/* Define to 1 if you have the `strtouq' function. */ +/* #undef HAVE_STRTOUQ */ + +/* Define to 1 if the system has the type `struct addrinfo'. */ +#define HAVE_STRUCT_ADDRINFO 1 + +/* Define to 1 if the system has the type `struct cmsgcred'. */ +/* #undef HAVE_STRUCT_CMSGCRED */ + +/* Define to 1 if the system has the type `struct option'. */ +#define HAVE_STRUCT_OPTION 1 + +/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */ +/* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */ + +/* Define to 1 if the system has the type `struct sockaddr_storage'. */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */ +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1 + +/* Define to 1 if `ss_len' is a member of `struct sockaddr_storage'. */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */ + +/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */ + +/* Define to 1 if `__ss_len' is a member of `struct sockaddr_storage'. */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN */ + +/* Define to 1 if `tm_zone' is a member of `struct tm'. */ +#define HAVE_STRUCT_TM_TM_ZONE 1 + +/* Define to 1 if you have the `symlink' function. */ +#define HAVE_SYMLINK 1 + +/* Define to 1 if you have the `sync_file_range' function. */ +#define HAVE_SYNC_FILE_RANGE 1 + +/* Define to 1 if you have the syslog interface. */ +#define HAVE_SYSLOG 1 + +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +#define HAVE_SYS_IOCTL_H 1 + +/* Define to 1 if you have the <sys/ipc.h> header file. */ +#define HAVE_SYS_IPC_H 1 + +/* Define to 1 if you have the <sys/poll.h> header file. */ +#define HAVE_SYS_POLL_H 1 + +/* Define to 1 if you have the <sys/pstat.h> header file. */ +/* #undef HAVE_SYS_PSTAT_H */ + +/* Define to 1 if you have the <sys/resource.h> header file. */ +#define HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have the <sys/select.h> header file. */ +#define HAVE_SYS_SELECT_H 1 + +/* Define to 1 if you have the <sys/sem.h> header file. */ +#define HAVE_SYS_SEM_H 1 + +/* Define to 1 if you have the <sys/shm.h> header file. */ +#define HAVE_SYS_SHM_H 1 + +/* Define to 1 if you have the <sys/socket.h> header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the <sys/sockio.h> header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/tas.h> header file. */ +/* #undef HAVE_SYS_TAS_H */ + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <sys/ucred.h> header file. */ +/* #undef HAVE_SYS_UCRED_H */ + +/* Define to 1 if you have the <sys/un.h> header file. */ +#define HAVE_SYS_UN_H 1 + +/* Define to 1 if you have the <termios.h> header file. */ +#define HAVE_TERMIOS_H 1 + +/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use + `HAVE_STRUCT_TM_TM_ZONE' instead. */ +#define HAVE_TM_ZONE 1 + +/* Define to 1 if you have the `towlower' function. */ +#define HAVE_TOWLOWER 1 + +/* Define to 1 if you have the external array `tzname'. */ +#define HAVE_TZNAME 1 + +/* Define to 1 if you have the <ucred.h> header file. */ +/* #undef HAVE_UCRED_H */ + +/* Define to 1 if the system has the type `uint64'. */ +/* #undef HAVE_UINT64 */ + +/* Define to 1 if the system has the type `uint8'. */ +/* #undef HAVE_UINT8 */ + +/* Define to 1 if the system has the type `uintptr_t'. */ +#define HAVE_UINTPTR_T 1 + +/* Define to 1 if the system has the type `union semun'. */ +/* #undef HAVE_UNION_SEMUN */ + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have unix sockets. */ +#define HAVE_UNIX_SOCKETS 1 + +/* Define to 1 if you have the `unsetenv' function. */ +#define HAVE_UNSETENV 1 + +/* Define to 1 if the system has the type `unsigned long long int'. */ +#define HAVE_UNSIGNED_LONG_LONG_INT 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the `utimes' function. */ +#define HAVE_UTIMES 1 + +/* Define to 1 if you have the <utime.h> header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if you have BSD UUID support. */ +/* #undef HAVE_UUID_BSD */ + +/* Define to 1 if you have E2FS UUID support. */ +/* #undef HAVE_UUID_E2FS */ + +/* Define to 1 if you have the <uuid.h> header file. */ +/* #undef HAVE_UUID_H */ + +/* Define to 1 if you have OSSP UUID support. */ +/* #undef HAVE_UUID_OSSP */ + +/* Define to 1 if you have the <uuid/uuid.h> header file. */ +/* #undef HAVE_UUID_UUID_H */ + +/* Define to 1 if you have the `vsnprintf' function. */ +#define HAVE_VSNPRINTF 1 + +/* Define to 1 if you have the <wchar.h> header file. */ +#define HAVE_WCHAR_H 1 + +/* Define to 1 if you have the `wcstombs' function. */ +#define HAVE_WCSTOMBS 1 + +/* Define to 1 if you have the `wcstombs_l' function. */ +/* #undef HAVE_WCSTOMBS_L */ + +/* Define to 1 if you have the <wctype.h> header file. */ +#define HAVE_WCTYPE_H 1 + +/* Define to 1 if you have the <winldap.h> header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if your compiler understands __builtin_constant_p. */ +#define HAVE__BUILTIN_CONSTANT_P 1 + +/* Define to 1 if your compiler understands __builtin_types_compatible_p. */ +#define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1 + +/* Define to 1 if your compiler understands __builtin_unreachable. */ +#define HAVE__BUILTIN_UNREACHABLE 1 + +/* Define to 1 if your compiler understands _Static_assert. */ +#define HAVE__STATIC_ASSERT 1 + +/* Define to 1 if your compiler understands __VA_ARGS__ in macros. */ +#define HAVE__VA_ARGS 1 + +/* Define to the appropriate snprintf format for 64-bit ints. */ +#define INT64_FORMAT "%ld" + +/* Define to 1 if `locale_t' requires <xlocale.h>. */ +/* #undef LOCALE_T_IN_XLOCALE */ + +/* Define as the maximum alignment requirement of any C data type. */ +#define MAXIMUM_ALIGNOF 8 + +/* Define bytes to use libc memset(). */ +#define MEMSET_LOOP_LIMIT 1024 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "pgsql-bugs@postgresql.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "PostgreSQL" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "PostgreSQL 9.4.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "postgresql" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "9.4.0" + +/* Define to the name of a signed 64-bit integer type. */ +#define PG_INT64_TYPE long int + +/* Define to the name of the default PostgreSQL service principal in Kerberos + (GSSAPI). (--with-krb-srvnam=NAME) */ +#define PG_KRB_SRVNAM "postgres" + +/* PostgreSQL major version as a string */ +#define PG_MAJORVERSION "9.4" + +/* Define to 1 if "static inline" works without unwanted warnings from + compilations where static inline functions are defined but not called. */ +#define PG_USE_INLINE 1 + +/* PostgreSQL version as a string */ +#define PG_VERSION "9.4.0" + +/* PostgreSQL version as a number */ +#define PG_VERSION_NUM 90400 + +/* A string containing the version number, platform, and C compiler */ +#define PG_VERSION_STR "PostgreSQL 9.4.0 on i686-pc-linux-gnu, compiled by gcc (Ubuntu/Linaro 4.7.2-2ubuntu1) 4.7.2, 64-bit" + +/* Define to 1 to allow profiling output to be saved separately for each + process. */ +/* #undef PROFILE_PID_DIR */ + +/* Define to the necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef PTHREAD_CREATE_JOINABLE */ + +/* RELSEG_SIZE is the maximum number of blocks allowed in one disk file. Thus, + the maximum size of a single file is RELSEG_SIZE * BLCKSZ; relations bigger + than that are divided into multiple files. RELSEG_SIZE * BLCKSZ must be + less than your OS' limit on file size. This is often 2 GB or 4GB in a + 32-bit operating system, unless you have large file support enabled. By + default, we make the limit 1 GB to avoid any possible integer-overflow + problems within the OS. A limit smaller than necessary only means we divide + a large relation into more chunks than necessary, so it seems best to err + in the direction of a small limit. A power-of-2 value is recommended to + save a few cycles in md.c, but is not absolutely required. Changing + RELSEG_SIZE requires an initdb. */ +#define RELSEG_SIZE 131072 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 8 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 8 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 8 + +/* The size of `void *', as computed by sizeof. */ +#define SIZEOF_VOID_P 8 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if strerror_r() returns a int. */ +/* #undef STRERROR_R_INT */ + +/* Define to 1 if your <sys/time.h> declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Define to the appropriate snprintf format for unsigned 64-bit ints. */ +#define UINT64_FORMAT "%lu" + +/* Define to 1 to build with assertion checks. (--enable-cassert) */ +/* #undef USE_ASSERT_CHECKING */ + +/* Define to 1 to build with Bonjour support. (--with-bonjour) */ +/* #undef USE_BONJOUR */ + +/* Define to 1 if you want float4 values to be passed by value. + (--enable-float4-byval) */ +#define USE_FLOAT4_BYVAL 1 + +/* Define to 1 if you want float8, int8, etc values to be passed by value. + (--enable-float8-byval) */ +#define USE_FLOAT8_BYVAL 1 + +/* Define to 1 if you want 64-bit integer timestamp and interval support. + (--enable-integer-datetimes) */ +#define USE_INTEGER_DATETIMES 1 + +/* Define to 1 to build with LDAP support. (--with-ldap) */ +/* #undef USE_LDAP */ + +/* Define to 1 to build with XML support. (--with-libxml) */ +/* #undef USE_LIBXML */ + +/* Define to 1 to use XSLT support when building contrib/xml2. + (--with-libxslt) */ +/* #undef USE_LIBXSLT */ + +/* Define to select named POSIX semaphores. */ +/* #undef USE_NAMED_POSIX_SEMAPHORES */ + +/* Define to 1 to build with PAM support. (--with-pam) */ +/* #undef USE_PAM */ + +/* Use replacement snprintf() functions. */ +/* #undef USE_REPL_SNPRINTF */ + +/* Define to build with (Open)SSL support. (--with-openssl) */ +/* #undef USE_SSL */ + +/* Define to select SysV-style semaphores. */ +#define USE_SYSV_SEMAPHORES 1 + +/* Define to select SysV-style shared memory. */ +#define USE_SYSV_SHARED_MEMORY 1 + +/* Define to select unnamed POSIX semaphores. */ +/* #undef USE_UNNAMED_POSIX_SEMAPHORES */ + +/* Define to select Win32-style semaphores. */ +/* #undef USE_WIN32_SEMAPHORES */ + +/* Define to select Win32-style shared memory. */ +/* #undef USE_WIN32_SHARED_MEMORY */ + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Size of a WAL file block. This need have no particular relation to BLCKSZ. + XLOG_BLCKSZ must be a power of 2, and if your system supports O_DIRECT I/O, + XLOG_BLCKSZ must be a multiple of the alignment requirement for direct-I/O + buffers, else direct I/O may fail. Changing XLOG_BLCKSZ requires an initdb. + */ +#define XLOG_BLCKSZ 8192 + +/* XLOG_SEG_SIZE is the size of a single WAL file. This must be a power of 2 + and larger than XLOG_BLCKSZ (preferably, a great deal larger than + XLOG_BLCKSZ). Changing XLOG_SEG_SIZE requires an initdb. */ +#define XLOG_SEG_SIZE (16 * 1024 * 1024) + + + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +/* #undef _LARGEFILE_SOURCE */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to the type of a signed integer type wide enough to hold a pointer, + if such a type exists, and if the system does not define it. */ +/* #undef intptr_t */ + +/* Define to empty if the C compiler does not understand signed types. */ +/* #undef signed */ + +/* Define to the type of an unsigned integer type wide enough to hold a + pointer, if such a type exists, and if the system does not define it. */ +/* #undef uintptr_t */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/Platforms/pg_config-windows32.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,863 @@ +/* src/include/pg_config.h. Generated from pg_config.h.in by configure. */ +/* src/include/pg_config.h.in. Generated from configure.in by autoheader. */ + +/* Define to the type of arg 1 of 'accept' */ +#define ACCEPT_TYPE_ARG1 unsigned int + +/* Define to the type of arg 2 of 'accept' */ +#define ACCEPT_TYPE_ARG2 struct sockaddr * + +/* Define to the type of arg 3 of 'accept' */ +#define ACCEPT_TYPE_ARG3 int + +/* Define to the return type of 'accept' */ +#define ACCEPT_TYPE_RETURN unsigned int PASCAL + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* The normal alignment of `double', in bytes. */ +#define ALIGNOF_DOUBLE 8 + +/* The normal alignment of `int', in bytes. */ +#define ALIGNOF_INT 4 + +/* The normal alignment of `long', in bytes. */ +#define ALIGNOF_LONG 4 + +/* The normal alignment of `long long int', in bytes. */ +#define ALIGNOF_LONG_LONG_INT 8 + +/* The normal alignment of `short', in bytes. */ +#define ALIGNOF_SHORT 2 + +/* Size of a disk block --- this also limits the size of a tuple. You can set + it bigger if you need bigger tuples (although TOAST should reduce the need + to have large tuples, since fields can be spread across multiple tuples). + BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is + currently 2^15 (32768). This is determined by the 15-bit widths of the + lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h). + Changing BLCKSZ requires an initdb. */ +#define BLCKSZ 8192 + +/* Define to the default TCP port number on which the server listens and to + which clients will try to connect. This can be overridden at run-time, but + it's convenient if your clients have the right default compiled in. + (--with-pgport=PORTNUM) */ +#define DEF_PGPORT 5432 + +/* Define to the default TCP port number as a string constant. */ +#define DEF_PGPORT_STR "5432" + +/* Define to build with GSSAPI support. (--with-gssapi) */ +/* #undef ENABLE_GSS */ + +/* Define to 1 if you want National Language Support. (--enable-nls) */ +/* #undef ENABLE_NLS */ + +/* Define to 1 to build client libraries as thread-safe code. + (--enable-thread-safety) */ +#define ENABLE_THREAD_SAFETY 1 + +/* Define to nothing if C supports flexible array members, and to 1 if it does + not. That way, with a declaration like `struct s { int n; double + d[FLEXIBLE_ARRAY_MEMBER]; };', the struct hack can be used with pre-C99 + compilers. When computing the size of such an object, don't use 'sizeof + (struct s)' as it overestimates the size. Use 'offsetof (struct s, d)' + instead. Don't use 'offsetof (struct s, d[0])', as this doesn't work with + MSVC and with C++ compilers. */ +#define FLEXIBLE_ARRAY_MEMBER /**/ + +/* float4 values are passed by value if 'true', by reference if 'false' */ +#define FLOAT4PASSBYVAL true + +/* float8, int8, and related values are passed by value if 'true', by + reference if 'false' */ +#define FLOAT8PASSBYVAL false + +/* Define to 1 if getpwuid_r() takes a 5th argument. */ +/* #undef GETPWUID_R_5ARG */ + +/* Define to 1 if gettimeofday() takes only 1 argument. */ +/* #undef GETTIMEOFDAY_1ARG */ + +#ifdef GETTIMEOFDAY_1ARG +# define gettimeofday(a,b) gettimeofday(a) +#endif + +/* Define to 1 if you have the `append_history' function. */ +/* #undef HAVE_APPEND_HISTORY */ + +/* Define to 1 if you have the `cbrt' function. */ +#define HAVE_CBRT 1 + +/* Define to 1 if you have the `class' function. */ +/* #undef HAVE_CLASS */ + +/* Define to 1 if you have the <crtdefs.h> header file. */ +#define HAVE_CRTDEFS_H 1 + +/* Define to 1 if you have the `crypt' function. */ +/* #undef HAVE_CRYPT */ + +/* Define to 1 if you have the <crypt.h> header file. */ +/* #undef HAVE_CRYPT_H */ + +/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you + don't. */ +#define HAVE_DECL_FDATASYNC 0 + +/* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you + don't. */ +#define HAVE_DECL_F_FULLFSYNC 0 + +/* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you + don't. */ +#define HAVE_DECL_POSIX_FADVISE 0 + +/* Define to 1 if you have the declaration of `snprintf', and to 0 if you + don't. */ +#define HAVE_DECL_SNPRINTF 1 + +/* Define to 1 if you have the declaration of `strlcat', and to 0 if you + don't. */ +#define HAVE_DECL_STRLCAT 0 + +/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you + don't. */ +#define HAVE_DECL_STRLCPY 0 + +/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you + don't. */ +#define HAVE_DECL_SYS_SIGLIST 0 + +/* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you + don't. */ +#define HAVE_DECL_VSNPRINTF 1 + +/* Define to 1 if you have the <dld.h> header file. */ +/* #undef HAVE_DLD_H */ + +/* Define to 1 if you have the `dlopen' function. */ +/* #undef HAVE_DLOPEN */ + +/* Define to 1 if you have the <editline/history.h> header file. */ +/* #undef HAVE_EDITLINE_HISTORY_H */ + +/* Define to 1 if you have the <editline/readline.h> header file. */ +/* #undef HAVE_EDITLINE_READLINE_H */ + +/* Define to 1 if you have the `fdatasync' function. */ +/* #undef HAVE_FDATASYNC */ + +/* Define to 1 if you have the `fls' function. */ +/* #undef HAVE_FLS */ + +/* Define to 1 if you have the `fpclass' function. */ +/* #undef HAVE_FPCLASS */ + +/* Define to 1 if you have the `fp_class' function. */ +/* #undef HAVE_FP_CLASS */ + +/* Define to 1 if you have the `fp_class_d' function. */ +/* #undef HAVE_FP_CLASS_D */ + +/* Define to 1 if you have the <fp_class.h> header file. */ +/* #undef HAVE_FP_CLASS_H */ + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#define HAVE_FSEEKO 1 + +/* Define to 1 if your compiler understands __func__. */ +#define HAVE_FUNCNAME__FUNC 1 + +/* Define to 1 if your compiler understands __FUNCTION__. */ +/* #undef HAVE_FUNCNAME__FUNCTION */ + +/* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */ +#define HAVE_GCC_INT_ATOMICS 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +/* #undef HAVE_GETADDRINFO */ + +/* Define to 1 if you have the `gethostbyname_r' function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* Define to 1 if you have the `getifaddrs' function. */ +/* #undef HAVE_GETIFADDRS */ + +/* Define to 1 if you have the `getopt' function. */ +#define HAVE_GETOPT 1 + +/* Define to 1 if you have the <getopt.h> header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the `getopt_long' function. */ +#define HAVE_GETOPT_LONG 1 + +/* Define to 1 if you have the `getpeereid' function. */ +#define HAVE_GETPEEREID 1 + +/* Define to 1 if you have the `getpeerucred' function. */ +/* #undef HAVE_GETPEERUCRED */ + +/* Define to 1 if you have the `getpwuid_r' function. */ +/* #undef HAVE_GETPWUID_R */ + +/* Define to 1 if you have the `getrlimit' function. */ +/* #undef HAVE_GETRLIMIT */ + +/* Define to 1 if you have the `getrusage' function. */ +/* #undef HAVE_GETRUSAGE */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the <gssapi/gssapi.h> header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the <gssapi.h> header file. */ +/* #undef HAVE_GSSAPI_H */ + +/* Define to 1 if you have the <history.h> header file. */ +/* #undef HAVE_HISTORY_H */ + +/* Define to 1 if you have the `history_truncate_file' function. */ +/* #undef HAVE_HISTORY_TRUNCATE_FILE */ + +/* Define to 1 if you have the <ieeefp.h> header file. */ +/* #undef HAVE_IEEEFP_H */ + +/* Define to 1 if you have the <ifaddrs.h> header file. */ +/* #undef HAVE_IFADDRS_H */ + +/* Define to 1 if you have the `inet_aton' function. */ +/* #undef HAVE_INET_ATON */ + +/* Define to 1 if the system has the type `int64'. */ +/* #undef HAVE_INT64 */ + +/* Define to 1 if the system has the type `int8'. */ +/* #undef HAVE_INT8 */ + +/* Define to 1 if the system has the type `intptr_t'. */ +#define HAVE_INTPTR_T 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the global variable 'int opterr'. */ +#define HAVE_INT_OPTERR 1 + +/* Define to 1 if you have the global variable 'int optreset'. */ +#define HAVE_INT_OPTRESET 1 + +/* Define to 1 if you have the global variable 'int timezone'. */ +#define HAVE_INT_TIMEZONE 1 + +/* Define to 1 if you have support for IPv6. */ +#define HAVE_IPV6 1 + +/* Define to 1 if you have isinf(). */ +#define HAVE_ISINF 1 + +/* Define to 1 if you have the <langinfo.h> header file. */ +/* #undef HAVE_LANGINFO_H */ + +/* Define to 1 if you have the <ldap.h> header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +/* #undef HAVE_LIBCRYPTO */ + +/* Define to 1 if you have the `ldap' library (-lldap). */ +/* #undef HAVE_LIBLDAP */ + +/* Define to 1 if you have the `ldap_r' library (-lldap_r). */ +/* #undef HAVE_LIBLDAP_R */ + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `pam' library (-lpam). */ +/* #undef HAVE_LIBPAM */ + +/* Define if you have a function readline library */ +/* #undef HAVE_LIBREADLINE */ + +/* Define to 1 if you have the `selinux' library (-lselinux). */ +/* #undef HAVE_LIBSELINUX */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ + +/* Define to 1 if you have the `wldap32' library (-lwldap32). */ +/* #undef HAVE_LIBWLDAP32 */ + +/* Define to 1 if you have the `xml2' library (-lxml2). */ +/* #undef HAVE_LIBXML2 */ + +/* Define to 1 if you have the `xslt' library (-lxslt). */ +/* #undef HAVE_LIBXSLT */ + +/* Define to 1 if you have the `z' library (-lz). */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if constants of type 'long long int' should have the suffix LL. + */ +#define HAVE_LL_CONSTANTS 1 + +/* Define to 1 if the system has the type `locale_t'. */ +/* #undef HAVE_LOCALE_T */ + +/* Define to 1 if `long int' works and is 64 bits. */ +/* #undef HAVE_LONG_INT_64 */ + +/* Define to 1 if the system has the type `long long int'. */ +#define HAVE_LONG_LONG_INT 1 + +/* Define to 1 if `long long int' works and is 64 bits. */ +#define HAVE_LONG_LONG_INT_64 1 + +/* Define to 1 if you have the `mbstowcs_l' function. */ +/* #undef HAVE_MBSTOWCS_L */ + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if the system has the type `MINIDUMP_TYPE'. */ +#define HAVE_MINIDUMP_TYPE 1 + +/* Define to 1 if you have the `mkdtemp' function. */ +/* #undef HAVE_MKDTEMP */ + +/* Define to 1 if you have the <netinet/in.h> header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the <netinet/tcp.h> header file. */ +/* #undef HAVE_NETINET_TCP_H */ + +/* Define to 1 if you have the <net/if.h> header file. */ +/* #undef HAVE_NET_IF_H */ + +/* Define to 1 if you have the <ossp/uuid.h> header file. */ +/* #undef HAVE_OSSP_UUID_H */ + +/* Define to 1 if you have the <pam/pam_appl.h> header file. */ +/* #undef HAVE_PAM_PAM_APPL_H */ + +/* Define to 1 if you have the `poll' function. */ +/* #undef HAVE_POLL */ + +/* Define to 1 if you have the <poll.h> header file. */ +/* #undef HAVE_POLL_H */ + +/* Define to 1 if you have the `posix_fadvise' function. */ +/* #undef HAVE_POSIX_FADVISE */ + +/* Define to 1 if you have the POSIX signal interface. */ +/* #undef HAVE_POSIX_SIGNALS */ + +/* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */ +/* #undef HAVE_PPC_LWARX_MUTEX_HINT */ + +/* Define to 1 if you have the `pstat' function. */ +/* #undef HAVE_PSTAT */ + +/* Define to 1 if the PS_STRINGS thing exists. */ +/* #undef HAVE_PS_STRINGS */ + +/* Define if you have POSIX threads libraries and header files. */ +/* #undef HAVE_PTHREAD */ + +/* Define to 1 if you have the <pwd.h> header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `random' function. */ +/* #undef HAVE_RANDOM */ + +/* Define to 1 if you have the <readline.h> header file. */ +/* #undef HAVE_READLINE_H */ + +/* Define to 1 if you have the <readline/history.h> header file. */ +/* #undef HAVE_READLINE_HISTORY_H */ + +/* Define to 1 if you have the <readline/readline.h> header file. */ +/* #undef HAVE_READLINE_READLINE_H */ + +/* Define to 1 if you have the `readlink' function. */ +/* #undef HAVE_READLINK */ + +/* Define to 1 if you have the `rint' function. */ +#define HAVE_RINT 1 + +/* Define to 1 if you have the global variable + 'rl_completion_append_character'. */ +/* #undef HAVE_RL_COMPLETION_APPEND_CHARACTER */ + +/* Define to 1 if you have the `rl_completion_matches' function. */ +/* #undef HAVE_RL_COMPLETION_MATCHES */ + +/* Define to 1 if you have the `rl_filename_completion_function' function. */ +/* #undef HAVE_RL_FILENAME_COMPLETION_FUNCTION */ + +/* Define to 1 if you have the <security/pam_appl.h> header file. */ +/* #undef HAVE_SECURITY_PAM_APPL_H */ + +/* Define to 1 if you have the `setproctitle' function. */ +/* #undef HAVE_SETPROCTITLE */ + +/* Define to 1 if you have the `setsid' function. */ +/* #undef HAVE_SETSID */ + +/* Define to 1 if you have the `shm_open' function. */ +/* #undef HAVE_SHM_OPEN */ + +/* Define to 1 if you have the `sigprocmask' function. */ +/* #undef HAVE_SIGPROCMASK */ + +/* Define to 1 if you have sigsetjmp(). */ +/* #undef HAVE_SIGSETJMP */ + +/* Define to 1 if the system has the type `sig_atomic_t'. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if you have the `snprintf' function. */ +/* #undef HAVE_SNPRINTF */ + +/* Define to 1 if you have spinlocks. */ +#define HAVE_SPINLOCKS 1 + +/* Define to 1 if you have the `srandom' function. */ +/* #undef HAVE_SRANDOM */ + +/* Define to 1 if you have the `SSL_get_current_compression' function. */ +/* #undef HAVE_SSL_GET_CURRENT_COMPRESSION */ + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strerror_r' function. */ +/* #undef HAVE_STRERROR_R */ + +/* Define to 1 if you have the <strings.h> header file. */ +/* #undef HAVE_STRINGS_H */ + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcat' function. */ +/* #undef HAVE_STRLCAT */ + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef HAVE_STRLCPY */ + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* Define to 1 if you have the `strtoq' function. */ +/* #undef HAVE_STRTOQ */ + +/* Define to 1 if you have the `strtoull' function. */ +#define HAVE_STRTOULL 1 + +/* Define to 1 if you have the `strtouq' function. */ +/* #undef HAVE_STRTOUQ */ + +/* Define to 1 if the system has the type `struct addrinfo'. */ +#define HAVE_STRUCT_ADDRINFO 1 + +/* Define to 1 if the system has the type `struct cmsgcred'. */ +/* #undef HAVE_STRUCT_CMSGCRED */ + +/* Define to 1 if the system has the type `struct option'. */ +#define HAVE_STRUCT_OPTION 1 + +/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */ +/* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */ + +/* Define to 1 if the system has the type `struct sockaddr_storage'. */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */ +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1 + +/* Define to 1 if `ss_len' is a member of `struct sockaddr_storage'. */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */ + +/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */ + +/* Define to 1 if `__ss_len' is a member of `struct sockaddr_storage'. */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN */ + +/* Define to 1 if `tm_zone' is a member of `struct tm'. */ +/* #undef HAVE_STRUCT_TM_TM_ZONE */ + +/* Define to 1 if you have the `symlink' function. */ +#define HAVE_SYMLINK 1 + +/* Define to 1 if you have the `sync_file_range' function. */ +/* #undef HAVE_SYNC_FILE_RANGE */ + +/* Define to 1 if you have the syslog interface. */ +/* #undef HAVE_SYSLOG */ + +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +/* #undef HAVE_SYS_IOCTL_H */ + +/* Define to 1 if you have the <sys/ipc.h> header file. */ +/* #undef HAVE_SYS_IPC_H */ + +/* Define to 1 if you have the <sys/poll.h> header file. */ +/* #undef HAVE_SYS_POLL_H */ + +/* Define to 1 if you have the <sys/pstat.h> header file. */ +/* #undef HAVE_SYS_PSTAT_H */ + +/* Define to 1 if you have the <sys/resource.h> header file. */ +/* #undef HAVE_SYS_RESOURCE_H */ + +/* Define to 1 if you have the <sys/select.h> header file. */ +/* #undef HAVE_SYS_SELECT_H */ + +/* Define to 1 if you have the <sys/sem.h> header file. */ +/* #undef HAVE_SYS_SEM_H */ + +/* Define to 1 if you have the <sys/shm.h> header file. */ +/* #undef HAVE_SYS_SHM_H */ + +/* Define to 1 if you have the <sys/socket.h> header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the <sys/sockio.h> header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/tas.h> header file. */ +/* #undef HAVE_SYS_TAS_H */ + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <sys/ucred.h> header file. */ +/* #undef HAVE_SYS_UCRED_H */ + +/* Define to 1 if you have the <sys/un.h> header file. */ +/* #undef HAVE_SYS_UN_H */ + +/* Define to 1 if you have the <termios.h> header file. */ +/* #undef HAVE_TERMIOS_H */ + +/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use + `HAVE_STRUCT_TM_TM_ZONE' instead. */ +/* #undef HAVE_TM_ZONE */ + +/* Define to 1 if you have the `towlower' function. */ +#define HAVE_TOWLOWER 1 + +/* Define to 1 if you have the external array `tzname'. */ +/* #undef HAVE_TZNAME */ + +/* Define to 1 if you have the <ucred.h> header file. */ +/* #undef HAVE_UCRED_H */ + +/* Define to 1 if the system has the type `uint64'. */ +/* #undef HAVE_UINT64 */ + +/* Define to 1 if the system has the type `uint8'. */ +/* #undef HAVE_UINT8 */ + +/* Define to 1 if the system has the type `uintptr_t'. */ +#define HAVE_UINTPTR_T 1 + +/* Define to 1 if the system has the type `union semun'. */ +/* #undef HAVE_UNION_SEMUN */ + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have unix sockets. */ +/* #undef HAVE_UNIX_SOCKETS */ + +/* Define to 1 if you have the `unsetenv' function. */ +#define HAVE_UNSETENV 1 + +/* Define to 1 if the system has the type `unsigned long long int'. */ +#define HAVE_UNSIGNED_LONG_LONG_INT 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the `utimes' function. */ +/* #undef HAVE_UTIMES */ + +/* Define to 1 if you have the <utime.h> header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if you have BSD UUID support. */ +/* #undef HAVE_UUID_BSD */ + +/* Define to 1 if you have E2FS UUID support. */ +/* #undef HAVE_UUID_E2FS */ + +/* Define to 1 if you have the <uuid.h> header file. */ +/* #undef HAVE_UUID_H */ + +/* Define to 1 if you have OSSP UUID support. */ +/* #undef HAVE_UUID_OSSP */ + +/* Define to 1 if you have the <uuid/uuid.h> header file. */ +/* #undef HAVE_UUID_UUID_H */ + +/* Define to 1 if you have the `vsnprintf' function. */ +/* #undef HAVE_VSNPRINTF */ + +/* Define to 1 if you have the <wchar.h> header file. */ +#define HAVE_WCHAR_H 1 + +/* Define to 1 if you have the `wcstombs' function. */ +#define HAVE_WCSTOMBS 1 + +/* Define to 1 if you have the `wcstombs_l' function. */ +/* #undef HAVE_WCSTOMBS_L */ + +/* Define to 1 if you have the <wctype.h> header file. */ +#define HAVE_WCTYPE_H 1 + +/* Define to 1 if you have the <winldap.h> header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if your compiler understands __builtin_constant_p. */ +#define HAVE__BUILTIN_CONSTANT_P 1 + +/* Define to 1 if your compiler understands __builtin_types_compatible_p. */ +#define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1 + +/* Define to 1 if your compiler understands __builtin_unreachable. */ +#define HAVE__BUILTIN_UNREACHABLE 1 + +/* Define to 1 if your compiler understands _Static_assert. */ +#define HAVE__STATIC_ASSERT 1 + +/* Define to 1 if your compiler understands __VA_ARGS__ in macros. */ +#define HAVE__VA_ARGS 1 + +/* Define to the appropriate snprintf format for 64-bit ints. */ +#define INT64_FORMAT "%lld" + +/* Define to 1 if `locale_t' requires <xlocale.h>. */ +/* #undef LOCALE_T_IN_XLOCALE */ + +/* Define as the maximum alignment requirement of any C data type. */ +#define MAXIMUM_ALIGNOF 8 + +/* Define bytes to use libc memset(). */ +#define MEMSET_LOOP_LIMIT 1024 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "pgsql-bugs@postgresql.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "PostgreSQL" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "PostgreSQL 9.4.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "postgresql" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "9.4.0" + +/* Define to the name of a signed 64-bit integer type. */ +#define PG_INT64_TYPE long long int + +/* Define to the name of the default PostgreSQL service principal in Kerberos + (GSSAPI). (--with-krb-srvnam=NAME) */ +#define PG_KRB_SRVNAM "postgres" + +/* PostgreSQL major version as a string */ +#define PG_MAJORVERSION "9.4" + +/* Define to 1 if "static inline" works without unwanted warnings from + compilations where static inline functions are defined but not called. */ +#define PG_USE_INLINE 1 + +/* PostgreSQL version as a string */ +#define PG_VERSION "9.4.0" + +/* PostgreSQL version as a number */ +#define PG_VERSION_NUM 90400 + +/* A string containing the version number, platform, and C compiler */ +#define PG_VERSION_STR "PostgreSQL 9.4.0 on i586-pc-mingw32msvc, compiled by i586-mingw32msvc-gcc (GCC) 4.6.3, 32-bit" + +/* Define to 1 to allow profiling output to be saved separately for each + process. */ +/* #undef PROFILE_PID_DIR */ + +/* Define to the necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef PTHREAD_CREATE_JOINABLE */ + +/* RELSEG_SIZE is the maximum number of blocks allowed in one disk file. Thus, + the maximum size of a single file is RELSEG_SIZE * BLCKSZ; relations bigger + than that are divided into multiple files. RELSEG_SIZE * BLCKSZ must be + less than your OS' limit on file size. This is often 2 GB or 4GB in a + 32-bit operating system, unless you have large file support enabled. By + default, we make the limit 1 GB to avoid any possible integer-overflow + problems within the OS. A limit smaller than necessary only means we divide + a large relation into more chunks than necessary, so it seems best to err + in the direction of a small limit. A power-of-2 value is recommended to + save a few cycles in md.c, but is not absolutely required. Changing + RELSEG_SIZE requires an initdb. */ +#define RELSEG_SIZE 131072 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 4 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `void *', as computed by sizeof. */ +#define SIZEOF_VOID_P 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if strerror_r() returns a int. */ +/* #undef STRERROR_R_INT */ + +/* Define to 1 if your <sys/time.h> declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Define to the appropriate snprintf format for unsigned 64-bit ints. */ +#define UINT64_FORMAT "%llu" + +/* Define to 1 to build with assertion checks. (--enable-cassert) */ +/* #undef USE_ASSERT_CHECKING */ + +/* Define to 1 to build with Bonjour support. (--with-bonjour) */ +/* #undef USE_BONJOUR */ + +/* Define to 1 if you want float4 values to be passed by value. + (--enable-float4-byval) */ +#define USE_FLOAT4_BYVAL 1 + +/* Define to 1 if you want float8, int8, etc values to be passed by value. + (--enable-float8-byval) */ +/* #undef USE_FLOAT8_BYVAL */ + +/* Define to 1 if you want 64-bit integer timestamp and interval support. + (--enable-integer-datetimes) */ +#define USE_INTEGER_DATETIMES 1 + +/* Define to 1 to build with LDAP support. (--with-ldap) */ +/* #undef USE_LDAP */ + +/* Define to 1 to build with XML support. (--with-libxml) */ +/* #undef USE_LIBXML */ + +/* Define to 1 to use XSLT support when building contrib/xml2. + (--with-libxslt) */ +/* #undef USE_LIBXSLT */ + +/* Define to select named POSIX semaphores. */ +/* #undef USE_NAMED_POSIX_SEMAPHORES */ + +/* Define to 1 to build with PAM support. (--with-pam) */ +/* #undef USE_PAM */ + +/* Use replacement snprintf() functions. */ +#define USE_REPL_SNPRINTF 1 + +/* Define to build with (Open)SSL support. (--with-openssl) */ +/* #undef USE_SSL */ + +/* Define to select SysV-style semaphores. */ +/* #undef USE_SYSV_SEMAPHORES */ + +/* Define to select SysV-style shared memory. */ +/* #undef USE_SYSV_SHARED_MEMORY */ + +/* Define to select unnamed POSIX semaphores. */ +/* #undef USE_UNNAMED_POSIX_SEMAPHORES */ + +/* Define to select Win32-style semaphores. */ +#define USE_WIN32_SEMAPHORES 1 + +/* Define to select Win32-style shared memory. */ +#define USE_WIN32_SHARED_MEMORY 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Size of a WAL file block. This need have no particular relation to BLCKSZ. + XLOG_BLCKSZ must be a power of 2, and if your system supports O_DIRECT I/O, + XLOG_BLCKSZ must be a multiple of the alignment requirement for direct-I/O + buffers, else direct I/O may fail. Changing XLOG_BLCKSZ requires an initdb. + */ +#define XLOG_BLCKSZ 8192 + +/* XLOG_SEG_SIZE is the size of a single WAL file. This must be a power of 2 + and larger than XLOG_BLCKSZ (preferably, a great deal larger than + XLOG_BLCKSZ). Changing XLOG_SEG_SIZE requires an initdb. */ +#define XLOG_SEG_SIZE (16 * 1024 * 1024) + + + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +/* #undef _LARGEFILE_SOURCE */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to the type of a signed integer type wide enough to hold a pointer, + if such a type exists, and if the system does not define it. */ +/* #undef intptr_t */ + +/* Define to empty if the C compiler does not understand signed types. */ +/* #undef signed */ + +/* Define to the type of an unsigned integer type wide enough to hold a + pointer, if such a type exists, and if the system does not define it. */ +/* #undef uintptr_t */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/Platforms/pg_config-windows64.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,863 @@ +/* src/include/pg_config.h. Generated from pg_config.h.in by configure. */ +/* src/include/pg_config.h.in. Generated from configure.in by autoheader. */ + +/* Define to the type of arg 1 of 'accept' */ +#define ACCEPT_TYPE_ARG1 unsigned int + +/* Define to the type of arg 2 of 'accept' */ +#define ACCEPT_TYPE_ARG2 struct sockaddr * + +/* Define to the type of arg 3 of 'accept' */ +#define ACCEPT_TYPE_ARG3 int + +/* Define to the return type of 'accept' */ +#define ACCEPT_TYPE_RETURN unsigned int PASCAL + +/* Define if building universal (internal helper macro) */ +/* #undef AC_APPLE_UNIVERSAL_BUILD */ + +/* The normal alignment of `double', in bytes. */ +#define ALIGNOF_DOUBLE 8 + +/* The normal alignment of `int', in bytes. */ +#define ALIGNOF_INT 4 + +/* The normal alignment of `long', in bytes. */ +#define ALIGNOF_LONG 4 + +/* The normal alignment of `long long int', in bytes. */ +#define ALIGNOF_LONG_LONG_INT 8 + +/* The normal alignment of `short', in bytes. */ +#define ALIGNOF_SHORT 2 + +/* Size of a disk block --- this also limits the size of a tuple. You can set + it bigger if you need bigger tuples (although TOAST should reduce the need + to have large tuples, since fields can be spread across multiple tuples). + BLCKSZ must be a power of 2. The maximum possible value of BLCKSZ is + currently 2^15 (32768). This is determined by the 15-bit widths of the + lp_off and lp_len fields in ItemIdData (see include/storage/itemid.h). + Changing BLCKSZ requires an initdb. */ +#define BLCKSZ 8192 + +/* Define to the default TCP port number on which the server listens and to + which clients will try to connect. This can be overridden at run-time, but + it's convenient if your clients have the right default compiled in. + (--with-pgport=PORTNUM) */ +#define DEF_PGPORT 5432 + +/* Define to the default TCP port number as a string constant. */ +#define DEF_PGPORT_STR "5432" + +/* Define to build with GSSAPI support. (--with-gssapi) */ +/* #undef ENABLE_GSS */ + +/* Define to 1 if you want National Language Support. (--enable-nls) */ +/* #undef ENABLE_NLS */ + +/* Define to 1 to build client libraries as thread-safe code. + (--enable-thread-safety) */ +#define ENABLE_THREAD_SAFETY 1 + +/* Define to nothing if C supports flexible array members, and to 1 if it does + not. That way, with a declaration like `struct s { int n; double + d[FLEXIBLE_ARRAY_MEMBER]; };', the struct hack can be used with pre-C99 + compilers. When computing the size of such an object, don't use 'sizeof + (struct s)' as it overestimates the size. Use 'offsetof (struct s, d)' + instead. Don't use 'offsetof (struct s, d[0])', as this doesn't work with + MSVC and with C++ compilers. */ +#define FLEXIBLE_ARRAY_MEMBER /**/ + +/* float4 values are passed by value if 'true', by reference if 'false' */ +#define FLOAT4PASSBYVAL true + +/* float8, int8, and related values are passed by value if 'true', by + reference if 'false' */ +#define FLOAT8PASSBYVAL false + +/* Define to 1 if getpwuid_r() takes a 5th argument. */ +/* #undef GETPWUID_R_5ARG */ + +/* Define to 1 if gettimeofday() takes only 1 argument. */ +/* #undef GETTIMEOFDAY_1ARG */ + +#ifdef GETTIMEOFDAY_1ARG +# define gettimeofday(a,b) gettimeofday(a) +#endif + +/* Define to 1 if you have the `append_history' function. */ +/* #undef HAVE_APPEND_HISTORY */ + +/* Define to 1 if you have the `cbrt' function. */ +#define HAVE_CBRT 1 + +/* Define to 1 if you have the `class' function. */ +/* #undef HAVE_CLASS */ + +/* Define to 1 if you have the <crtdefs.h> header file. */ +#define HAVE_CRTDEFS_H 1 + +/* Define to 1 if you have the `crypt' function. */ +/* #undef HAVE_CRYPT */ + +/* Define to 1 if you have the <crypt.h> header file. */ +/* #undef HAVE_CRYPT_H */ + +/* Define to 1 if you have the declaration of `fdatasync', and to 0 if you + don't. */ +#define HAVE_DECL_FDATASYNC 0 + +/* Define to 1 if you have the declaration of `F_FULLFSYNC', and to 0 if you + don't. */ +#define HAVE_DECL_F_FULLFSYNC 0 + +/* Define to 1 if you have the declaration of `posix_fadvise', and to 0 if you + don't. */ +#define HAVE_DECL_POSIX_FADVISE 0 + +/* Define to 1 if you have the declaration of `snprintf', and to 0 if you + don't. */ +#define HAVE_DECL_SNPRINTF 1 + +/* Define to 1 if you have the declaration of `strlcat', and to 0 if you + don't. */ +#define HAVE_DECL_STRLCAT 0 + +/* Define to 1 if you have the declaration of `strlcpy', and to 0 if you + don't. */ +#define HAVE_DECL_STRLCPY 0 + +/* Define to 1 if you have the declaration of `sys_siglist', and to 0 if you + don't. */ +#define HAVE_DECL_SYS_SIGLIST 0 + +/* Define to 1 if you have the declaration of `vsnprintf', and to 0 if you + don't. */ +#define HAVE_DECL_VSNPRINTF 1 + +/* Define to 1 if you have the <dld.h> header file. */ +/* #undef HAVE_DLD_H */ + +/* Define to 1 if you have the `dlopen' function. */ +/* #undef HAVE_DLOPEN */ + +/* Define to 1 if you have the <editline/history.h> header file. */ +/* #undef HAVE_EDITLINE_HISTORY_H */ + +/* Define to 1 if you have the <editline/readline.h> header file. */ +/* #undef HAVE_EDITLINE_READLINE_H */ + +/* Define to 1 if you have the `fdatasync' function. */ +/* #undef HAVE_FDATASYNC */ + +/* Define to 1 if you have the `fls' function. */ +/* #undef HAVE_FLS */ + +/* Define to 1 if you have the `fpclass' function. */ +/* #undef HAVE_FPCLASS */ + +/* Define to 1 if you have the `fp_class' function. */ +/* #undef HAVE_FP_CLASS */ + +/* Define to 1 if you have the `fp_class_d' function. */ +/* #undef HAVE_FP_CLASS_D */ + +/* Define to 1 if you have the <fp_class.h> header file. */ +/* #undef HAVE_FP_CLASS_H */ + +/* Define to 1 if fseeko (and presumably ftello) exists and is declared. */ +#define HAVE_FSEEKO 1 + +/* Define to 1 if your compiler understands __func__. */ +#define HAVE_FUNCNAME__FUNC 1 + +/* Define to 1 if your compiler understands __FUNCTION__. */ +/* #undef HAVE_FUNCNAME__FUNCTION */ + +/* Define to 1 if you have __sync_lock_test_and_set(int *) and friends. */ +#define HAVE_GCC_INT_ATOMICS 1 + +/* Define to 1 if you have the `getaddrinfo' function. */ +/* #undef HAVE_GETADDRINFO */ + +/* Define to 1 if you have the `gethostbyname_r' function. */ +/* #undef HAVE_GETHOSTBYNAME_R */ + +/* Define to 1 if you have the `getifaddrs' function. */ +/* #undef HAVE_GETIFADDRS */ + +/* Define to 1 if you have the `getopt' function. */ +#define HAVE_GETOPT 1 + +/* Define to 1 if you have the <getopt.h> header file. */ +#define HAVE_GETOPT_H 1 + +/* Define to 1 if you have the `getopt_long' function. */ +#define HAVE_GETOPT_LONG 1 + +/* Define to 1 if you have the `getpeereid' function. */ +#define HAVE_GETPEEREID 1 + +/* Define to 1 if you have the `getpeerucred' function. */ +/* #undef HAVE_GETPEERUCRED */ + +/* Define to 1 if you have the `getpwuid_r' function. */ +/* #undef HAVE_GETPWUID_R */ + +/* Define to 1 if you have the `getrlimit' function. */ +/* #undef HAVE_GETRLIMIT */ + +/* Define to 1 if you have the `getrusage' function. */ +/* #undef HAVE_GETRUSAGE */ + +/* Define to 1 if you have the `gettimeofday' function. */ +#define HAVE_GETTIMEOFDAY 1 + +/* Define to 1 if you have the <gssapi/gssapi.h> header file. */ +/* #undef HAVE_GSSAPI_GSSAPI_H */ + +/* Define to 1 if you have the <gssapi.h> header file. */ +/* #undef HAVE_GSSAPI_H */ + +/* Define to 1 if you have the <history.h> header file. */ +/* #undef HAVE_HISTORY_H */ + +/* Define to 1 if you have the `history_truncate_file' function. */ +/* #undef HAVE_HISTORY_TRUNCATE_FILE */ + +/* Define to 1 if you have the <ieeefp.h> header file. */ +/* #undef HAVE_IEEEFP_H */ + +/* Define to 1 if you have the <ifaddrs.h> header file. */ +/* #undef HAVE_IFADDRS_H */ + +/* Define to 1 if you have the `inet_aton' function. */ +/* #undef HAVE_INET_ATON */ + +/* Define to 1 if the system has the type `int64'. */ +/* #undef HAVE_INT64 */ + +/* Define to 1 if the system has the type `int8'. */ +/* #undef HAVE_INT8 */ + +/* Define to 1 if the system has the type `intptr_t'. */ +#define HAVE_INTPTR_T 1 + +/* Define to 1 if you have the <inttypes.h> header file. */ +#define HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the global variable 'int opterr'. */ +#define HAVE_INT_OPTERR 1 + +/* Define to 1 if you have the global variable 'int optreset'. */ +#define HAVE_INT_OPTRESET 1 + +/* Define to 1 if you have the global variable 'int timezone'. */ +#define HAVE_INT_TIMEZONE 1 + +/* Define to 1 if you have support for IPv6. */ +#define HAVE_IPV6 1 + +/* Define to 1 if you have isinf(). */ +#define HAVE_ISINF 1 + +/* Define to 1 if you have the <langinfo.h> header file. */ +/* #undef HAVE_LANGINFO_H */ + +/* Define to 1 if you have the <ldap.h> header file. */ +/* #undef HAVE_LDAP_H */ + +/* Define to 1 if you have the `crypto' library (-lcrypto). */ +/* #undef HAVE_LIBCRYPTO */ + +/* Define to 1 if you have the `ldap' library (-lldap). */ +/* #undef HAVE_LIBLDAP */ + +/* Define to 1 if you have the `ldap_r' library (-lldap_r). */ +/* #undef HAVE_LIBLDAP_R */ + +/* Define to 1 if you have the `m' library (-lm). */ +#define HAVE_LIBM 1 + +/* Define to 1 if you have the `pam' library (-lpam). */ +/* #undef HAVE_LIBPAM */ + +/* Define if you have a function readline library */ +/* #undef HAVE_LIBREADLINE */ + +/* Define to 1 if you have the `selinux' library (-lselinux). */ +/* #undef HAVE_LIBSELINUX */ + +/* Define to 1 if you have the `ssl' library (-lssl). */ +/* #undef HAVE_LIBSSL */ + +/* Define to 1 if you have the `wldap32' library (-lwldap32). */ +/* #undef HAVE_LIBWLDAP32 */ + +/* Define to 1 if you have the `xml2' library (-lxml2). */ +/* #undef HAVE_LIBXML2 */ + +/* Define to 1 if you have the `xslt' library (-lxslt). */ +/* #undef HAVE_LIBXSLT */ + +/* Define to 1 if you have the `z' library (-lz). */ +/* #undef HAVE_LIBZ */ + +/* Define to 1 if constants of type 'long long int' should have the suffix LL. + */ +#define HAVE_LL_CONSTANTS 1 + +/* Define to 1 if the system has the type `locale_t'. */ +/* #undef HAVE_LOCALE_T */ + +/* Define to 1 if `long int' works and is 64 bits. */ +/* #undef HAVE_LONG_INT_64 */ + +/* Define to 1 if the system has the type `long long int'. */ +#define HAVE_LONG_LONG_INT 1 + +/* Define to 1 if `long long int' works and is 64 bits. */ +#define HAVE_LONG_LONG_INT_64 1 + +/* Define to 1 if you have the `mbstowcs_l' function. */ +/* #undef HAVE_MBSTOWCS_L */ + +/* Define to 1 if you have the `memmove' function. */ +#define HAVE_MEMMOVE 1 + +/* Define to 1 if you have the <memory.h> header file. */ +#define HAVE_MEMORY_H 1 + +/* Define to 1 if the system has the type `MINIDUMP_TYPE'. */ +#define HAVE_MINIDUMP_TYPE 1 + +/* Define to 1 if you have the `mkdtemp' function. */ +/* #undef HAVE_MKDTEMP */ + +/* Define to 1 if you have the <netinet/in.h> header file. */ +#define HAVE_NETINET_IN_H 1 + +/* Define to 1 if you have the <netinet/tcp.h> header file. */ +/* #undef HAVE_NETINET_TCP_H */ + +/* Define to 1 if you have the <net/if.h> header file. */ +/* #undef HAVE_NET_IF_H */ + +/* Define to 1 if you have the <ossp/uuid.h> header file. */ +/* #undef HAVE_OSSP_UUID_H */ + +/* Define to 1 if you have the <pam/pam_appl.h> header file. */ +/* #undef HAVE_PAM_PAM_APPL_H */ + +/* Define to 1 if you have the `poll' function. */ +/* #undef HAVE_POLL */ + +/* Define to 1 if you have the <poll.h> header file. */ +/* #undef HAVE_POLL_H */ + +/* Define to 1 if you have the `posix_fadvise' function. */ +/* #undef HAVE_POSIX_FADVISE */ + +/* Define to 1 if you have the POSIX signal interface. */ +/* #undef HAVE_POSIX_SIGNALS */ + +/* Define to 1 if the assembler supports PPC's LWARX mutex hint bit. */ +/* #undef HAVE_PPC_LWARX_MUTEX_HINT */ + +/* Define to 1 if you have the `pstat' function. */ +/* #undef HAVE_PSTAT */ + +/* Define to 1 if the PS_STRINGS thing exists. */ +/* #undef HAVE_PS_STRINGS */ + +/* Define if you have POSIX threads libraries and header files. */ +/* #undef HAVE_PTHREAD */ + +/* Define to 1 if you have the <pwd.h> header file. */ +#define HAVE_PWD_H 1 + +/* Define to 1 if you have the `random' function. */ +/* #undef HAVE_RANDOM */ + +/* Define to 1 if you have the <readline.h> header file. */ +/* #undef HAVE_READLINE_H */ + +/* Define to 1 if you have the <readline/history.h> header file. */ +/* #undef HAVE_READLINE_HISTORY_H */ + +/* Define to 1 if you have the <readline/readline.h> header file. */ +/* #undef HAVE_READLINE_READLINE_H */ + +/* Define to 1 if you have the `readlink' function. */ +/* #undef HAVE_READLINK */ + +/* Define to 1 if you have the `rint' function. */ +#define HAVE_RINT 1 + +/* Define to 1 if you have the global variable + 'rl_completion_append_character'. */ +/* #undef HAVE_RL_COMPLETION_APPEND_CHARACTER */ + +/* Define to 1 if you have the `rl_completion_matches' function. */ +/* #undef HAVE_RL_COMPLETION_MATCHES */ + +/* Define to 1 if you have the `rl_filename_completion_function' function. */ +/* #undef HAVE_RL_FILENAME_COMPLETION_FUNCTION */ + +/* Define to 1 if you have the <security/pam_appl.h> header file. */ +/* #undef HAVE_SECURITY_PAM_APPL_H */ + +/* Define to 1 if you have the `setproctitle' function. */ +/* #undef HAVE_SETPROCTITLE */ + +/* Define to 1 if you have the `setsid' function. */ +/* #undef HAVE_SETSID */ + +/* Define to 1 if you have the `shm_open' function. */ +/* #undef HAVE_SHM_OPEN */ + +/* Define to 1 if you have the `sigprocmask' function. */ +/* #undef HAVE_SIGPROCMASK */ + +/* Define to 1 if you have sigsetjmp(). */ +/* #undef HAVE_SIGSETJMP */ + +/* Define to 1 if the system has the type `sig_atomic_t'. */ +#define HAVE_SIG_ATOMIC_T 1 + +/* Define to 1 if you have the `snprintf' function. */ +/* #undef HAVE_SNPRINTF */ + +/* Define to 1 if you have spinlocks. */ +#define HAVE_SPINLOCKS 1 + +/* Define to 1 if you have the `srandom' function. */ +/* #undef HAVE_SRANDOM */ + +/* Define to 1 if you have the `SSL_get_current_compression' function. */ +/* #undef HAVE_SSL_GET_CURRENT_COMPRESSION */ + +/* Define to 1 if you have the <stdint.h> header file. */ +#define HAVE_STDINT_H 1 + +/* Define to 1 if you have the <stdlib.h> header file. */ +#define HAVE_STDLIB_H 1 + +/* Define to 1 if you have the `strerror' function. */ +#define HAVE_STRERROR 1 + +/* Define to 1 if you have the `strerror_r' function. */ +/* #undef HAVE_STRERROR_R */ + +/* Define to 1 if you have the <strings.h> header file. */ +/* #undef HAVE_STRINGS_H */ + +/* Define to 1 if you have the <string.h> header file. */ +#define HAVE_STRING_H 1 + +/* Define to 1 if you have the `strlcat' function. */ +/* #undef HAVE_STRLCAT */ + +/* Define to 1 if you have the `strlcpy' function. */ +/* #undef HAVE_STRLCPY */ + +/* Define to 1 if you have the `strtoll' function. */ +#define HAVE_STRTOLL 1 + +/* Define to 1 if you have the `strtoq' function. */ +/* #undef HAVE_STRTOQ */ + +/* Define to 1 if you have the `strtoull' function. */ +#define HAVE_STRTOULL 1 + +/* Define to 1 if you have the `strtouq' function. */ +/* #undef HAVE_STRTOUQ */ + +/* Define to 1 if the system has the type `struct addrinfo'. */ +#define HAVE_STRUCT_ADDRINFO 1 + +/* Define to 1 if the system has the type `struct cmsgcred'. */ +/* #undef HAVE_STRUCT_CMSGCRED */ + +/* Define to 1 if the system has the type `struct option'. */ +#define HAVE_STRUCT_OPTION 1 + +/* Define to 1 if `sa_len' is a member of `struct sockaddr'. */ +/* #undef HAVE_STRUCT_SOCKADDR_SA_LEN */ + +/* Define to 1 if the system has the type `struct sockaddr_storage'. */ +#define HAVE_STRUCT_SOCKADDR_STORAGE 1 + +/* Define to 1 if `ss_family' is a member of `struct sockaddr_storage'. */ +#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1 + +/* Define to 1 if `ss_len' is a member of `struct sockaddr_storage'. */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE_SS_LEN */ + +/* Define to 1 if `__ss_family' is a member of `struct sockaddr_storage'. */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY */ + +/* Define to 1 if `__ss_len' is a member of `struct sockaddr_storage'. */ +/* #undef HAVE_STRUCT_SOCKADDR_STORAGE___SS_LEN */ + +/* Define to 1 if `tm_zone' is a member of `struct tm'. */ +/* #undef HAVE_STRUCT_TM_TM_ZONE */ + +/* Define to 1 if you have the `symlink' function. */ +#define HAVE_SYMLINK 1 + +/* Define to 1 if you have the `sync_file_range' function. */ +/* #undef HAVE_SYNC_FILE_RANGE */ + +/* Define to 1 if you have the syslog interface. */ +/* #undef HAVE_SYSLOG */ + +/* Define to 1 if you have the <sys/ioctl.h> header file. */ +/* #undef HAVE_SYS_IOCTL_H */ + +/* Define to 1 if you have the <sys/ipc.h> header file. */ +/* #undef HAVE_SYS_IPC_H */ + +/* Define to 1 if you have the <sys/poll.h> header file. */ +/* #undef HAVE_SYS_POLL_H */ + +/* Define to 1 if you have the <sys/pstat.h> header file. */ +/* #undef HAVE_SYS_PSTAT_H */ + +/* Define to 1 if you have the <sys/resource.h> header file. */ +/* #undef HAVE_SYS_RESOURCE_H */ + +/* Define to 1 if you have the <sys/select.h> header file. */ +/* #undef HAVE_SYS_SELECT_H */ + +/* Define to 1 if you have the <sys/sem.h> header file. */ +/* #undef HAVE_SYS_SEM_H */ + +/* Define to 1 if you have the <sys/shm.h> header file. */ +/* #undef HAVE_SYS_SHM_H */ + +/* Define to 1 if you have the <sys/socket.h> header file. */ +#define HAVE_SYS_SOCKET_H 1 + +/* Define to 1 if you have the <sys/sockio.h> header file. */ +/* #undef HAVE_SYS_SOCKIO_H */ + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#define HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the <sys/tas.h> header file. */ +/* #undef HAVE_SYS_TAS_H */ + +/* Define to 1 if you have the <sys/time.h> header file. */ +#define HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the <sys/types.h> header file. */ +#define HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the <sys/ucred.h> header file. */ +/* #undef HAVE_SYS_UCRED_H */ + +/* Define to 1 if you have the <sys/un.h> header file. */ +/* #undef HAVE_SYS_UN_H */ + +/* Define to 1 if you have the <termios.h> header file. */ +/* #undef HAVE_TERMIOS_H */ + +/* Define to 1 if your `struct tm' has `tm_zone'. Deprecated, use + `HAVE_STRUCT_TM_TM_ZONE' instead. */ +/* #undef HAVE_TM_ZONE */ + +/* Define to 1 if you have the `towlower' function. */ +#define HAVE_TOWLOWER 1 + +/* Define to 1 if you have the external array `tzname'. */ +/* #undef HAVE_TZNAME */ + +/* Define to 1 if you have the <ucred.h> header file. */ +/* #undef HAVE_UCRED_H */ + +/* Define to 1 if the system has the type `uint64'. */ +/* #undef HAVE_UINT64 */ + +/* Define to 1 if the system has the type `uint8'. */ +/* #undef HAVE_UINT8 */ + +/* Define to 1 if the system has the type `uintptr_t'. */ +#define HAVE_UINTPTR_T 1 + +/* Define to 1 if the system has the type `union semun'. */ +/* #undef HAVE_UNION_SEMUN */ + +/* Define to 1 if you have the <unistd.h> header file. */ +#define HAVE_UNISTD_H 1 + +/* Define to 1 if you have unix sockets. */ +/* #undef HAVE_UNIX_SOCKETS */ + +/* Define to 1 if you have the `unsetenv' function. */ +#define HAVE_UNSETENV 1 + +/* Define to 1 if the system has the type `unsigned long long int'. */ +#define HAVE_UNSIGNED_LONG_LONG_INT 1 + +/* Define to 1 if you have the `utime' function. */ +#define HAVE_UTIME 1 + +/* Define to 1 if you have the `utimes' function. */ +/* #undef HAVE_UTIMES */ + +/* Define to 1 if you have the <utime.h> header file. */ +#define HAVE_UTIME_H 1 + +/* Define to 1 if you have BSD UUID support. */ +/* #undef HAVE_UUID_BSD */ + +/* Define to 1 if you have E2FS UUID support. */ +/* #undef HAVE_UUID_E2FS */ + +/* Define to 1 if you have the <uuid.h> header file. */ +/* #undef HAVE_UUID_H */ + +/* Define to 1 if you have OSSP UUID support. */ +/* #undef HAVE_UUID_OSSP */ + +/* Define to 1 if you have the <uuid/uuid.h> header file. */ +/* #undef HAVE_UUID_UUID_H */ + +/* Define to 1 if you have the `vsnprintf' function. */ +/* #undef HAVE_VSNPRINTF */ + +/* Define to 1 if you have the <wchar.h> header file. */ +#define HAVE_WCHAR_H 1 + +/* Define to 1 if you have the `wcstombs' function. */ +#define HAVE_WCSTOMBS 1 + +/* Define to 1 if you have the `wcstombs_l' function. */ +/* #undef HAVE_WCSTOMBS_L */ + +/* Define to 1 if you have the <wctype.h> header file. */ +#define HAVE_WCTYPE_H 1 + +/* Define to 1 if you have the <winldap.h> header file. */ +/* #undef HAVE_WINLDAP_H */ + +/* Define to 1 if your compiler understands __builtin_constant_p. */ +#define HAVE__BUILTIN_CONSTANT_P 1 + +/* Define to 1 if your compiler understands __builtin_types_compatible_p. */ +#define HAVE__BUILTIN_TYPES_COMPATIBLE_P 1 + +/* Define to 1 if your compiler understands __builtin_unreachable. */ +#define HAVE__BUILTIN_UNREACHABLE 1 + +/* Define to 1 if your compiler understands _Static_assert. */ +#define HAVE__STATIC_ASSERT 1 + +/* Define to 1 if your compiler understands __VA_ARGS__ in macros. */ +#define HAVE__VA_ARGS 1 + +/* Define to the appropriate snprintf format for 64-bit ints. */ +#define INT64_FORMAT "%lld" + +/* Define to 1 if `locale_t' requires <xlocale.h>. */ +/* #undef LOCALE_T_IN_XLOCALE */ + +/* Define as the maximum alignment requirement of any C data type. */ +#define MAXIMUM_ALIGNOF 8 + +/* Define bytes to use libc memset(). */ +#define MEMSET_LOOP_LIMIT 1024 + +/* Define to the address where bug reports for this package should be sent. */ +#define PACKAGE_BUGREPORT "pgsql-bugs@postgresql.org" + +/* Define to the full name of this package. */ +#define PACKAGE_NAME "PostgreSQL" + +/* Define to the full name and version of this package. */ +#define PACKAGE_STRING "PostgreSQL 9.4.0" + +/* Define to the one symbol short name of this package. */ +#define PACKAGE_TARNAME "postgresql" + +/* Define to the home page for this package. */ +#define PACKAGE_URL "" + +/* Define to the version of this package. */ +#define PACKAGE_VERSION "9.4.0" + +/* Define to the name of a signed 64-bit integer type. */ +#define PG_INT64_TYPE long long int + +/* Define to the name of the default PostgreSQL service principal in Kerberos + (GSSAPI). (--with-krb-srvnam=NAME) */ +#define PG_KRB_SRVNAM "postgres" + +/* PostgreSQL major version as a string */ +#define PG_MAJORVERSION "9.4" + +/* Define to 1 if "static inline" works without unwanted warnings from + compilations where static inline functions are defined but not called. */ +#define PG_USE_INLINE 1 + +/* PostgreSQL version as a string */ +#define PG_VERSION "9.4.0" + +/* PostgreSQL version as a number */ +#define PG_VERSION_NUM 90400 + +/* A string containing the version number, platform, and C compiler */ +#define PG_VERSION_STR "PostgreSQL 9.4.0 on i686-w64-mingw32, compiled by i686-w64-mingw32-gcc (GCC) 4.6.3, 32-bit" + +/* Define to 1 to allow profiling output to be saved separately for each + process. */ +/* #undef PROFILE_PID_DIR */ + +/* Define to the necessary symbol if this constant uses a non-standard name on + your system. */ +/* #undef PTHREAD_CREATE_JOINABLE */ + +/* RELSEG_SIZE is the maximum number of blocks allowed in one disk file. Thus, + the maximum size of a single file is RELSEG_SIZE * BLCKSZ; relations bigger + than that are divided into multiple files. RELSEG_SIZE * BLCKSZ must be + less than your OS' limit on file size. This is often 2 GB or 4GB in a + 32-bit operating system, unless you have large file support enabled. By + default, we make the limit 1 GB to avoid any possible integer-overflow + problems within the OS. A limit smaller than necessary only means we divide + a large relation into more chunks than necessary, so it seems best to err + in the direction of a small limit. A power-of-2 value is recommended to + save a few cycles in md.c, but is not absolutely required. Changing + RELSEG_SIZE requires an initdb. */ +#define RELSEG_SIZE 131072 + +/* The size of `long', as computed by sizeof. */ +#define SIZEOF_LONG 4 + +/* The size of `off_t', as computed by sizeof. */ +#define SIZEOF_OFF_T 4 + +/* The size of `size_t', as computed by sizeof. */ +#define SIZEOF_SIZE_T 4 + +/* The size of `void *', as computed by sizeof. */ +#define SIZEOF_VOID_P 4 + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Define to 1 if strerror_r() returns a int. */ +/* #undef STRERROR_R_INT */ + +/* Define to 1 if your <sys/time.h> declares `struct tm'. */ +/* #undef TM_IN_SYS_TIME */ + +/* Define to the appropriate snprintf format for unsigned 64-bit ints. */ +#define UINT64_FORMAT "%llu" + +/* Define to 1 to build with assertion checks. (--enable-cassert) */ +/* #undef USE_ASSERT_CHECKING */ + +/* Define to 1 to build with Bonjour support. (--with-bonjour) */ +/* #undef USE_BONJOUR */ + +/* Define to 1 if you want float4 values to be passed by value. + (--enable-float4-byval) */ +#define USE_FLOAT4_BYVAL 1 + +/* Define to 1 if you want float8, int8, etc values to be passed by value. + (--enable-float8-byval) */ +/* #undef USE_FLOAT8_BYVAL */ + +/* Define to 1 if you want 64-bit integer timestamp and interval support. + (--enable-integer-datetimes) */ +#define USE_INTEGER_DATETIMES 1 + +/* Define to 1 to build with LDAP support. (--with-ldap) */ +/* #undef USE_LDAP */ + +/* Define to 1 to build with XML support. (--with-libxml) */ +/* #undef USE_LIBXML */ + +/* Define to 1 to use XSLT support when building contrib/xml2. + (--with-libxslt) */ +/* #undef USE_LIBXSLT */ + +/* Define to select named POSIX semaphores. */ +/* #undef USE_NAMED_POSIX_SEMAPHORES */ + +/* Define to 1 to build with PAM support. (--with-pam) */ +/* #undef USE_PAM */ + +/* Use replacement snprintf() functions. */ +#define USE_REPL_SNPRINTF 1 + +/* Define to build with (Open)SSL support. (--with-openssl) */ +/* #undef USE_SSL */ + +/* Define to select SysV-style semaphores. */ +/* #undef USE_SYSV_SEMAPHORES */ + +/* Define to select SysV-style shared memory. */ +/* #undef USE_SYSV_SHARED_MEMORY */ + +/* Define to select unnamed POSIX semaphores. */ +/* #undef USE_UNNAMED_POSIX_SEMAPHORES */ + +/* Define to select Win32-style semaphores. */ +#define USE_WIN32_SEMAPHORES 1 + +/* Define to select Win32-style shared memory. */ +#define USE_WIN32_SHARED_MEMORY 1 + +/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most + significant byte first (like Motorola and SPARC, unlike Intel). */ +#if defined AC_APPLE_UNIVERSAL_BUILD +# if defined __BIG_ENDIAN__ +# define WORDS_BIGENDIAN 1 +# endif +#else +# ifndef WORDS_BIGENDIAN +/* # undef WORDS_BIGENDIAN */ +# endif +#endif + +/* Size of a WAL file block. This need have no particular relation to BLCKSZ. + XLOG_BLCKSZ must be a power of 2, and if your system supports O_DIRECT I/O, + XLOG_BLCKSZ must be a multiple of the alignment requirement for direct-I/O + buffers, else direct I/O may fail. Changing XLOG_BLCKSZ requires an initdb. + */ +#define XLOG_BLCKSZ 8192 + +/* XLOG_SEG_SIZE is the size of a single WAL file. This must be a power of 2 + and larger than XLOG_BLCKSZ (preferably, a great deal larger than + XLOG_BLCKSZ). Changing XLOG_SEG_SIZE requires an initdb. */ +#define XLOG_SEG_SIZE (16 * 1024 * 1024) + + + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _FILE_OFFSET_BITS */ + +/* Define to 1 to make fseeko visible on some hosts (e.g. glibc 2.2). */ +/* #undef _LARGEFILE_SOURCE */ + +/* Define for large files, on AIX-style hosts. */ +/* #undef _LARGE_FILES */ + +/* Define to `__inline__' or `__inline' if that's what the C compiler + calls it, or to nothing if 'inline' is not supported under any name. */ +#ifndef __cplusplus +/* #undef inline */ +#endif + +/* Define to the type of a signed integer type wide enough to hold a pointer, + if such a type exists, and if the system does not define it. */ +/* #undef intptr_t */ + +/* Define to empty if the C compiler does not understand signed types. */ +/* #undef signed */ + +/* Define to the type of an unsigned integer type wide enough to hold a + pointer, if such a type exists, and if the system does not define it. */ +/* #undef uintptr_t */
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/Platforms/pg_config_ext.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,8 @@ +/* + * src/include/pg_config_ext.h.in. This is generated manually, not by + * autoheader, since we want to limit which symbols get defined here. + */ + +/* Define to the name of a signed 64-bit integer type. */ +#include <stdint.h> +#define PG_INT64_TYPE int64_t
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Resources/VersionScript.map Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,12 @@ +# This is a version-script for Orthanc plugins + +{ +global: + OrthancPluginInitialize; + OrthancPluginFinalize; + OrthancPluginGetName; + OrthancPluginGetVersion; + +local: + *; +};
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/StoragePlugin/Plugin.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,155 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include <orthanc/OrthancCPlugin.h> + +#include "PostgreSQLStorageArea.h" +#include "../Core/PostgreSQLException.h" +#include "../Core/Configuration.h" + + +static OrthancPluginContext* context_ = NULL; +static OrthancPlugins::PostgreSQLStorageArea* storage_ = NULL; + + +static int32_t StorageCreate(const char* uuid, + const void* content, + int64_t size, + OrthancPluginContentType type) +{ + try + { + storage_->Create(uuid, content, static_cast<size_t>(size), type); + return 0; + } + catch (std::runtime_error& e) + { + OrthancPluginLogError(context_, e.what()); + return -1; + } +} + + +static int32_t StorageRead(void** content, + int64_t* size, + const char* uuid, + OrthancPluginContentType type) +{ + try + { + size_t tmp; + storage_->Read(*content, tmp, uuid, type); + *size = static_cast<int64_t>(tmp); + return 0; + } + catch (std::runtime_error& e) + { + OrthancPluginLogError(context_, e.what()); + return -1; + } +} + + +static int32_t StorageRemove(const char* uuid, + OrthancPluginContentType type) +{ + try + { + storage_->Remove(uuid, type); + return 0; + } + catch (std::runtime_error& e) + { + OrthancPluginLogError(context_, e.what()); + return -1; + } +} + + + +extern "C" +{ + ORTHANC_PLUGINS_API int32_t OrthancPluginInitialize(OrthancPluginContext* context) + { + context_ = context; + OrthancPluginLogWarning(context, "Using PostgreSQL storage area"); + + /* Check the version of the Orthanc core */ + if (OrthancPluginCheckVersion(context_) == 0) + { + char info[1024]; + sprintf(info, "Your version of Orthanc (%s) must be above %d.%d.%d to run this plugin", + context_->orthancVersion, + ORTHANC_PLUGINS_MINIMAL_MAJOR_NUMBER, + ORTHANC_PLUGINS_MINIMAL_MINOR_NUMBER, + ORTHANC_PLUGINS_MINIMAL_REVISION_NUMBER); + OrthancPluginLogError(context, info); + return -1; + } + + bool allowUnlock = OrthancPlugins::IsFlagInCommandLineArguments(context_, FLAG_UNLOCK); + + OrthancPluginSetDescription(context_, "Stores the files received by Orthanc into a PostgreSQL database."); + + try + { + /* Create the connection to PostgreSQL */ + std::auto_ptr<OrthancPlugins::PostgreSQLConnection> pg(OrthancPlugins::CreateConnection(context_)); + pg->Open(); + + /* Create the storage area back-end */ + storage_ = new OrthancPlugins::PostgreSQLStorageArea(pg.release(), allowUnlock); + + /* Register the storage area into Orthanc */ + OrthancPluginRegisterStorageArea(context, StorageCreate, StorageRead, StorageRemove); + } + catch (std::runtime_error& e) + { + OrthancPluginLogError(context_, e.what()); + return -1; + } + + return 0; + } + + + ORTHANC_PLUGINS_API void OrthancPluginFinalize() + { + OrthancPluginLogWarning(context_, "Storage plugin is finalizing"); + + if (storage_ != NULL) + { + delete storage_; + storage_ = NULL; + } + } + + + ORTHANC_PLUGINS_API const char* OrthancPluginGetName() + { + return "postgresql-storage"; + } + + + ORTHANC_PLUGINS_API const char* OrthancPluginGetVersion() + { + return "1.0"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/StoragePlugin/PostgreSQLStorageArea.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,169 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "PostgreSQLStorageArea.h" + +#include "../Core/PostgreSQLTransaction.h" +#include "../Core/PostgreSQLResult.h" +#include "../Core/PostgreSQLException.h" +#include "../Core/Configuration.h" + +namespace OrthancPlugins +{ + PostgreSQLStorageArea::PostgreSQLStorageArea(PostgreSQLConnection* db, + bool allowUnlock) : + db_(db), + globalProperties_(*db, GlobalProperty_StorageLock) + { + globalProperties_.Lock(allowUnlock); + + Prepare(); + } + + + void PostgreSQLStorageArea::Prepare() + { + PostgreSQLTransaction transaction(*db_); + + db_->Execute("CREATE TABLE IF NOT EXISTS StorageArea(" + "uuid VARCHAR NOT NULL PRIMARY KEY," + "content OID NOT NULL," + "type INTEGER NOT NULL)"); + + // Automatically remove the large objects associated with the table + db_->Execute("CREATE OR REPLACE RULE StorageAreaDelete AS ON DELETE TO StorageArea DO SELECT lo_unlink(old.content);"); + + create_.reset(new PostgreSQLStatement(*db_, "INSERT INTO StorageArea VALUES ($1,$2,$3)")); + create_->DeclareInputString(0); + create_->DeclareInputLargeObject(1); + create_->DeclareInputInteger(2); + + read_.reset(new PostgreSQLStatement(*db_, "SELECT content FROM StorageArea WHERE uuid=$1 AND type=$2")); + read_->DeclareInputString(0); + read_->DeclareInputInteger(1); + + remove_.reset(new PostgreSQLStatement(*db_, "DELETE FROM StorageArea WHERE uuid=$1 AND type=$2")); + remove_->DeclareInputString(0); + remove_->DeclareInputInteger(1); + + transaction.Commit(); + } + + + PostgreSQLStorageArea::~PostgreSQLStorageArea() + { + globalProperties_.Unlock(); + } + + + void PostgreSQLStorageArea::Create(const std::string& uuid, + const void* content, + size_t size, + OrthancPluginContentType type) + { + boost::mutex::scoped_lock lock(mutex_); + PostgreSQLTransaction transaction(*db_); + + PostgreSQLLargeObject obj(*db_, content, size); + create_->BindString(0, uuid); + create_->BindLargeObject(1, obj); + create_->BindInteger(2, static_cast<int>(type)); + create_->Run(); + + transaction.Commit(); + } + + + void PostgreSQLStorageArea::Read(void*& content, + size_t& size, + const std::string& uuid, + OrthancPluginContentType type) + { + boost::mutex::scoped_lock lock(mutex_); + PostgreSQLTransaction transaction(*db_); + + read_->BindString(0, uuid); + read_->BindInteger(1, static_cast<int>(type)); + PostgreSQLResult result(*read_); + + if (result.IsDone()) + { + throw PostgreSQLException(); + } + + result.GetLargeObject(content, size, 0); + + transaction.Commit(); + } + + + void PostgreSQLStorageArea::Read(std::string& content, + const std::string& uuid, + OrthancPluginContentType type) + { + void* tmp = NULL; + size_t size; + Read(tmp, size, uuid, type); + + try + { + content.resize(size); + } + catch (std::bad_alloc&) + { + free(tmp); + throw; + } + + if (size != 0) + { + assert(tmp != NULL); + memcpy(&content[0], tmp, size); + } + + free(tmp); + } + + + void PostgreSQLStorageArea::Remove(const std::string& uuid, + OrthancPluginContentType type) + { + boost::mutex::scoped_lock lock(mutex_); + PostgreSQLTransaction transaction(*db_); + + remove_->BindString(0, uuid); + remove_->BindInteger(1, static_cast<int>(type)); + remove_->Run(); + + transaction.Commit(); + } + + + void PostgreSQLStorageArea::Clear() + { + boost::mutex::scoped_lock lock(mutex_); + PostgreSQLTransaction transaction(*db_); + + db_->Execute("DELETE FROM StorageArea"); + + transaction.Commit(); + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/StoragePlugin/PostgreSQLStorageArea.h Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,77 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#pragma once + +#include "../Core/GlobalProperties.h" +#include "../Core/PostgreSQLConnection.h" +#include "../Core/PostgreSQLStatement.h" + +#include <orthanc/OrthancCPlugin.h> +#include <memory> +#include <boost/thread/mutex.hpp> + +namespace OrthancPlugins +{ + class PostgreSQLStorageArea + { + private: + std::auto_ptr<PostgreSQLConnection> db_; + GlobalProperties globalProperties_; + + boost::mutex mutex_; + std::auto_ptr<PostgreSQLStatement> create_; + std::auto_ptr<PostgreSQLStatement> read_; + std::auto_ptr<PostgreSQLStatement> remove_; + + void Prepare(); + + public: + PostgreSQLStorageArea(PostgreSQLConnection* db, + bool allowUnlock); // Takes the ownership + + ~PostgreSQLStorageArea(); + + void Create(const std::string& uuid, + const void* content, + size_t size, + OrthancPluginContentType type); + + void Read(std::string& content, + const std::string& uuid, + OrthancPluginContentType type); + + void Read(void*& content, + size_t& size, + const std::string& uuid, + OrthancPluginContentType type); + + void Remove(const std::string& uuid, + OrthancPluginContentType type); + + void Clear(); + + // For unit tests only (not thread-safe)! + PostgreSQLConnection& GetConnection() + { + return *db_; + } + }; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UnitTestsSources/PostgreSQLTests.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,352 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include <gtest/gtest.h> + +#include <boost/lexical_cast.hpp> + +#include "../Core/PostgreSQLTransaction.h" +#include "../Core/PostgreSQLResult.h" +#include "../Core/PostgreSQLLargeObject.h" +#include "../Core/PostgreSQLException.h" +#include "../StoragePlugin/PostgreSQLStorageArea.h" + +using namespace OrthancPlugins; + +extern PostgreSQLConnection* CreateTestConnection(); + + +static int64_t CountLargeObjects(PostgreSQLConnection& db) +{ + // Count the number of large objects in the DB + PostgreSQLTransaction t(db); + PostgreSQLStatement s(db, "SELECT COUNT(*) FROM pg_catalog.pg_largeobject"); + PostgreSQLResult r(s); + return r.GetInteger64(0); +} + + +TEST(PostgreSQL, Basic) +{ + std::auto_ptr<PostgreSQLConnection> pg(CreateTestConnection()); + + ASSERT_FALSE(pg->DoesTableExist("Test")); + pg->Execute("CREATE TABLE Test(name INTEGER, value BIGINT)"); + ASSERT_TRUE(pg->DoesTableExist("Test")); + + PostgreSQLStatement s(*pg, "INSERT INTO Test VALUES ($1,$2)"); + s.DeclareInputInteger(0); + s.DeclareInputInteger64(1); + + s.BindInteger(0, 43); + s.BindNull(0); + s.BindInteger(0, 42); + s.BindInteger64(1, -4242); + s.Run(); + + s.BindInteger(0, 43); + s.BindNull(1); + s.Run(); + + s.BindNull(0); + s.BindInteger64(1, 4444); + s.Run(); + + { + PostgreSQLStatement t(*pg, "SELECT name, value FROM Test ORDER BY name"); + PostgreSQLResult r(t); + + ASSERT_FALSE(r.IsDone()); + ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(42, r.GetInteger(0)); + ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ(-4242, r.GetInteger64(1)); + + r.Step(); + ASSERT_FALSE(r.IsDone()); + ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(43, r.GetInteger(0)); + ASSERT_TRUE(r.IsNull(1)); + + r.Step(); + ASSERT_FALSE(r.IsDone()); + ASSERT_TRUE(r.IsNull(0)); + ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ(4444, r.GetInteger64(1)); + + r.Step(); + ASSERT_TRUE(r.IsDone()); + } + + { + PostgreSQLStatement t(*pg, "SELECT name, value FROM Test WHERE name=$1"); + t.DeclareInputInteger(0); + + { + t.BindInteger(0, 42); + PostgreSQLResult r(t); + ASSERT_FALSE(r.IsDone()); + ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(42, r.GetInteger(0)); + ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ(-4242, r.GetInteger64(1)); + + r.Step(); + ASSERT_TRUE(r.IsDone()); + } + + { + t.BindInteger(0, 40); + PostgreSQLResult r(t); + ASSERT_TRUE(r.IsDone()); + } + } + +} + + +TEST(PostgreSQL, String) +{ + std::auto_ptr<PostgreSQLConnection> pg(CreateTestConnection()); + + pg->Execute("CREATE TABLE Test(name INTEGER, value VARCHAR(40))"); + + PostgreSQLStatement s(*pg, "INSERT INTO Test VALUES ($1,$2)"); + s.DeclareInputInteger(0); + s.DeclareInputString(1); + + s.BindInteger(0, 42); + s.BindString(1, "Hello"); + s.Run(); + + s.BindInteger(0, 43); + s.BindNull(1); + s.Run(); + + s.BindNull(0); + s.BindString(1, ""); + s.Run(); + + { + PostgreSQLStatement t(*pg, "SELECT name, value FROM Test ORDER BY name"); + PostgreSQLResult r(t); + + ASSERT_FALSE(r.IsDone()); + ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(42, r.GetInteger(0)); + ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ("Hello", r.GetString(1)); + + r.Step(); + ASSERT_FALSE(r.IsDone()); + ASSERT_FALSE(r.IsNull(0)); ASSERT_EQ(43, r.GetInteger(0)); + ASSERT_TRUE(r.IsNull(1)); + + r.Step(); + ASSERT_FALSE(r.IsDone()); + ASSERT_TRUE(r.IsNull(0)); + ASSERT_FALSE(r.IsNull(1)); ASSERT_EQ("", r.GetString(1)); + + r.Step(); + ASSERT_TRUE(r.IsDone()); + } +} + + +TEST(PostgreSQL, Transaction) +{ + std::auto_ptr<PostgreSQLConnection> pg(CreateTestConnection()); + + pg->Execute("CREATE TABLE Test(name INTEGER, value INTEGER)"); + + { + PostgreSQLStatement s(*pg, "INSERT INTO Test VALUES ($1,$2)"); + s.DeclareInputInteger(0); + s.DeclareInputInteger(1); + s.BindInteger(0, 42); + s.BindInteger(1, 4242); + s.Run(); + + { + PostgreSQLTransaction t(*pg); + s.BindInteger(0, 43); + s.BindInteger(1, 4343); + s.Run(); + s.BindInteger(0, 44); + s.BindInteger(1, 4444); + s.Run(); + + PostgreSQLStatement u(*pg, "SELECT COUNT(*) FROM Test"); + PostgreSQLResult r(u); + ASSERT_EQ(3, r.GetInteger64(0)); + + // No commit + } + + { + PostgreSQLStatement u(*pg, "SELECT COUNT(*) FROM Test"); + PostgreSQLResult r(u); + ASSERT_EQ(1, r.GetInteger64(0)); // Just "1" because of implicit rollback + } + + { + PostgreSQLTransaction t(*pg); + s.BindInteger(0, 43); + s.BindInteger(1, 4343); + s.Run(); + s.BindInteger(0, 44); + s.BindInteger(1, 4444); + s.Run(); + + { + PostgreSQLStatement u(*pg, "SELECT COUNT(*) FROM Test"); + PostgreSQLResult r(u); + ASSERT_EQ(3, r.GetInteger64(0)); + + t.Commit(); + ASSERT_THROW(t.Rollback(), PostgreSQLException); + ASSERT_THROW(t.Commit(), PostgreSQLException); + } + } + + { + PostgreSQLStatement u(*pg, "SELECT COUNT(*) FROM Test"); + PostgreSQLResult r(u); + ASSERT_EQ(3, r.GetInteger64(0)); + } + } +} + + + + + +TEST(PostgreSQL, LargeObject) +{ + std::auto_ptr<PostgreSQLConnection> pg(CreateTestConnection()); + ASSERT_EQ(0, CountLargeObjects(*pg)); + + pg->Execute("CREATE TABLE Test(name VARCHAR, value OID)"); + + // Automatically remove the large objects associated with the table + pg->Execute("CREATE RULE TestDelete AS ON DELETE TO Test DO SELECT lo_unlink(old.value);"); + + { + PostgreSQLStatement s(*pg, "INSERT INTO Test VALUES ($1,$2)"); + s.DeclareInputString(0); + s.DeclareInputLargeObject(1); + + for (int i = 0; i < 10; i++) + { + PostgreSQLTransaction t(*pg); + + std::string value = "Value " + boost::lexical_cast<std::string>(i * 2); + PostgreSQLLargeObject obj(*pg, value); + + s.BindString(0, "Index " + boost::lexical_cast<std::string>(i)); + s.BindLargeObject(1, obj); + s.Run(); + + std::string tmp; + PostgreSQLLargeObject::Read(tmp, *pg, obj.GetOid()); + ASSERT_EQ(value, tmp); + + t.Commit(); + } + } + + + ASSERT_EQ(10, CountLargeObjects(*pg)); + + { + PostgreSQLTransaction t(*pg); + PostgreSQLStatement s(*pg, "SELECT * FROM Test ORDER BY name DESC"); + PostgreSQLResult r(s); + + ASSERT_FALSE(r.IsDone()); + + ASSERT_FALSE(r.IsNull(0)); + ASSERT_EQ("Index 9", r.GetString(0)); + + std::string data; + r.GetLargeObject(data, 1); + ASSERT_EQ("Value 18", data); + + r.Step(); + ASSERT_FALSE(r.IsDone()); + + //ASSERT_TRUE(r.IsString(0)); + } + + + { + PostgreSQLTransaction t(*pg); + PostgreSQLStatement s(*pg, "DELETE FROM Test WHERE name='Index 9'"); + s.Run(); + t.Commit(); + } + + + { + // Count the number of items in the DB + PostgreSQLTransaction t(*pg); + PostgreSQLStatement s(*pg, "SELECT COUNT(*) FROM Test"); + PostgreSQLResult r(s); + ASSERT_EQ(9, r.GetInteger64(0)); + } + + ASSERT_EQ(9, CountLargeObjects(*pg)); +} + + + +TEST(PostgreSQL, StorageArea) +{ + std::auto_ptr<PostgreSQLConnection> pg(CreateTestConnection()); + PostgreSQLStorageArea s(pg.release(), true); + + ASSERT_EQ(0, CountLargeObjects(s.GetConnection())); + + for (int i = 0; i < 10; i++) + { + std::string uuid = boost::lexical_cast<std::string>(i); + std::string value = "Value " + boost::lexical_cast<std::string>(i * 2); + s.Create(uuid, value.c_str(), value.size(), OrthancPluginContentType_Unknown); + } + + std::string tmp; + ASSERT_THROW(s.Read(tmp, "nope", OrthancPluginContentType_Unknown), PostgreSQLException); + + ASSERT_EQ(10, CountLargeObjects(s.GetConnection())); + s.Remove("5", OrthancPluginContentType_Unknown); + ASSERT_EQ(9, CountLargeObjects(s.GetConnection())); + + for (int i = 0; i < 10; i++) + { + std::string uuid = boost::lexical_cast<std::string>(i); + std::string expected = "Value " + boost::lexical_cast<std::string>(i * 2); + std::string content; + + if (i == 5) + { + ASSERT_THROW(s.Read(content, uuid, OrthancPluginContentType_Unknown), PostgreSQLException); + } + else + { + s.Read(content, uuid, OrthancPluginContentType_Unknown); + ASSERT_EQ(expected, content); + } + } + + s.Clear(); + ASSERT_EQ(0, CountLargeObjects(s.GetConnection())); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UnitTestsSources/PostgreSQLWrapperTests.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,411 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "EmbeddedResources.h" + +#include <gtest/gtest.h> + +#include "../Core/PostgreSQLTransaction.h" +#include "../Core/PostgreSQLResult.h" +#include "../IndexPlugin/PostgreSQLWrapper.h" + +using namespace OrthancPlugins; + +extern PostgreSQLConnection* CreateTestConnection(); + + +// From Orthanc enumerations +static const int32_t GlobalProperty_DatabaseSchemaVersion = 1; +static const int32_t GlobalProperty_AnonymizationSequence = 3; +static const int32_t MetadataType_ModifiedFrom = 5; +static const int32_t MetadataType_LastUpdate = 7; +static const int32_t FileContentType_Dicom = 1; +static const int32_t FileContentType_DicomAsJson = 2; +static const int32_t CompressionType_None = 1; +static const int32_t CompressionType_Zlib = 2; + + +static std::auto_ptr<OrthancPluginAttachment> expectedAttachment; +static std::list<OrthancPluginDicomTag> expectedDicomTags; +static std::auto_ptr<OrthancPluginExportedResource> expectedExported; + +static void CheckAttachment(const OrthancPluginAttachment& attachment) +{ + ASSERT_STREQ(expectedAttachment->uuid, attachment.uuid); + ASSERT_EQ(expectedAttachment->contentType, attachment.contentType); + ASSERT_EQ(expectedAttachment->uncompressedSize, attachment.uncompressedSize); + ASSERT_STREQ(expectedAttachment->uncompressedHash, attachment.uncompressedHash); + ASSERT_EQ(expectedAttachment->compressionType, attachment.compressionType); + ASSERT_EQ(expectedAttachment->compressedSize, attachment.compressedSize); + ASSERT_STREQ(expectedAttachment->compressedHash, attachment.compressedHash); +} + +static void CheckExportedResource(const OrthancPluginExportedResource& exported) +{ + ASSERT_EQ(expectedExported->seq, exported.seq); + ASSERT_EQ(expectedExported->resourceType, exported.resourceType); + ASSERT_STREQ(expectedExported->publicId, exported.publicId); + ASSERT_STREQ(expectedExported->modality, exported.modality); + ASSERT_STREQ(expectedExported->date, exported.date); + ASSERT_STREQ(expectedExported->patientId, exported.patientId); + ASSERT_STREQ(expectedExported->studyInstanceUid, exported.studyInstanceUid); + ASSERT_STREQ(expectedExported->seriesInstanceUid, exported.seriesInstanceUid); + ASSERT_STREQ(expectedExported->sopInstanceUid, exported.sopInstanceUid); +} + +static void CheckDicomTag(const OrthancPluginDicomTag& tag) +{ + for (std::list<OrthancPluginDicomTag>::const_iterator + it = expectedDicomTags.begin(); it != expectedDicomTags.end(); it++) + { + if (it->group == tag.group && + it->element == tag.element && + !strcmp(it->value, tag.value)) + { + // OK, match + return; + } + } + + ASSERT_TRUE(0); // Error +} + +static int32_t InvokeService(struct _OrthancPluginContext_t* context, + _OrthancPluginService service, + const void* params) +{ + if (service == _OrthancPluginService_DatabaseAnswer) + { + const _OrthancPluginDatabaseAnswer& answer = + *reinterpret_cast<const _OrthancPluginDatabaseAnswer*>(params); + + switch (answer.type) + { + case _OrthancPluginDatabaseAnswerType_Attachment: + { + const OrthancPluginAttachment& attachment = + *reinterpret_cast<const OrthancPluginAttachment*>(answer.valueGeneric); + CheckAttachment(attachment); + break; + } + + case _OrthancPluginDatabaseAnswerType_ExportedResource: + { + const OrthancPluginExportedResource& attachment = + *reinterpret_cast<const OrthancPluginExportedResource*>(answer.valueGeneric); + CheckExportedResource(attachment); + break; + } + + case _OrthancPluginDatabaseAnswerType_DicomTag: + { + const OrthancPluginDicomTag& tag = + *reinterpret_cast<const OrthancPluginDicomTag*>(answer.valueGeneric); + CheckDicomTag(tag); + break; + } + + default: + printf("Unhandled message: %d\n", answer.type); + break; + } + } + + return 0; +} + + +TEST(PostgreSQLWrapper, Basic) +{ + std::auto_ptr<PostgreSQLConnection> pg(CreateTestConnection()); + + OrthancPluginContext context; + context.pluginsManager = NULL; + context.orthancVersion = "mainline"; + context.Free = ::free; + context.InvokeService = InvokeService; + + PostgreSQLWrapper db(pg.release(), true); + db.RegisterOutput(new DatabaseBackendOutput(&context, NULL)); + + std::string s; + ASSERT_TRUE(db.LookupGlobalProperty(s, GlobalProperty_DatabaseSchemaVersion)); + ASSERT_EQ("5", s); + + ASSERT_FALSE(db.LookupGlobalProperty(s, GlobalProperty_AnonymizationSequence)); + db.SetGlobalProperty(GlobalProperty_AnonymizationSequence, "Hello"); + ASSERT_TRUE(db.LookupGlobalProperty(s, GlobalProperty_AnonymizationSequence)); + ASSERT_EQ("Hello", s); + + int64_t a = db.CreateResource("study", OrthancPluginResourceType_Study); + ASSERT_TRUE(db.IsExistingResource(a)); + ASSERT_FALSE(db.IsExistingResource(a + 1)); + + int64_t b; + OrthancPluginResourceType t; + ASSERT_FALSE(db.LookupResource(b, t, "world")); + ASSERT_TRUE(db.LookupResource(b, t, "study")); + ASSERT_EQ(a, b); + ASSERT_EQ(OrthancPluginResourceType_Study, t); + + b = db.CreateResource("series", OrthancPluginResourceType_Series); + ASSERT_NE(a, b); + + ASSERT_EQ("study", db.GetPublicId(a)); + ASSERT_EQ("series", db.GetPublicId(b)); + ASSERT_EQ(OrthancPluginResourceType_Study, db.GetResourceType(a)); + ASSERT_EQ(OrthancPluginResourceType_Series, db.GetResourceType(b)); + + db.AttachChild(a, b); + + int64_t c; + ASSERT_FALSE(db.LookupParent(c, a)); + ASSERT_TRUE(db.LookupParent(c, b)); + ASSERT_EQ(a, c); + + c = db.CreateResource("series2", OrthancPluginResourceType_Series); + db.AttachChild(a, c); + + ASSERT_EQ(3, db.GetTableRecordCount("Resources")); + ASSERT_EQ(0, db.GetResourceCount(OrthancPluginResourceType_Patient)); + ASSERT_EQ(1, db.GetResourceCount(OrthancPluginResourceType_Study)); + ASSERT_EQ(2, db.GetResourceCount(OrthancPluginResourceType_Series)); + + ASSERT_FALSE(db.GetParentPublicId(s, a)); + ASSERT_TRUE(db.GetParentPublicId(s, b)); ASSERT_EQ("study", s); + ASSERT_TRUE(db.GetParentPublicId(s, c)); ASSERT_EQ("study", s); + + std::list<std::string> children; + db.GetChildren(children, a); + ASSERT_EQ(2u, children.size()); + db.GetChildren(children, b); + ASSERT_EQ(0u, children.size()); + db.GetChildren(children, c); + ASSERT_EQ(0u, children.size()); + + std::list<std::string> cp; + db.GetChildrenPublicId(cp, a); + ASSERT_EQ(2, cp.size()); + ASSERT_TRUE(cp.front() == "series" || cp.front() == "series2"); + ASSERT_TRUE(cp.back() == "series" || cp.back() == "series2"); + ASSERT_NE(cp.front(), cp.back()); + + std::list<std::string> pub; + db.GetAllPublicIds(pub, OrthancPluginResourceType_Patient); + ASSERT_EQ(0, pub.size()); + db.GetAllPublicIds(pub, OrthancPluginResourceType_Study); + ASSERT_EQ(1, pub.size()); + ASSERT_EQ("study", pub.front()); + db.GetAllPublicIds(pub, OrthancPluginResourceType_Series); + ASSERT_EQ(2, pub.size()); + ASSERT_TRUE(pub.front() == "series" || pub.front() == "series2"); + ASSERT_TRUE(pub.back() == "series" || pub.back() == "series2"); + ASSERT_NE(pub.front(), pub.back()); + + std::list<int64_t> ci; + db.GetChildrenInternalId(ci, a); + ASSERT_EQ(2, ci.size()); + ASSERT_TRUE(ci.front() == b || ci.front() == c); + ASSERT_TRUE(ci.back() == b || ci.back() == c); + ASSERT_NE(ci.front(), ci.back()); + + db.SetMetadata(a, MetadataType_ModifiedFrom, "modified"); + db.SetMetadata(a, MetadataType_LastUpdate, "update"); + ASSERT_FALSE(db.LookupMetadata(s, b, MetadataType_LastUpdate)); + ASSERT_TRUE(db.LookupMetadata(s, a, MetadataType_LastUpdate)); + ASSERT_EQ("update", s); + + std::list<int32_t> md; + db.ListAvailableMetadata(md, a); + ASSERT_EQ(2, md.size()); + ASSERT_TRUE(md.front() == MetadataType_ModifiedFrom || md.back() == MetadataType_ModifiedFrom); + ASSERT_TRUE(md.front() == MetadataType_LastUpdate || md.back() == MetadataType_LastUpdate); + std::string mdd; + ASSERT_TRUE(db.LookupMetadata(mdd, a, MetadataType_ModifiedFrom)); + ASSERT_EQ("modified", mdd); + ASSERT_TRUE(db.LookupMetadata(mdd, a, MetadataType_LastUpdate)); + ASSERT_EQ("update", mdd); + + db.ListAvailableMetadata(md, b); + ASSERT_EQ(0, md.size()); + + db.DeleteMetadata(a, MetadataType_LastUpdate); + db.DeleteMetadata(b, MetadataType_LastUpdate); + ASSERT_FALSE(db.LookupMetadata(s, a, MetadataType_LastUpdate)); + + db.ListAvailableMetadata(md, a); + ASSERT_EQ(1, md.size()); + ASSERT_EQ(MetadataType_ModifiedFrom, md.front()); + + ASSERT_EQ(0, db.GetTotalCompressedSize()); + ASSERT_EQ(0, db.GetTotalUncompressedSize()); + + + std::list<int32_t> fc; + + OrthancPluginAttachment a1; + a1.uuid = "uuid1"; + a1.contentType = FileContentType_Dicom; + a1.uncompressedSize = 42; + a1.uncompressedHash = "md5_1"; + a1.compressionType = CompressionType_None; + a1.compressedSize = 42; + a1.compressedHash = "md5_1"; + + OrthancPluginAttachment a2; + a2.uuid = "uuid2"; + a2.contentType = FileContentType_DicomAsJson; + a2.uncompressedSize = 4242; + a2.uncompressedHash = "md5_2"; + a2.compressionType = CompressionType_None; + a2.compressedSize = 4242; + a2.compressedHash = "md5_2"; + + db.AddAttachment(a, a1); + db.ListAvailableAttachments(fc, a); + ASSERT_EQ(1, fc.size()); + ASSERT_EQ(FileContentType_Dicom, fc.front()); + db.AddAttachment(a, a2); + db.ListAvailableAttachments(fc, a); + ASSERT_EQ(2, fc.size()); + ASSERT_FALSE(db.LookupAttachment(b, FileContentType_Dicom)); + + ASSERT_EQ(4284, db.GetTotalCompressedSize()); + ASSERT_EQ(4284, db.GetTotalUncompressedSize()); + + expectedAttachment.reset(new OrthancPluginAttachment); + expectedAttachment->uuid = "uuid1"; + expectedAttachment->contentType = FileContentType_Dicom; + expectedAttachment->uncompressedSize = 42; + expectedAttachment->uncompressedHash = "md5_1"; + expectedAttachment->compressionType = CompressionType_None; + expectedAttachment->compressedSize = 42; + expectedAttachment->compressedHash = "md5_1"; + ASSERT_TRUE(db.LookupAttachment(a, FileContentType_Dicom)); + + expectedAttachment.reset(new OrthancPluginAttachment); + expectedAttachment->uuid = "uuid2"; + expectedAttachment->contentType = FileContentType_DicomAsJson; + expectedAttachment->uncompressedSize = 4242; + expectedAttachment->uncompressedHash = "md5_2"; + expectedAttachment->compressionType = CompressionType_None; + expectedAttachment->compressedSize = 4242; + expectedAttachment->compressedHash = "md5_2"; + ASSERT_TRUE(db.LookupAttachment(a, FileContentType_DicomAsJson)); + + db.ListAvailableAttachments(fc, b); + ASSERT_EQ(0, fc.size()); + db.DeleteAttachment(a, FileContentType_Dicom); + db.ListAvailableAttachments(fc, a); + ASSERT_EQ(1, fc.size()); + ASSERT_EQ(FileContentType_DicomAsJson, fc.front()); + db.DeleteAttachment(a, FileContentType_DicomAsJson); + db.ListAvailableAttachments(fc, a); + ASSERT_EQ(0, fc.size()); + + + db.SetIdentifierTag(a, 0x0010, 0x0020, "patient"); + db.SetIdentifierTag(a, 0x0020, 0x000d, "study"); + + expectedDicomTags.clear(); + expectedDicomTags.push_back(OrthancPluginDicomTag()); + expectedDicomTags.push_back(OrthancPluginDicomTag()); + expectedDicomTags.front().group = 0x0010; + expectedDicomTags.front().element = 0x0020; + expectedDicomTags.front().value = "patient"; + expectedDicomTags.back().group = 0x0020; + expectedDicomTags.back().element = 0x000d; + expectedDicomTags.back().value = "study"; + db.GetMainDicomTags(a); + + + db.LookupIdentifier(ci, 0x0010, 0x0020, "patient"); + ASSERT_EQ(1, ci.size()); + ASSERT_EQ(a, ci.front()); + db.LookupIdentifier(ci, 0x0010, 0x0020, "study"); + ASSERT_EQ(0, ci.size()); + db.LookupIdentifier(ci, "study"); + ASSERT_EQ(1, ci.size()); + ASSERT_EQ(a, ci.front()); + + + OrthancPluginExportedResource exp; + exp.seq = -1; + exp.resourceType = OrthancPluginResourceType_Study; + exp.publicId = "id"; + exp.modality = "remote"; + exp.date = "date"; + exp.patientId = "patient"; + exp.studyInstanceUid = "study"; + exp.seriesInstanceUid = "series"; + exp.sopInstanceUid = "instance"; + db.LogExportedResource(exp); + + expectedExported.reset(new OrthancPluginExportedResource()); + *expectedExported = exp; + expectedExported->seq = 1; + + bool done; + db.GetExportedResources(done, 0, 10); + + + db.GetAllPublicIds(pub, OrthancPluginResourceType_Patient); ASSERT_EQ(0, pub.size()); + db.GetAllPublicIds(pub, OrthancPluginResourceType_Study); ASSERT_EQ(1, pub.size()); + db.GetAllPublicIds(pub, OrthancPluginResourceType_Series); ASSERT_EQ(2, pub.size()); + db.GetAllPublicIds(pub, OrthancPluginResourceType_Instance); ASSERT_EQ(0, pub.size()); + ASSERT_EQ(3, db.GetTableRecordCount("Resources")); + + ASSERT_EQ(0, db.GetTableRecordCount("PatientRecyclingOrder")); // No patient was inserted + ASSERT_TRUE(db.IsExistingResource(c)); + db.DeleteResource(c); + ASSERT_FALSE(db.IsExistingResource(c)); + ASSERT_TRUE(db.IsExistingResource(a)); + ASSERT_TRUE(db.IsExistingResource(b)); + ASSERT_EQ(2, db.GetTableRecordCount("Resources")); + db.DeleteResource(a); + ASSERT_EQ(0, db.GetTableRecordCount("Resources")); + ASSERT_FALSE(db.IsExistingResource(a)); + ASSERT_FALSE(db.IsExistingResource(b)); + ASSERT_FALSE(db.IsExistingResource(c)); + + ASSERT_EQ(0, db.GetTableRecordCount("Resources")); + ASSERT_EQ(0, db.GetTableRecordCount("PatientRecyclingOrder")); + int64_t p1 = db.CreateResource("patient1", OrthancPluginResourceType_Patient); + int64_t p2 = db.CreateResource("patient2", OrthancPluginResourceType_Patient); + int64_t p3 = db.CreateResource("patient3", OrthancPluginResourceType_Patient); + ASSERT_EQ(3, db.GetTableRecordCount("PatientRecyclingOrder")); + int64_t r; + ASSERT_TRUE(db.SelectPatientToRecycle(r)); + ASSERT_EQ(p1, r); + ASSERT_TRUE(db.SelectPatientToRecycle(r, p1)); + ASSERT_EQ(p2, r); + ASSERT_FALSE(db.IsProtectedPatient(p1)); + db.SetProtectedPatient(p1, true); + ASSERT_TRUE(db.IsProtectedPatient(p1)); + ASSERT_TRUE(db.SelectPatientToRecycle(r)); + ASSERT_EQ(p2, r); + db.SetProtectedPatient(p1, false); + ASSERT_FALSE(db.IsProtectedPatient(p1)); + ASSERT_TRUE(db.SelectPatientToRecycle(r)); + ASSERT_EQ(p2, r); + db.DeleteResource(p2); + ASSERT_TRUE(db.SelectPatientToRecycle(r, p3)); + ASSERT_EQ(p1, r); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/UnitTestsSources/UnitTestsMain.cpp Thu Feb 12 16:05:39 2015 +0100 @@ -0,0 +1,65 @@ +/** + * Orthanc - A Lightweight, RESTful DICOM Store + * Copyright (C) 2012-2015 Sebastien Jodogne, Medical Physics + * Department, University Hospital of Liege, Belgium + * + * This program is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License + * as published by the Free Software Foundation, either version 3 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 + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + **/ + + +#include "../Core/PostgreSQLConnection.h" + +#include <gtest/gtest.h> +#include <memory> +#include <boost/lexical_cast.hpp> + +static int argc_; +static char** argv_; + +OrthancPlugins::PostgreSQLConnection* CreateTestConnection() +{ + std::auto_ptr<OrthancPlugins::PostgreSQLConnection> pg(new OrthancPlugins::PostgreSQLConnection); + + pg->SetHost(argv_[1]); + pg->SetPortNumber(boost::lexical_cast<uint16_t>(argv_[2])); + pg->SetUsername(argv_[3]); + pg->SetPassword(argv_[4]); + pg->SetDatabase(argv_[5]); + + pg->Open(); + pg->ClearAll(); + + return pg.release(); +} + + + +int main(int argc, char **argv) +{ + if (argc != 6) + { + std::cerr << "Usage: " << argv[0] << " <host> <port> <username> <password> <database>" + << std::endl << std::endl + << "Example: " << argv[0] << " localhost 5432 postgres postgres orthanctests" + << std::endl << std::endl; + return -1; + } + + argc_ = argc; + argv_ = argv; + + ::testing::InitGoogleTest(&argc, argv); + + return RUN_ALL_TESTS(); +}