MYSQL

NAVIGATION
CATEGORIES
REFERRENCE
LINKS
  • static globals in SSQL macro expansion -> multiple definitionlinker errors

    12 answers - 1906 bytes - related search similar search Add To My Delicious Add To My Stumble Upon Add To My Google Mark Add To My Facebook Add To My Digg Add To My Reddit

    Hi,
    While we're talking about wish-lists for version 2.0, I have an item to
    contribute. In fact, it surprised me this hasn't been addressed yet, or
    maybe I'm missing something.
    The SSQL macro expansion will create static globals that are being
    defined (assinged) as part of the macro. With the ssqls-pretty tool it
    was easy to see that
    sql_create_7(PriceData,
    6,
    7,
    Date, date,
    int, open,
    int, high,
    int, low,
    int, close,
    int, volume,
    int, suspended);
    expands into
    struct PriceData {
    []
    static const char *names[];
    static const char *_table;
    []
    };
    []
    const char *PriceData::names[] = {
    "date" , "open" , "high" , "low" , "close" , "volume" , "suspended" };
    []
    This is fine and dandy, as long as the SSQL macro expansion is used in
    only one .cpp source file in the application. If the SSQL macro is put
    into a header file and include it into multiple .cpp source files, then
    the linker will invariably complain that names and _tables are multiply
    defined symbols.
    I've only tried this with version 1.7.35 so far, but I haven't seen
    anything in the release notes since that this behavior has been changed.
    Can this be fixed? Not being able to share SSQL structures across
    compilation units inhibits code modularity in cases where the Database
    table is the common data structure shared between many different clients
    in an application.
    Could the macro be split into two or take an extra flag to optionally
    not generate the definition for the globals? I'd be glad to give this a
    shot, but I wanted to hear from the community if there is any reason
    other than lack of volunteers. This has come up before; I found mailing
    list articles as far back as 2001 on this.
    Cheers,
    Wolfram
  • No.1 | | 1069 bytes | |

    Wed, Jul 06, 2005 at 01:15:33AM -0700, Wolfram Arnold wrote:
    Could the macro be split into two or take an extra flag to optionally
    not generate the definition for the globals? I'd be glad to give this a
    shot, but I wanted to hear from the community if there is any reason
    other than lack of volunteers. This has come up before; I found mailing
    list articles as far back as 2001 on this.

    Personally, I'd say go for it. Keeping all the logic in one macro / header
    (i.e. custom-macros.h) is probably the most maintenance friendly, since the
    macro needs to be expanded for the names anyway, and you don't want to
    duplicate it anywhere.

    Something like this might be useful:

    // file: tables.h - define it
    sql_create_5(stock, );

    // file: stock.cpp - the only file that has the static data
    #define SSQLS_GENERATE_STATICS
    #include "tables.h"

    // file: client.cpp - simple user module
    #include "tables.h"

    Might take some creativity to do that, but I think it's possible.
    - Chris
  • No.2 | | 1200 bytes | |

    Thanks for that suggestion, Chris. I'll play with it.
    -Wolfram

    Wed, 2005-07-06 at 06:39 -0400, Chris Frey wrote:
    Wed, Jul 06, 2005 at 01:15:33AM -0700, Wolfram Arnold wrote:
    Could the macro be split into two or take an extra flag to optionally
    not generate the definition for the globals? I'd be glad to give this a
    shot, but I wanted to hear from the community if there is any reason
    other than lack of volunteers. This has come up before; I found mailing
    list articles as far back as 2001 on this.

    Personally, I'd say go for it. Keeping all the logic in one macro / header
    (i.e. custom-macros.h) is probably the most maintenance friendly, since the
    macro needs to be expanded for the names anyway, and you don't want to
    duplicate it anywhere.

    Something like this might be useful:

    // file: tables.h - define it
    sql_create_5(stock, );

    // file: stock.cpp - the only file that has the static data
    #define SSQLS_GENERATE_STATICS
    #include "tables.h"

    // file: client.cpp - simple user module
    #include "tables.h"

    Might take some creativity to do that, but I think it's possible.
    - Chris
  • No.3 | | 1443 bytes | |

    Wolfram Arnold wrote:

    While we're talking about wish-lists for version 2.0,

    News to me. Since the beta was just released, the v2.0 feature set is
    frozen, as far as I'm concerned. (To me, beta means "feature-complete,
    but may have bugs.")

    That's not to say that I'm not accepting patches for v2.0. Just that
    it's a little late

    The SSQL macro expansion will create static globals that are being
    defined (assinged) as part of the macro.

    This has been on the Wishlist for a long time. The copy you have in
    your 1.7.35 version has itlook for "static". I point that out
    because it contains two suggestions for fixing it as well.

    I added a third possibility recently:

    "redesign the SSQLS mechanism entirely. Instead of defining SSQLSes
    by instantiating macros, you could declare the structure in, say, an XML
    format, which could be tranformed (XSLT? Perl + SAX?) into code very
    much like in the current SSQLS macros, except that it would generate
    separate .cpp and .h files for each structure. In addition to solving
    the static member problem, it would have other advantages, like
    side-stepping the Borland C++ macro size limit."

    I like this a lot better than the other two choices. The macros are
    ugly and unmaintainable. We have the technology to build a better
    mechanism.

    This would not be a trivial patch, of course.
  • No.4 | | 224 bytes | |

    Chris Frey wrote:
    // file: stock.cpp - the only file that has the static data
    #define SSQLS_GENERATE_STATICS
    #include "tables.h"
    Doesn't work. I tried it. You can't have an ifdef inside a macro.
  • No.5 | | 536 bytes | |

    Wed, Jul 06, 2005 at 11:52:25AM -0600, Warren Young wrote:
    Chris Frey wrote:

    >// file: stock.cpp - the only file that has the static data
    >#define SSQLS_GENERATE_STATICS
    >#include "tables.h"


    Doesn't work. I tried it. You can't have an ifdef inside a macro.

    You can define other sub macros conditionally though, and call them from
    the first. The macro that outputs the static definitions would be
    defined or empty depending on the #define flag.
    - Chris
  • No.6 | | 1884 bytes | |

    Chris Frey wrote:

    You can define other sub macros conditionally though, and call them from
    the first.

    True

    What do you think of the idea of generating separate .cpp and .h files
    for each SSQLS from an XML input file? I like it because:

    1. It generates code you can read. (It doesn't _have to_, I know, but
    it will be a design requirement.)

    2. It generates code you can debug. Ever gotten compiler errors on the
    final line of an SSQLS declaration, because of an error in the expanded
    macro? I have. These messages are almost completely useless. And
    heaven help you should try single-stepping into an SSQLS method call.

    3. It gives us the opportunity to trade C macro punctuationitis
    (trailing backslashes, token pasting syntax) for a better syntax. I
    don't expect the boilerplate code to ever be as readable as pure C++
    code, but it can be more readable than it is now.

    4. The generated macro concept forces you into generating too much code.
    custom.pl generates macros for up to N-member SSQLSes, even if you
    never use all the {1N-1} instances. The library maintainer's
    incentive is to make N large, so the end user never has to increase N,
    even though most programs will never have SSQLSes approaching N members.
    Complier limits and good sense, on the other hand, argue for lower
    values of N. The closest you can come to a happy medium is when the
    minimum number of compilers and bits of end-user code break when
    upgrading the library.

    5. Last but not least, it solves the static member problem naturally.

    My only objection to it is that it requires special setup in the build
    environment, or a separate by-hand step for those environments that
    don't allow you to set up special build rules. To get those advantages,
    I can live with this.
  • No.7 | | 2581 bytes | |

    Wed, Jul 06, 2005 at 02:51:20PM -0600, Warren Young wrote:
    1. It generates code you can read. (It doesn't _have to_, I know, but
    it will be a design requirement.)

    2. It generates code you can debug. Ever gotten compiler errors on the
    final line of an SSQLS declaration, because of an error in the expanded
    macro? I have. These messages are almost completely useless. And
    heaven help you should try single-stepping into an SSQLS method call.

    3. It gives us the opportunity to trade C macro punctuationitis
    (trailing backslashes, token pasting syntax) for a better syntax. I
    don't expect the boilerplate code to ever be as readable as pure C++
    code, but it can be more readable than it is now.

    4. The generated macro concept forces you into generating too much code.
    custom.pl generates macros for up to N-member SSQLSes, even if you
    never use all the {1N-1} instances. The library maintainer's
    incentive is to make N large, so the end user never has to increase N,
    even though most programs will never have SSQLSes approaching N members.
    Complier limits and good sense, on the other hand, argue for lower
    values of N. The closest you can come to a happy medium is when the
    minimum number of compilers and bits of end-user code break when
    upgrading the library.

    5. Last but not least, it solves the static member problem naturally.

    I like all those points too. In addition, the fewer macros there are,
    the easier it is to separate things into C++ namespaces. When there
    are naming conflicts with macros, the choices for fixing them are
    limited.

    My only objection to it is that it requires special setup in the build
    environment, or a separate by-hand step for those environments that
    don't allow you to set up special build rules. To get those advantages,
    I can live with this.

    This is a big disadvantage in my view. It adds a dependency to the
    user's build process, not just to mysql++'s.

    I would not be keen on writing XML in order to get C That would seem
    a step backwards to me, compared to the usability we currently have
    with macros. An sql_create() is pretty straightforward.

    Every so often I ponder methods to get rid of the macros, but the direction
    I would prefer to take would be some C++ method that is as easy to
    use as the macros (not sure that's possible though). I'm uncomfortable
    going in the other direction toward code generators, even with the above
    advantages.
    - Chris
  • No.8 | | 2084 bytes | |

    Chris Frey wrote:

    This is a big disadvantage in my view. It adds a dependency to the
    user's build process, not just to mysql++'s.

    Yes, it's a problem. But we are beset by problems currently, too. I am
    proposing trading a large problem set for a smaller one.

    I would not be keen on writing XML in order to get C

    even if the library comes with good examples for you to hack up to
    meet your personal requirements? I can't imagine it needing a syntax
    more complicated than:

    <ssqls name="MyStruct">
    <int name="MyNumber"/>
    <mysqlpp:Date name="MyDate"/>

    </ssqls>

    Pretty much the same as the current syntax.

    Another advantage I forgot to mention is that you could put several of
    these declarations into a single file, and the tool would be able to
    spit out as many source files as needed.

    And another advantage just popped out of the XML syntax I just invented:
    because the types are tags, we can verify in advance that the caller is
    using appropriate types. Currently, nothing stops someone from saying:

    sql_create_3(doomed,
    1, 3,
    char*, x,
    std::complex, y,
    MStrangeType, z)

    This will generate a perfectly legal C++ structure. But, using it will
    at best cause the compiler to barf in the middle of some hideous macros.
    Even worse, the code may compile, and then cause who knows what kind
    of run-time havoc when trying to do the type conversions.

    If the syntax is all that bugs you, we could make the generator accept
    the current SSQLS macro syntax. It's pretty straightforward. The main
    reasons not to are that it rules out several classes of tools (e.g.
    XSLT) and it makes the parser more complex than it has to be. A middle
    ground would be to write a translator from the SSQLS syntax to the new one.

    I'm uncomfortable
    going in the other direction toward code generators, even with the above
    advantages.

    If those advantages aren't sufficient, what would it take?
  • No.9 | | 2515 bytes | |

    Wed, Jul 06, 2005 at 08:24:08PM -0600, Warren Young wrote:
    If the syntax is all that bugs you, we could make the generator accept
    the current SSQLS macro syntax. It's pretty straightforward. The main
    reasons not to are that it rules out several classes of tools (e.g.
    XSLT) and it makes the parser more complex than it has to be.

    It is the syntax, I must admit (it's so top-heavy with markup), plus needing
    some other dependency on my system to build. It's like the boost build
    process which used to require a whole other make (Jam). Fortunately their
    tarballs come with Jam source, so it is easy to compile it on pretty much
    any system with a decent compiler.

    I also like that the macros are part of C++ code. It's not some new
    language that's added to a project. I'm reminded of Microsoft's special
    interface language here.

    Also, the idea of generating code usually tells me that something is
    broken in the design or abstraction somewhere. The macro is code generation
    too, but I consider it broken in the same respect. The downside is that
    I can think of no other way to get SSQLS functionality other than using
    some kind of code generation, so it is a necessary evil.

    But overall, I guess my arguments against XML are more prejudices than
    valid reasons. I'm not totally against code generation: I'm pondering
    it myself for my own CPPHP project.

    Doing it in XML may make it easier to GUI-ify or automate this.
    The syntax makes me shudder, but it's the best in the field so far,
    it seems. :-)

    A middle
    ground would be to write a translator from the SSQLS syntax to the new one.

    This could be done as a macro itself. :-)

    I'm uncomfortable
    >going in the other direction toward code generators, even with the above
    >advantages.


    If those advantages aren't sufficient, what would it take?

    If we go with XML, it would be nice to keep the macros around for a major
    version cycle, even if marked deprecated with no guarantee that they would
    keep up with their XML cousins. Would be easier to compare the advantages
    that way.

    I've sifted my way though the macros before, so I don't mind supporting
    them for a while, even deprecated. They are pretty stable anyway.

    If Wolfram sends a patch, I hope it is included, even if XML is the new
    direction.
    - Chris
  • No.10 | | 1758 bytes | |

    Chris Frey wrote:

    It is the syntax, I must admit (it's so top-heavy with markup),

    XML can be ugly, but take another look at what I posted. It's very
    nearly the same number of characters as current SSQLS definitions.

    plus needing
    some other dependency on my system to build.

    Naturally if there's a separate tool, it will be built and installed
    along with the library. There may be prerequisites like xsltproc or
    Perl, by they're very readily available on all common systems, if not
    installed already.

    The only inconvenience to the user is when setting up the build system
    for their own project. And most people will probably be suitably well
    served by cutting-and-pasting from the examples' build system.

    I'm reminded of Microsoft's special interface language here.

    or Motif's, or Qt's, or There are a great many other projects
    that have run into this same wall, and routed around it the same way.

    Also, the idea of generating code usually tells me that something is
    broken in the design or abstraction somewhere.

    We're _creating types_ here, for a statically-typed language. Code must
    be generated at or before compile time, somehow. Abstractions don't
    enter into it.

    I'm not totally against code generation: I'm pondering
    it myself for my own CPPHP project.

    Then you can consider this a prototype pass for your own effort. Steal
    the result when we get it right. :)

    The syntax makes me shudder, but it's the best in the field so far,
    it seems. :-)

    Nobody likes XML for XML's sake. We like it because of all the tools
    that have sprung up around it.
  • No.11 | | 835 bytes | |

    Hi,
    I am using mysql++ very lightlyconnect to a DB, run a
    select/insert/update and use the result set. Now I have 2 things I
    want to I want to figure how to keep the connection always on
    and be able to check if the connection has disconnected and if so,
    then connect to the db again.

    Is it a big overhead to keep connecting every 1/2 a sec or so? If
    it is then I would like to have this feature where I can probably set
    a idle time out and be able to check of the connection is down.

    Also how do I get how many filed are returned by a select * from
    query. I know how to get how many rows, but the col number and names,
    how do I get that?

    I have few other questions which I will send in a seperate email once
    I am alittle clear as to what I want to do.

    Thanks a ton

    AS
  • No.12 | | 1122 bytes | |

    Ankur G35 Saxena wrote:
    I am using mysql++ very lightlyconnect to a DB, run a
    select/insert/update and use the result set. Now I have 2 things I
    want to I want to figure how to keep the connection always on
    and be able to check if the connection has disconnected and if so,
    then connect to the db again.

    Use Connection::ping(). Here's why:

    Is it a big overhead to keep connecting every 1/2 a sec or so?

    Are you asking us to guess what the results of your benchmark testing
    will be? That's a poor substitute for actually doing the tests

    Also how do I get how many filed are returned by a select * from
    query. I know how to get how many rows, but the col number and names,
    how do I get that?

    Look at the value_list() and field_list() member functions. See also
    the fieldinf1 and dbinfo examples.

    I have few other questions which I will send in a seperate email once
    I am alittle clear as to what I want to do.

    Please avail yourself of the manual first:

    Two of the questions you've already asked are already addressed there.

Re: static globals in SSQL macro expansion -> multiple definitionlinker errors


max 4000 letters.
Your nickname that display:
In order to stop the spam: 0 + 9 =
QUESTION ON "MYSQL"

EMSDN.COM