Support for DB2 databases?
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
I'm not having any luck so far. Maybe Sphericus can help (this is the first time I've seen the MTK, so I'm not really familiar with it and I might be missing something). First of all, I don't see any 'replacement UDFs' in the MTK. My understanding that the MTK 'generates' code, it does not 'provide additional UDFs'. What I did with the MTK was: 1) Read the doc Quote:
SELECT iam0.g_itemId, COUNT(iam1.g_itemId) FROM g2_ItemAttributesMap AS iam0, g2_ItemAttributesMap AS iam1, g2_AccessSubscriberMap WHERE iam0.g_itemId IN (7) AND iam1.g_parentSequence LIKE iam0.g_parentSequence || iam0.g_itemId || '/%' AND iam1.g_itemId = g2_AccessSubscriberMap.g_itemId AND g2_AccessSubscriberMap.g_accessListId IN (8,9) GROUP BY iam0.g_itemId 5) Clicked on the "Convert" button. The conversion failed with various 'Unexpected Syntax' errors. Then I tried setting the 'From' platform to Oracle, and got similar errors. The end result is that I cannot get the MTK to convert this statement. Sphericus, do you know if I'm doing something wrong? Thanks. |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
- i guess there might be a directory with source code files for UDFs - also, maybe use CONCAT instead of || or use a much simpler query. |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
There is NO code in the MTK. Take my word for it. I've now managed to get a very simple scenario to work. Quote:
SELECT mycolumn1 FROM mytable WHERE mycolumn2 = 'xyz' But it does not like either form of concatenation: Quote:
SELECT mycolumn1 FROM mytable WHERE mycolumn2 LIKE 'Prefix' || '%') Both of them choke with "Unexpected Syntax" on any kind of concatenation. |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
FYI, it chokes even on concatenation in a "=" predicate: Quote:
SELECT mycolumn1 FROM mytable WHERE mycolumn2 = 'Prefix' || 'Suffix' It seems to me like the MTK doesn't support concatenation. |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
we'll have to wait for Sphericus for a real answer. but we're not interested in concat / a replacement for concat. SELECT mycolumn1 FROM mytable WHERE mycolumn2 LIKE mycolumn3; or something like that... yeah. won't help, i'm pretty sure :/ |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
Well it translated successfully, but the output statement is exactly the same as the original statement. |
|
sphericus
Joined: 2005-11-06
Posts: 55 |
![]() |
There is UDF code in the MTK package. Also, Larry, I believe that the output would be very similar or the same as the original as the MTK probably acknowledges that the new LIKE it has can do it without trouble. If you have a look at those. I found there wasn't any LIKE UDF's for oracle, but there were for Sybase and MS SQL. Also while we are on the point, I assume you are familiar with the differences between "DB2" and "DB2/400 (a.k.a. DB2 for iSeries)" ? |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
Ah, hiding in plain sight. I was looking only at the navigation tree, which only shows subdirectories, I never actually opened up the C:\MTK folder. I'm normally a command-line bigot, but in recent years am trying to force myself to use GUIs like Windows Explorer. And this is the result. I despise GUIs. OK, so I'm looking at the UDF files, and will try to figure out how they are used. Any idea why the SQL Translator doesn't seem to be working? Yes, I've worked with iSeries (a.k.a. AS/400) a little. DB2 on that platform is significantly different from its Linux/UNIX/Windows cousin. Thanks, Sphericus. |
|
sphericus
Joined: 2005-11-06
Posts: 55 |
![]() |
No idea why the SQL translator isn't working to be honest. |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
Quote:
No idea why the SQL translator isn't working to be honest. OK, well, that makes two of us. I now see roughly how the UDF files are used. They provide UDFs in either of two languages... some are implemented in SQL/PL, others in java. The 'LIKE-equivalent' UDFs are unfortunately written in java, which means: - They depend on an external ".class" file (like I mentioned a couple of days ago), and External UDFs mean that extra level of complexity due to the external file dependency. And another drawback of this method (IMHO) is that (AFAICS) they don't seem to provide the java source for these UDFs... they provide only the binary ".jar" file, which makes our problem determination more awkward. To be honest, I still prefer the solution I proposed ("LOCATE ()"), because: - It's not UDF-based at all. Any concerns if I stick with the LOCATE () solution? |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
Summary of the LIKE / CONCAT issue: Locate solution: LIKE replacment: Just to be clear: What statements would need to be replaced? that's it...for now. I searched for grep -r LIKE *, so hopefully no statements used lower-case "like". Let's also see what bharat thinks about the two alternatives. |
|
bharat
![]()
Joined: 2002-05-21
Posts: 7994 |
![]() |
I spent some time going through the code to see if we could change the way that we do this parent sequencing code to avoid this problem altogether, but I don't see an alternative that we could go to. So if we have to do this, I think that we should aim for the solution that has the lightest footprint on the code so that it's the most maintainable. Therefore I'm in favor of the 2nd (LIKE replacement) solution. |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
First, I don't see how solution #2 is lighter in footprint or maintainability. As for the porting effort, that's what I'm doing now. Both solutions require us to use $storage->getFunctionSql(). Second, the licensing question is a good one. I don't think G2 can legally redistribute any part of it. I've pasted the MTK's EULA into a Word doc nd am attaching it here. Third, we don't even know if it will work yet, because: 1) I haven't done any testing of it yet. 2) There are still any number of unknowns with this UDF. There doesn't even seem to be any documentation on how to use it. 3) There seems to be several different versions of this UDF, labelled: - mtkms7.udf Which version should I try to use? I dunno. What's the difference between them? Beats me. Why does iSeries have its own version of each of the UDFs? I have no idea. 4) If it breaks in the future, we don't have the java source. Do you really want to rely on IBM to support this? Read the EULA. ;-) |
|
sphericus
Joined: 2005-11-06
Posts: 55 |
![]() |
Well, I would expect the ms7 one to be like in MS SQL 7, and Sybase, to be like Sybase. Thus with the choice of Sybase compatibility UDF's or MS SQL 7 compatibility UDF's I think it would be up to the G2 developers which one they choose. As they may prefer the Sybase or MS SQL commands over the other. Including but not limited to the LIKE predicate. I will have a word with the IBM/DB2 people about licensing of the MTK and distribution with G2. Regardless, I will have a word with IBM about this tomorrow, and see what they say, if we are lucky, they may even be able to see if they can release the source code for that specific UDF to open source. All the best. |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
@License: @why is the LIKE replacement better for us? list ($ret, $concat) = $storage->getFunctionSql( 'CONCAT', array('[GalleryItemAttributesMap=1::parentSequence]', '[GalleryItemAttributesMap=1::itemId]', '\'/%\'')); ... $query = sprintf('... AND [GalleryItemAttributesMap=2::parentSequence] LIKE %s ... ', ..., $concat, ...); for DB2, we need something like list ($ret, $concat) = $storage->getFunctionSql( 'CONCAT', array('[GalleryItemAttributesMap=1::parentSequence]', '[GalleryItemAttributesMap=1::itemId]', '\'/\'')); list ($ret, $likeConcat) = $storage->getFunctionSql( 'LIKECONCAT', array('[GalleryItemAttributesMap=2::parentSequence]', $concat)); ... $query = sprintf('... AND %s ... ', ..., $likeConcat, ...);
The challenge would be to have a single replacement for DB2 and our existing classes. list ($ret, $concat) = $storage->getFunctionSql( 'CONCAT', array('[GalleryItemAttributesMap=1::parentSequence]', '[GalleryItemAttributesMap=1::itemId]', '\'/\'')); list ($ret, $likeConcat) = $storage->getFunctionSql( 'LIKECONCAT', array('[GalleryItemAttributesMap=2::parentSequence]', $concat)); ... $query = sprintf('... AND %s ... ', ..., $likeConcat, ...); and LIKECONCAT in mysql, pg and oracle would append a '%' if possible ('\'/\'' -> '\'/%\'' is not just appending. Maybe just concat it with another '\'%\''. And db2 would use locate() instead. or the other way: your DB2 LIKECONCAT function should check for '%' and remove it. and if there was a % at the beginning, you need to check for > 0 instead of = 1. well that would make your DB2 LIKECONCAT quite a bit more flexible and more attractive. that would work for our LIKE + CONCAT. Maybe we should call this function LIKECOLUMNPLUS or so :/, our specific replacement is quite unflexible anyway, it's not a genenral like. there could be more and more statements that need a different replacement. here the code needed if we used the UDF LIKE: list ($ret, $concat) = $storage->getFunctionSql( 'CONCAT', array('[GalleryItemAttributesMap=1::parentSequence]', '[GalleryItemAttributesMap=1::itemId]', '\'/%\'')); list ($ret, $like) = $storage->getFunctionSql( 'LIKE', array('[GalleryItemAttributesMap=2::parentSequence]', $concat)); ... $query = sprintf('... AND %s ... ', ..., $likeConcat, ...); so given that your Locate / likeconcat replacement would do checking for '%' and handle it correctly, the LIKE + CONCAT alternative is about as easy / small in code footprint as the UDF LIKE replacement. the question is now: whereas we can expect a UDF LIKE replacement to just work as expected, i.e. work as the LIKE operator in ms sql / oracle, ... the UDF LIKE replacement would be something that we wouldn't have to care much about. if we find another statement that needs it, just plug it in. if we go with the locate(), we'd have to make sure that the locate() also works for the new case. |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
Well, I've now done some preliminary testing of the MTK UDFs, and here's what I've found. 1) There are actually only two replacements for LIKE: ms7.isLike() and syb.isLike(). 2) In both cases, they still have the same problem as the regular LIKE predicate... they don't support column names in concatenation. Quote:
SELECT iam0.g_itemId, COUNT(iam1.g_itemId) FROM g2_ItemAttributesMap AS iam0, g2_ItemAttributesMap AS iam1, g2_AccessSubscriberMap WHERE iam0.g_itemId IN (7) AND SYB.isLike(iam1.g_parentSequence, iam0.g_parentSequence || iam0.g_itemId, '') = 1 AND iam1.g_itemId = g2_AccessSubscriberMap.g_itemId AND g2_AccessSubscriberMap.g_accessListId IN (8,9) GROUP BY iam0.g_itemId Concatenation of string literals do work. Quote:
SELECT iam0.g_itemId, COUNT(iam1.g_itemId) FROM g2_ItemAttributesMap AS iam0, g2_ItemAttributesMap AS iam1, g2_AccessSubscriberMap WHERE iam0.g_itemId IN (7) AND SYB.isLike(iam1.g_parentSequence, 'x' || 'y' || '/%', '') = 1 AND iam1.g_itemId = g2_AccessSubscriberMap.g_itemId AND g2_AccessSubscriberMap.g_accessListId IN (8,9) GROUP BY iam0.g_itemId (And yes, I also tested CONCAT() instead of '||'.) They also do work with a single column name (no concatenation): Quote:
SELECT iam0.g_itemId, COUNT(iam1.g_itemId) FROM g2_ItemAttributesMap AS iam0, g2_ItemAttributesMap AS iam1, g2_AccessSubscriberMap WHERE iam0.g_itemId IN (7) AND SYB.isLike(iam1.g_parentSequence, iam0.g_parentSequence, '') = 1 AND iam1.g_itemId = g2_AccessSubscriberMap.g_itemId AND g2_AccessSubscriberMap.g_accessListId IN (8,9) GROUP BY iam0.g_itemId I grant you that the LOCATE() solution won't be as easy as I thought, but I now don't think the MTK UDFs solution is going to fly at all. |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
thanks for testing. let's just shortly explore how such a PL/SQL function would look like: - preferably 100% replaces LIKE (no getSqlFunction call required), but a functin with another name is also fine from the sql 92 standard: http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt Quote:
<like predicate> uses the triadic operator LIKE (or the inverse, then on page 213 section 8.5 there's more. <like predicate> ::= <match value> [ NOT ] LIKE <pattern> [ ESCAPE <escape character> ] so we have a function with 2 operands, and we iterate through <pattern> character by character with current character c to match current character mo f m of <match value> (c++, m++ means to set c/m = next character in the match/pattern string): while (c) { if c == '_') { // doing already everything after if elseif else clause } else if (c == '%') { if c == last character of <pattern>, return true; else { c++; do: if new c != m, m++; while (m not end of string) if (m end of string) { return false; } } } else (not _ or %): if c != m, return false; } c++; m++; } // end while c
i'm not a PL/SQL guru, but that should be feasible. Larry Menard |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
Yes, that's roughly what I'm thinking too. I'll see if I can come up with our own UDF (in PL/SQL) that handles concatenating strings and column values. I still don't know what's 'down the road' after this LIKE/CONCAT issue in this porting exercise. I haven't yet gotten the 'main.php' interface to successfully run. |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
Question: will any of the SQL in g2 use more than one '%' wildcard in a LIKE? E.g., WHERE ... LIKE 'The quick % fox jumped %' Handling multiple '%' wildcards is significantly more difficult than if we limit ourselves to just one. |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
i don't know but such a limitation would / could only lead to other issues. cd modules/core/classes there might be more. |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
You're killing me, you know that? |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
i'm there for your daily challenge. i guess you must hate me by now :/ got another question: |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
The max size of a VARCHAR in DB2 is 32,762. The fact that it's FOR BIT DATA doesn't change that. However, to use VARCHAR of more than 4000 will require a bufferpool and tablespace with a page size of more than 4K are created (the current default pagesize is 4K). That's something that could be done within g2, but it's probably much easier to ensure the User does so when they create the database. |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
thanks |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
OK, I think I have a working PL/SQL "g2_like" UDF that handles concatenated parms and multiple wildcards. (Actually the concatenation is done at the time UDF is called... the value received into the UDF is already concatenated.) It returns 0 if the match is successful, 1 if the match is not successful. I've tested a number of scenarios: Quote:
These five are expected to match (and they do): Any concerns about this, or can you suggest any other scenaios I should test? |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
Quote:
OK, I think I have a working PL/SQL "g2_like" UDF that handles concatenated parms and multiple wildcards. yay for that! Quote:
It returns 0 if the match is successful, 1 if the match is not successful. usually 0 == false and 1 == true. why did you invert this? could you test another few edge cases? these test should not pass: thanks!! |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
I think I fell into the "0 = success" trap. I can easily switch the return values. I'll test the new test scenarios tonight and let you know how it goes. Thanks for the input. |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
The UDF is failing on a few of your testcases. I'm on it. Thanks for the suggestions. |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
I'm stumped on something. I've trimmed down my UDF to bare bones to illustrate this, hopefully somebody can tell me what I'm doing wrong. (Note, DB2 CLP scripts such as the following, "--" indicates comments.) Quote:
connect to gallery2 user g2user using g2pwd@ With the outer 'if' commented out, the pattern matches successfully: Quote:
values g2_like ('The quick brown fox jumped over the lazy dog', 'The quick % fox jumped over the lazy dog') But if we un-comment that outer 'if', all of a sudden it starts to fail, and it suddenly seems to think the '%' is in position 12 (it is in fact in position 11). Quote:
values g2_like ('The quick brown fox jumped over the lazy dog', 'The quick % fox jumped over the lazy dog') Can anybody see anything wrong with the logic? |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
are you sure the _ and especially the % do not already have a special meaning in DB2? and i can't answer the why 12 question without seeing the whole code i guess. should return true: should return false: |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
I reworked a number of things and the problem went away. ('%' and '_' are special to DB2 only when used in a LIKE predicate... in a garden-variety PL/SQL UDF they're just plain characters.) FYI, I'm down to only 4 failing testcases out of 20. I think these will boil down to only 2 problems (if I'm lucky, only 1). Will keep you posted. |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
great hope you will GPL the UDF, for the fame and the glory ;) |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
OK, all 20 testcases are now successful. There might be better ways to write it, but I never claimed to be a hardcore Developer. As it is, I think it's fairly clean and understandable. As this has been a significant piece of work, I'm attaching the UDF source, testcases, and testcase output here for your review. P.S.: I'm not familiar with the use of the term "GPL" as a verb. Exactly what does that entail? |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
Kudos! You rock i took a quick look at the code. not as short as i thought, but it looks reasonable. congrats! to GPL something := to make it available to the public under the GPL license (well, that's my definition). so i suggest we add it to G2 as soon as you give your ok. |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
OK, feel free to add my name anywhere you wish. My time is somewhat booked up for tomorrow, but I want to implement this and one more change to see how far that gets me, then I'll send you my current changes on Friday evening. Thanks. |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
Please also submit your BITAND UDF then we can add everything to g2 and see how far that gets you. there are a few issues now: - BIT_OR: SELECT [GalleryAccessSubscriberMap::itemId], BIT_OR([GalleryAccessMap::permission]) FROM [GalleryAccessMap], [GalleryAccessSubscriberMap] WHERE ... GROUP BY [GalleryAccessSubscriberMap::itemId]
2. it needs to OR bit by bit just like BITAND. see i guess compared to this user defined aggregate function, the LIKE method was almost easy... i've started changing the db classes, added CreateDb2Udfs.sql etc. but before we don't have this BITOR aggregate, we've got a problem. |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
Yes, I will also provide my BIT_AND. It already functions as you describe, bit-by-bit, and the arguments are sequences of 32 bits. Thanks for the description of BIT_OR, I had assumed it was more similar to BIT_AND (receives 2 sequences of bits). I have no experience with user-defined aggregate functions, and haven't yet read Knut's article, so before I look into them I don't know if they ever were or are now supported. Yet another thing I have to learn on the fly. I'll send you my latest changes (since my last CVS UPDATE) tomorrow. (Only things that work.) |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
Great |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
In integrating the G2_LIKE() UDF into the G2 code I've hit a (hopefully minor) snag. The SQL generated is: Quote:
AND G2_LIKE(iam1.g_parentSequence, iam0.g_parentSequence || iam0.g_itemId || '/%' ) = 1 But the || fails because iam0.g_itemId is not a string literal. It works if I wrap it in a CAST(... AS CHAR(10)): Quote:
AND G2_LIKE(iam1.g_parentSequence, iam0.g_parentSequence || CAST(iam0.g_itemId AS CHAR(10)) || '/%' ) = 1 The problem is that I can't always assume that the 3rd arg needs to be cast, can I? One solution is if I can programmatically test the datatype for each arg in the getFunctionSql() code. Is that possible? Then I could wrap the CAST around only the necessary columns. |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
yeah, when looking yesterday at the code, i thought too of that issue. can't you in case 'CONCAT': always cast to CHAR? why would that be bad? that's what i have in my current version of Db2DatabaseStorage.class: case 'CONCAT': $sql = 'char(' . implode(') || char(', $args) . ')'; break; thus casting every argument to CHAR. programmatically check each argument for the type? don't think that's easily feasible, quite some changes would be necessary. of course we could just add another arg to concat to let getSqlFuntion know... but only if it's really necessary. and i'd really prefer if we could just use CHAR($arg[..]) and not CAST as CHAR(10)), we don't know the length... |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
Yeah, good idea. But for some reason the ||s in my SQL don't seem to be going through the case 'CONCAT'. Any idea why that might be happening? Also, if you have three values concatenated, will you not be wrapping a char() wrapper around another char() wrapper in the 2nd arg? The first time through the code it will wrap char() around $arg[0] and $arg[1]. The second time through the code it will wrap another char() around $arg[1] (which already has a char() wrapper) and a wrapper around $arg[2]. So you'll wind up with char($arg[0]) || char(char($arg[1])) || char($arg[2]). You might want to first test it to see if it's already being cast. (Re the CAST($arg[x] AS CHAR(n)) versus CHAR($arg[x]), sorry, old habits die hard. |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
|| that is not generated with || ? the above case 'CONCAT': is not yet in your DB2 class, i have it just on my harddisk, maybe that was confusing. @multiple arguments: |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
Never mind, I retract my questions... I found and fixed the problem, and yes I realized how the implode() works. I should have thought about it a bit more before posting. OK, the update to case 'CONCAT' is now working fine, as is the G2_LIKE(). Thanks. |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
I think I know how I can do the aggregate BIT_OR. I think I will have to write a UDF that uses a 'scratchpad' (a data area that holds persistent data across invocations of the function). For example: In statement "SELECT foo(col1) FROM tb1", function "foo" is invoked for each value in column "col1". Each time it is invoked on a new value, it should: Quote:
if (scratchpad is empty) then The original SQL statement will only see the returned value from the last invocation of the function. (Actually, I'm not 100% sure of that part. ;-) I expect the G2 SQL might even be able to remain unchanged from what it is currently. The down side is that only 'external' UDFs are able to use the SCRATCHPAD functionality. 'External' basically means the function resides in a separate library. In this case, I'd write it in java so that the library is binary-portable. I may have to amend this plan as I proceed, but does that sound OK to you so far? P.S., I apologize that the above code is so difficult to read. Is there any way to preserve indenting in these forum posts? |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
@unchanged g2 sql code: that would be great, but from the example for a user defined workaround aggregate function in DB2 from the link, it looks like the returned format of the MAX(BIT_OR(column)) is counterBIT_OR_RESULT, whereas the counter part can't be removed without rewriting the SQL of the whole query (subquery). the problem is, that you have to print each intermediate result in your user defined function. i guess i have an idea: say SELECT BIT_OR(column) so we have a counter in the first x nr of characters. the INTERMEDIATE_BIT_OR_RESULT is a NR_OF_BITS long string of 0's and 1's. so instead of we do now: SELECT MAX(BIT_OR(column)) - (COUNT(*) * 10^NR_OF_BITS) FROM foo explanation: 10^NR_OF_BITS will have to be computed in PHP and we can just write 'COUNT(*) * ' . pow(10, 32) since we're using 32 bits right now. i really hope that works @java: @code formatting in the forums: |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
> from the example for a user defined workaround aggregate function in DB2 from the link I'd suggest you don't pay any attention to Knut's article. I find he's made it much more complicated than it needs to be. I turned to Don Chamberlin's book "Understanding DB2 Universal Database"... it's much more understandable by mere humans like me. The query I'm now working on is: SELECT g2_AccessSubscriberMap.g_itemId, BIT_OR(g2_AccessMap.g_permission) FROM g2_AccessMap, g2_AccessSubscriberMap WHERE g2_AccessSubscriberMap.g_itemId IN (?) AND g2_AccessSubscriberMap.g_accessListId = g2_AccessMap.g_accessListId AND (g2_AccessMap.g_userId = ? OR g2_AccessMap.g_groupId IN (?)) GROUP BY g2_AccessSubscriberMap.g_itemId There's no MAX() in there, so I don't understand why you keep bringing that up. There's no COUNT() either. I guess I was misunderstanding what the BIT_OR() was supposed to do. My current understanding is that it is supposed to return a sequence of values (one for each g_permission value) prefixed by a counter. If so, the counter is no problem (I can easily use the scratchpad for that), but what is each g_permission value being ORed against? (BTW, I'm not a Mathie at heart, so applied math explanations are not as helpful to me as you might think. |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
@MAX(): @BIT_OR(): for a table product, category, price the following is also a fictive query: SELECT itemId, BIT_OR(permission) for a table itemId, permission, user itemId permisssion user --------------------------- 5 10000000 tom 5 00100000 joe 5 00000001 joe 99 00000010 joe 99 00100001 joe 99 11000000 joe it will OR all rows that match the where clause (joe) for each itemId (group by). itemId permission ---------------------- 5 00100101 99 11000011
so, no: our BIT_OR(), what we need as a 1:1 replacement for the mysql BIT_OR, is an aggregate function that just returns a value. not a sequence, not prefixed by a counter. @your alternative: |
|
Larry Menard
![]()
Joined: 2005-10-01
Posts: 757 |
![]() |
I'll try to digest this tonight. In the meantime, here's what I have for delivery. Quote:
lib/adodb/drivers/adodb-db2.php.inc (SQL_CUR_USE_IF_NEEDED) Remember, the new LIKE case in getFunctionSql() will need to be added to the other RDBMSs. This will bring the code up to the same spot I'm at... dying on the BIT_OR. Let me know when it's checked in, and I'll get a fresh copy of the build and verify it's working as I expect. Thanks, Valiant. |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
committed to cvs, get tomorrows nightly snapshot. you can't use anonymous CVS right now, since sf.net is having hardware problems and anonymous cvs is still in the state of a few days back. |
|
valiant
Joined: 2003-01-04
Posts: 32509 |
![]() |
Larry, bharat is adding another place where he uses BITAND, but this time for PermissionSetMap::flags, which is just 4 bits ling (it's an integer anyway). |
|