Javac string concatenation desugaring
Where in the JDK7 javac source does string concatenation using pluses (e.g., String s = string1 + string2 + int1;) get desugared into an instantiation of a StringBuilder, with subsequent calls to append, ending with a call to toString? (if this is not actually currently done, what is the equivalent, and where in the javac source does it occur?)
Thanks.
FYI: I know that consecutive concatenated literals are combined into a single literal in com.sun.tools.javac.parser.JavacParser.foldStrings(JCTree), but I do not know where the desugaring involving non-literals occurs.
As a side question, does the compiler also combine non-literals whose values are definitely known, e.g.:
int i = 0;
String s = "1";
String t = i + s;
t will always be set to "01", but neither of the two arguments to + are literals.
Okay. Any particular problem you're looking to fix, or just picking this particular area out of general interest?No particular area, just whatever I see. It started out with investigating String/Builder/Buffer inefficiencies, because I noticed them a while ago, but it's grown to anything that I happen to notice.
Add an instance field named currentDeterminantValue of type Object to whatever class represents a variable in javac. Also add a final static byte[] named NONDETERMINANT. If an assignment is to something that is known at compile time (e.g., a literal, a final variable (i.e. a constant), a determinant return of a final, private, or static method, etc.), then set currentDeterminantValue = <object or boxed primitive>. If the assignment is to something that is unknown at compile time, set currentDeterminantValue = NONDETERMINANT. Also add a method named isCurrentlyDeterminant() to the aforementioned class that performs {return currentDeterminantValue != NONDETERMINANT}. Whenever isCurrentlyDeterminant() is true, perform appropriate optimizations. A similar mechanism can be used for private, static, or final methods, as long as you cannot use reflection or some other weird mechanism to change their behavior. e.g., if the whole body of a final method is {return "ABC";}, then the currentDeterminantValue of the instance that represents that method in javac can be set to "ABC".I forgot to mention that NONDETERMINANT = new byte[] {}; It should also be private. Nothing special about byte[]. It could be an int[], an Object, etc, just an object that will never be used in a real call. An empty array should be the most memory-efficient way to create such a sentinel.
Not really following that, but it sounds like this applies specifically to member variables, not locals. I don't think what you're suggesting can work for members. To recap your previous example:This would not apply to member or static variables, unless the assignment and use are in the same synchronized block, and all assignments to the variable are synchronized on the same object, and you can somehow disable or ignore the nefarious combination of java.lang.reflect.Class getDeclaredField and Field methods setAccessible and set, and any other similar sneaky tricks if they exist (using those three methods, you can even mutate “immutable” Strings). This would obviously be more difficult to detect than the case of local variables, but member / static variable determinacy determination could be implemented as a later improvement.
String x = "1";
int y = 2
String z = x + y;If x, y, and z are member variables, then between the first and second or between the second and third assignment, another thread can modify x or y, so there's no way that the compiler can know that z will be "12", unless x and y are compile-time constants, and in that case, it already sets z to "12" at compile time.In my example that you've quoted above, the variables are all local.
There are many complex additional optimizations that javac could perform, but they are probably more easily and comprehensively performed by the jvm given that it knows what other classes have been loaded and their bytecode.
Similar Messages
-
Connect by - sql help : getting error ORA-01489: result of string concatena
here is an sql query and I am trying to cook a decode but since there are many columns invloved when I am trying to run this I am getting the following error:
ORA-01489: result of string concatenation is too long
Any kind of help is appreciated, I need to get this going otherwise I am dead :(
Regards
Rahul
SQL:
select sys_connect_by_path(c.decode_prep,'-') decode_prep
from (select 'DECODE(BIAPPS_11.'||substr(b.all_cols,instr(b.all_cols,',',1,a.rn)+1,instr(b.all_cols,',',1,a.rn+1)-instr(b.all_cols,',',1,a.rn)-1)||','||'RAHULKALRA.'||substr(b.all_cols,instr(b.all_cols,',',1,a.rn)+1,instr(b.all_cols,',',1,a.rn+1)-instr(b.all_cols,',',1,a.rn)-1)||',''1'',''0'')' decode_prep, rownum curr, rownum -1 prev
from (select rownum rn
from dual connect by rownum <=
(select (length('ROW_WID,COST_CENTER_NUM,COST_CENTER_NAME,COST_CENTER_DESC,CONTROL_AREA_NUM,CONTROL_AREA_NAME,CATEGORY_CODE,CATEGORY_NAME,CATEGORY_DESC,MANAGER_NAME,CURRENCY_CODE,CURRENCY_NAME,LANGUAGE_CODE,LANGUAGE_NAME,ST_ADDRESS1,ST_ADDRESS2,POST_OFFICE_BOX,CITY_NAME,STATE_CODE,STATE_NAME,REGION_CODE,REGION_NAME,COUNTRY_CODE,COUNTRY_NAME,POSTAL_CODE,PHONE_NUM,FAX_NUM,CSCN_HIER1_CODE,CSCN_HIER1_NAME,CSCN_HIER2_CODE,CSCN_HIER2_NAME,CSCN_HIER3_CODE,CSCN_HIER3_NAME,CSCN_HIER4_CODE,CSCN_HIER4_NAME,CSCN_HIER5_CODE,CSCN_HIER5_NAME,CSCN_HIER6_CODE,CSCN_HIER6_NAME,ACTIVE_FLG,CREATED_BY_WID,CHANGED_BY_WID,CREATED_ON_DT,CHANGED_ON_DT,AUX1_CHANGED_ON_DT,AUX2_CHANGED_ON_DT,AUX3_CHANGED_ON_DT,AUX4_CHANGED_ON_DT,SRC_EFF_FROM_DT,SRC_EFF_TO_DT,EFFECTIVE_FROM_DT,EFFECTIVE_TO_DT,DELETE_FLG,CURRENT_FLG,W_INSERT_DT,W_UPDATE_DT,DATASOURCE_NUM_ID,ETL_PROC_WID,INTEGRATION_ID,SET_ID,TENANT_ID,X_CUSTOM')
- length(replace('ROW_WID,COST_CENTER_NUM,COST_CENTER_NAME,COST_CENTER_DESC,CONTROL_AREA_NUM,CONTROL_AREA_NAME,CATEGORY_CODE,CATEGORY_NAME,CATEGORY_DESC,MANAGER_NAME,CURRENCY_CODE,CURRENCY_NAME,LANGUAGE_CODE,LANGUAGE_NAME,ST_ADDRESS1,ST_ADDRESS2,POST_OFFICE_BOX,CITY_NAME,STATE_CODE,STATE_NAME,REGION_CODE,REGION_NAME,COUNTRY_CODE,COUNTRY_NAME,POSTAL_CODE,PHONE_NUM,FAX_NUM,CSCN_HIER1_CODE,CSCN_HIER1_NAME,CSCN_HIER2_CODE,CSCN_HIER2_NAME,CSCN_HIER3_CODE,CSCN_HIER3_NAME,CSCN_HIER4_CODE,CSCN_HIER4_NAME,CSCN_HIER5_CODE,CSCN_HIER5_NAME,CSCN_HIER6_CODE,CSCN_HIER6_NAME,ACTIVE_FLG,CREATED_BY_WID,CHANGED_BY_WID,CREATED_ON_DT,CHANGED_ON_DT,AUX1_CHANGED_ON_DT,AUX2_CHANGED_ON_DT,AUX3_CHANGED_ON_DT,AUX4_CHANGED_ON_DT,SRC_EFF_FROM_DT,SRC_EFF_TO_DT,EFFECTIVE_FROM_DT,EFFECTIVE_TO_DT,DELETE_FLG,CURRENT_FLG,W_INSERT_DT,W_UPDATE_DT,DATASOURCE_NUM_ID,ETL_PROC_WID,INTEGRATION_ID,SET_ID,TENANT_ID,X_CUSTOM',',')))+1 total_cols
from dual)) a, (select ','||'ROW_WID,COST_CENTER_NUM,COST_CENTER_NAME,COST_CENTER_DESC,CONTROL_AREA_NUM,CONTROL_AREA_NAME,CATEGORY_CODE,CATEGORY_NAME,CATEGORY_DESC,MANAGER_NAME,CURRENCY_CODE,CURRENCY_NAME,LANGUAGE_CODE,LANGUAGE_NAME,ST_ADDRESS1,ST_ADDRESS2,POST_OFFICE_BOX,CITY_NAME,STATE_CODE,STATE_NAME,REGION_CODE,REGION_NAME,COUNTRY_CODE,COUNTRY_NAME,POSTAL_CODE,PHONE_NUM,FAX_NUM,CSCN_HIER1_CODE,CSCN_HIER1_NAME,CSCN_HIER2_CODE,CSCN_HIER2_NAME,CSCN_HIER3_CODE,CSCN_HIER3_NAME,CSCN_HIER4_CODE,CSCN_HIER4_NAME,CSCN_HIER5_CODE,CSCN_HIER5_NAME,CSCN_HIER6_CODE,CSCN_HIER6_NAME,ACTIVE_FLG,CREATED_BY_WID,CHANGED_BY_WID,CREATED_ON_DT,CHANGED_ON_DT,AUX1_CHANGED_ON_DT,AUX2_CHANGED_ON_DT,AUX3_CHANGED_ON_DT,AUX4_CHANGED_ON_DT,SRC_EFF_FROM_DT,SRC_EFF_TO_DT,EFFECTIVE_FROM_DT,EFFECTIVE_TO_DT,DELETE_FLG,CURRENT_FLG,W_INSERT_DT,W_UPDATE_DT,DATASOURCE_NUM_ID,ETL_PROC_WID,INTEGRATION_ID,SET_ID,TENANT_ID,X_CUSTOM'||',' all_cols from dual) b) c
start with curr = 1
connect by prior curr = prev
order by length(sys_connect_by_path(c.decode_prep,'-')) desc
same as above sql only difference is here I am pulling the first record from the result set which above query returns :
select ltrim(replace(decode_prep,'-','||'),'||') decode_prep
from (select sys_connect_by_path(c.decode_prep,'-') decode_prep
from (select 'DECODE(BIAPPS_11.'||substr(b.all_cols,instr(b.all_cols,',',1,a.rn)+1,instr(b.all_cols,',',1,a.rn+1)-instr(b.all_cols,',',1,a.rn)-1)||','||'RAHULKALRA.'||substr(b.all_cols,instr(b.all_cols,',',1,a.rn)+1,instr(b.all_cols,',',1,a.rn+1)-instr(b.all_cols,',',1,a.rn)-1)||',''1'',''0'')' decode_prep, rownum curr, rownum -1 prev
from (select rownum rn
from dual connect by rownum <=
(select (length('ROW_WID,COST_CENTER_NUM,COST_CENTER_NAME,COST_CENTER_DESC,CONTROL_AREA_NUM,CONTROL_AREA_NAME,CATEGORY_CODE,CATEGORY_NAME,CATEGORY_DESC,MANAGER_NAME,CURRENCY_CODE,CURRENCY_NAME,LANGUAGE_CODE,LANGUAGE_NAME,ST_ADDRESS1,ST_ADDRESS2,POST_OFFICE_BOX,CITY_NAME,STATE_CODE,STATE_NAME,REGION_CODE,REGION_NAME,COUNTRY_CODE,COUNTRY_NAME,POSTAL_CODE,PHONE_NUM,FAX_NUM,CSCN_HIER1_CODE,CSCN_HIER1_NAME,CSCN_HIER2_CODE,CSCN_HIER2_NAME,CSCN_HIER3_CODE,CSCN_HIER3_NAME,CSCN_HIER4_CODE,CSCN_HIER4_NAME,CSCN_HIER5_CODE,CSCN_HIER5_NAME,CSCN_HIER6_CODE,CSCN_HIER6_NAME,ACTIVE_FLG,CREATED_BY_WID,CHANGED_BY_WID,CREATED_ON_DT,CHANGED_ON_DT,AUX1_CHANGED_ON_DT,AUX2_CHANGED_ON_DT,AUX3_CHANGED_ON_DT,AUX4_CHANGED_ON_DT,SRC_EFF_FROM_DT,SRC_EFF_TO_DT,EFFECTIVE_FROM_DT,EFFECTIVE_TO_DT,DELETE_FLG,CURRENT_FLG,W_INSERT_DT,W_UPDATE_DT,DATASOURCE_NUM_ID,ETL_PROC_WID,INTEGRATION_ID,SET_ID,TENANT_ID,X_CUSTOM')
- length(replace('ROW_WID,COST_CENTER_NUM,COST_CENTER_NAME,COST_CENTER_DESC,CONTROL_AREA_NUM,CONTROL_AREA_NAME,CATEGORY_CODE,CATEGORY_NAME,CATEGORY_DESC,MANAGER_NAME,CURRENCY_CODE,CURRENCY_NAME,LANGUAGE_CODE,LANGUAGE_NAME,ST_ADDRESS1,ST_ADDRESS2,POST_OFFICE_BOX,CITY_NAME,STATE_CODE,STATE_NAME,REGION_CODE,REGION_NAME,COUNTRY_CODE,COUNTRY_NAME,POSTAL_CODE,PHONE_NUM,FAX_NUM,CSCN_HIER1_CODE,CSCN_HIER1_NAME,CSCN_HIER2_CODE,CSCN_HIER2_NAME,CSCN_HIER3_CODE,CSCN_HIER3_NAME,CSCN_HIER4_CODE,CSCN_HIER4_NAME,CSCN_HIER5_CODE,CSCN_HIER5_NAME,CSCN_HIER6_CODE,CSCN_HIER6_NAME,ACTIVE_FLG,CREATED_BY_WID,CHANGED_BY_WID,CREATED_ON_DT,CHANGED_ON_DT,AUX1_CHANGED_ON_DT,AUX2_CHANGED_ON_DT,AUX3_CHANGED_ON_DT,AUX4_CHANGED_ON_DT,SRC_EFF_FROM_DT,SRC_EFF_TO_DT,EFFECTIVE_FROM_DT,EFFECTIVE_TO_DT,DELETE_FLG,CURRENT_FLG,W_INSERT_DT,W_UPDATE_DT,DATASOURCE_NUM_ID,ETL_PROC_WID,INTEGRATION_ID,SET_ID,TENANT_ID,X_CUSTOM',',')))+1 total_cols
from dual)) a, (select ','||'ROW_WID,COST_CENTER_NUM,COST_CENTER_NAME,COST_CENTER_DESC,CONTROL_AREA_NUM,CONTROL_AREA_NAME,CATEGORY_CODE,CATEGORY_NAME,CATEGORY_DESC,MANAGER_NAME,CURRENCY_CODE,CURRENCY_NAME,LANGUAGE_CODE,LANGUAGE_NAME,ST_ADDRESS1,ST_ADDRESS2,POST_OFFICE_BOX,CITY_NAME,STATE_CODE,STATE_NAME,REGION_CODE,REGION_NAME,COUNTRY_CODE,COUNTRY_NAME,POSTAL_CODE,PHONE_NUM,FAX_NUM,CSCN_HIER1_CODE,CSCN_HIER1_NAME,CSCN_HIER2_CODE,CSCN_HIER2_NAME,CSCN_HIER3_CODE,CSCN_HIER3_NAME,CSCN_HIER4_CODE,CSCN_HIER4_NAME,CSCN_HIER5_CODE,CSCN_HIER5_NAME,CSCN_HIER6_CODE,CSCN_HIER6_NAME,ACTIVE_FLG,CREATED_BY_WID,CHANGED_BY_WID,CREATED_ON_DT,CHANGED_ON_DT,AUX1_CHANGED_ON_DT,AUX2_CHANGED_ON_DT,AUX3_CHANGED_ON_DT,AUX4_CHANGED_ON_DT,SRC_EFF_FROM_DT,SRC_EFF_TO_DT,EFFECTIVE_FROM_DT,EFFECTIVE_TO_DT,DELETE_FLG,CURRENT_FLG,W_INSERT_DT,W_UPDATE_DT,DATASOURCE_NUM_ID,ETL_PROC_WID,INTEGRATION_ID,SET_ID,TENANT_ID,X_CUSTOM'||',' all_cols from dual) b) c
start with curr = 1
connect by prior curr = prev
order by length(sys_connect_by_path(c.decode_prep,'-')) desc)
where rownum = 1
Edited by: Mac_Freak_Rahul on Nov 28, 2012 1:31 AM : in the first sql ')'
removed after desc in the last line so now this query will run and throw an error.Clearly your error is because the string concatenation you are doing with sys_connect_by_path is exceeding the 4000 bytes permitted by SQL.
In that case you need to concatenate your data into a CLOB datatype, for which you'll need a CLOB aggregation function...
create or replace type clobagg_type as object
text clob,
static function ODCIAggregateInitialize(sctx in out clobagg_type) return number,
member function ODCIAggregateIterate(self in out clobagg_type, value in clob) return number,
member function ODCIAggregateTerminate(self in clobagg_type, returnvalue out clob, flags in number) return number,
member function ODCIAggregateMerge(self in out clobagg_type, ctx2 in clobagg_type) return number
create or replace type body clobagg_type is
static function ODCIAggregateInitialize(sctx in out clobagg_type) return number is
begin
sctx := clobagg_type(null) ;
return ODCIConst.Success ;
end;
member function ODCIAggregateIterate(self in out clobagg_type, value in clob) return number is
begin
self.text := self.text || value ;
return ODCIConst.Success;
end;
member function ODCIAggregateTerminate(self in clobagg_type, returnvalue out clob, flags in number) return number is
begin
returnValue := self.text;
return ODCIConst.Success;
end;
member function ODCIAggregateMerge(self in out clobagg_type, ctx2 in clobagg_type) return number is
begin
self.text := self.text || ctx2.text;
return ODCIConst.Success;
end;
end;
create or replace function clobagg(input clob) return clob
deterministic
parallel_enable
aggregate using clobagg_type;
SQL> select trim(',' from clobagg(ename||',')) as enames from emp;
ENAMES
SMITH,ALLEN,WARD,JONES,MARTIN,BLAKE,CLARK,SCOTT,KING,TURNER,ADAMS,JAMES,FORD,MILLER
SQL> ed
Wrote file afiedt.buf
1 with t as
2 (select 'PFL' c1, 0 c2,110 c3 from dual union all
3 select 'LHL', 0 ,111 from dual union all
4 select 'PHL', 1, 111 from dual union all
5 select 'CHL', 2, 111 from dual union all
6 select 'DHL', 0, 112 from dual union all
7 select 'VHL', 1, 112 from dual union all
8 select 'CPHL', 0, 114 from dual union all
9 select 'WDCL', 1, 114 from dual union all
10 select 'AHL' ,2 ,114 from dual union all
11 select 'NFDL', 3, 114 from dual)
12 --
13 -- end of test data
14 --
15 select trim(clobagg(c1||' ')) as c1, c3
16 from (select * from t order by c3, c2)
17 group by c3
18* order by c3
SQL> /
C1 C3
PFL 110
LHL CHL PHL 111
DHL VHL 112
CPHL AHL NFDL WDCL 114 -
String.concat() vs + operator in strings concatenations
Whats the difference between String.concat() and + operator in strings concatenation?
I cant find any functional one.
Are there any performance differences?
ThanksTM-Nite wrote:
Whats the difference between String.concat() and + operator in strings concatenation?
I cant find any functional one.There isn't any for all one can tell from the API docs. More details would be up to the String implementation.
Are there any performance differences?No. Both are bad if repeated a lot, as long as there aren't exclusively compile-time constants involved. Use StringBuilder/StringBuffer instead, in those cases. -
Ora-01489: result of string concatenation is too long
Hello Gurus,
i have a typical problem
i am constructing a query in FORM and writing SQLPLUS script into a .SQL file. file will contain final data like below..
set linesize 90
set pagesize 0
set echo off
set verify off
set termout off
set feedback off
set trimspool on
set escape '^'
spool D:\10GAPPServerappln\xxx\TEMPREP\ADA39057.sql;
set linesize 229
select ' IQIS# ,Cust Complaint Short Txt ,CD Short Txt ' from dual;
set linesize 129
select a||','||b||','||c||d from table;
spool off;
exit;
After this By using HOST command i will execute the above .sql script and will write the output to text file.
But problem is when i have clob column in any one of concatenated columns in query (a or b or c) then i am getting the error "Ora-01489: result of string concatenation is too long".
pls suggest me how to overcome this problem..sybrand_b wrote:
Obviously the || operator is concatenating strings, your CLOB is implicitly converted to a VARCHAR2, which has a 4000 bytes limit.???
From non-experts who did read documentation:
CLOB || VARCHAR2 = CLOB:
SQL> CREATE OR REPLACE
2 VIEW V1
3 AS SELECT TO_CLOB('A') || 'A' clob_concat_varchar2 FROM dual
4 /
View created.
SQL> DESC V1
Name Null? Type
CLOB_CONCAT_VARCHAR2 CLOB
SQL> SY. -
Patch 111685 breaks string concatenation!!!
Patch 111685 for WS6U2 fixes a lot of problems but introduces a massive memory leak in operator+= for std::string. Sun has already acknowledged that it's a serious bug (bug id 4520126) although they are taking forever to fix it:
This is the test case that we submitted to Sun:
$ uname -a
SunOS mildev1 5.8 Generic_108528-09 sun4u sparc SUNW,Ultra-80
$ CC -V
CC: Sun WorkShop 6 update 2 C++ 5.3 Patch 111685-01 2001/08/01
main.cpp
#include <string>
int main()
const char JUNK[] = "JUNK";
std::string s;
for (int i = 0; i < 10000; ++i) s += JUNK;
return 0;
$ CC -staticlib=Crun,Cstd -g main.cpp -o main
$ dbx ./main
Reading main
Reading ld.so.1
Reading libm.so.1
Reading libw.so.1
Reading libc.so.1
Reading libdl.so.1
Reading libc_psr.so.1
(/pkgs/sun_workshop62/bin/../WS6U2/bin/sparcv9/dbx) check -leaks
leaks checking - ON
(/pkgs/sun_workshop62/bin/../WS6U2/bin/sparcv9/dbx) run
Running: main
(process id 17850)
Reading librtc.so
RTC: Enabling Error Checking...
RTC: Running program...
Checking for memory leaks...
Actual leaks report (actual leaks: 9986 total size: 200142024 bytes)
Total Num of Leaked Allocation call stack
Size Blocks Block
Address
====== ====== ========== =======================================
200142024 9986 - operator new < std::basic_string<char,std::char_traits<char>,std::allocator<char> >::__getRep
Possible leaks report (possible leaks: 13 total size: 257934 bytes)
Total Num of Leaked Allocation call stack
Size Blocks Block
Address
====== ====== ========== =======================================
257934 13 - operator new < std::basic_string<char,std::char_traits<char>,std::allocator<char> >::__getRep
execution completed, exit code is 0The original message here was posted almost a month ago. The response by ForteSupport clearly confirms the existence of the problem, and I have written my own tests. Since the time when this problem was acknowledged, Sun has released patches for Forte C++ 6U2, in the same patch line (111685-03 updates 111685-02. 02 introduces the leak) but that patch does not address the problem.
Memory leaks of any type are not acceptable, but this is a nightmare memory leak: it is in library code and it is triggered by a what is a very common operation (string concatenation) in any sort of web or network services product. These are exactly the type of products that cannot tolerate memory leaks, because they have long uptimes.
This memory leak was introduced in a patch that fixed, among other things, the fact that exceptions were not being caught so that any program that threw an exception aborted. While I find it difficult to understand how problems like these could pass any sort of regression testing, this is not a perfect world, and things do go wrong. But what I find absolutely incomprehensible is that it could take a month to release a fix for this. What is the delay? -
Running Total String Concatenation
Hello,
For our Project we need to do String Concatenation, if data has to display only in Footer Running Total String Concatenation works great. If I have to display in Reports Header or Group Header Running Total String Concatenation. I can work around by having Sub Report to get the data, but I have to Text Rotation to display data in 270 degree. Since Sub report is an object, I canu2019t do that.
If any one has any better idea let me know.
Thanks in advanceYes,Thanks a lot My Quesition has been answered. I can rotate the data in Subreports.
-
Unexpected "result of the string concatenation is too long" error
Hello,
I am using Oracle Database 11.2.0.
When querying my database with a common table expression which concatenates VARCHAR2 strings, I receive an ORA-01489 error although I'm doubting that I am concatenating more than 4000 characters.
To be more precise, I have a table entity which basically stores XML elements including their parent element and their sibling position among its siblings. The CREATE statement for this table is listed below.
CREATE TABLE Entity (
ID NUMBER(10,0) NOT NULL PRIMARY KEY,
Name VARCHAR2(100) NOT NULL,
Parent NUMBER(10,0) REFERENCES Entity(ID),
Sibling_Pos NUMBER(2,0) DEFAULT 0
Now, I would like for all elements to be concatenated with their ancestor elements to a structure like this:
"/root_element(sibling_pos)/.../ancestor_element(sibling_pos)/parent_element(sibling_pos)/current_element(sibling_pos)"
(where root_element, ancestor_element, parent_element and current_element are just values from the name column of the entity table)
In order to achieve this, I use a common table expression which concatenates the name and sibling_pos values as shown below:
WITH entity_cte (lvl, id, path) AS (
SELECT 1 AS lvl, id, '/' || name || '(0' || sibling_pos || ')' AS path
FROM entity
WHERE parent IS NULL
UNION ALL (
SELECT lvl + 1 AS lvl, e.id, entity_cte.path || '/' || e.name || '(' || cast(e.sibling_pos AS VARCHAR2(2)) || ')' AS path
FROM entity_cte, entity e
WHERE entity_cte.id = e.parent
SELECT lvl, id, path
FROM entity_cte e
After inserting certain values, I get the ORA-01489 error, that the result of the string concatenation is too long. The maximum is referred to as being 4000 characters for VARCHAR2 in the oracle documentation and in various websites. Of course, it is clear to me by just using the common table expression like that, I could run into such an error. However, due to the structure of my XML documents, I doubted that the resulting strings would be more than 4000 characters long.
So, I rearranged my query in order to count the characters to be concatenated instead of actually concatenating them. The query is stated below as well, the changes are marked bold:
WITH entity_cte (lvl, id, path) AS (
SELECT 1 AS lvl, id, length('/' || name || '(0' || sibling_pos || ')') AS path
FROM entity
WHERE parent IS NULL
UNION ALL (
SELECT lvl + 1 AS lvl, e.id, entity_cte.path + length('/' || e.name || '(' || cast(e.sibling_pos AS VARCHAR2(2)) || ')') AS path
FROM entity_cte, entity e
WHERE entity_cte.id = e.parent
SELECT lvl, id, path
FROM entity_cte e
ORDER BY path DESC
The result of the query gives me a maximum length of 319 characters.
To be sure, I also checked the maximum level depth (indicated by the column named lvl in the common table expression), meaning the maximum number of elements in my path (the concatenated string). The result is 18. As I use VARCHAR2(100) for the name column and add 5 charcaters in each level, the maximum number of characters expected for 18 levels would be 1890.
So, now I wonder is the ORA-01489 maybe raised for another reason? Or is there something else I am missing?
Any help would be appreciated. Further suggestions to track down the error are more than welcome. Thanks in advance.Thanks for the hint, BluShadow.
Still, I don't reach that limit of 1000 characters with my actual data (yet). I understand that if my data changes, I might run into that error with the given query. But I don't understand why this error is raised with the given data I have. The longest string in the column "name" is 32 characters long up to now. When I'm adding 5 characters on each level and I only have max 18 levels that should only result in max 2664 bytes.
@odie_63
The database characterset is: AL32UTF8. If I googled correctly, than it just confirms what BluShadow said, that one character is represented by max 4 byte.
Regarding the sample data, the XML document that I am inserting and which causes the error comprises 1058 nodes. That means I have 1058 entries in my entity table. I think it would be no sense posting all of it here, but is there a way that I can attach a text file containing an insert script to this post?
Some sample data from the entity table orderd by the length of the string in the name column are shown below.
"ID" "NAME" "TYPE" "PARENT" "SIBLING_POS"
90 "representedCustodianOrganization" 1 89 0
109 "serviceProviderOrganization" 1 108 0
58 "standardIndustryClassCode" 1 55 2
186 "standardIndustryClassCode" 1 173 7
150 "standardIndustryClassCode" 1 137 7
106 "dischargeDispositionCode" 1 99 4
35 "administrativeGenderCode" 1 29 3
932 "substanceAdministration" 1 931 0
950 "substanceAdministration" 1 949 0
1043 "representedOrganization" 1 1041 1
71 "representedOrganization" 1 61 6
137 "representedOrganization" 1 128 5
173 "representedOrganization" 1 163 6
504 "substanceAdministration" 1 503 0
223 "representedOrganization" 1 221 1
252 "representedOrganization" 1 250 1
272 "representedOrganization" 1 270 1
477 "substanceAdministration" 1 476 0
481 "manufacturedLabeledDrug" 1 480 0
207 "representedOrganization" 1 205 1
802 "specimenPlayingEntity" 1 801 0
830 "specimenPlayingEntity" 1 829 0
844 "specimenPlayingEntity" 1 843 0
858 "specimenPlayingEntity" 1 857 0
99 "encompassingEncounter" 1 98 0
788 "specimenPlayingEntity" 1 787 0
676 "specimenPlayingEntity" 1 675 0
704 "specimenPlayingEntity" 1 703 0
718 "specimenPlayingEntity" 1 717 0
746 "specimenPlayingEntity" 1 745 0
Any help or further suggestion are appreciated. Thank you. -
String concatenation is the string manipulation method when you join 2 or more strings together.
In PHP it is a quite easy task. You can use the concatenation operator which is the u2018.u2019 (dot). You can join 2 or more strings into one as follows:
$str1 = 'This';
$str2 = 'is a';
$str3 = 'string';
$full = $str1.' '.$str2.' '.$str3;
echo $full; // This is a string
Besides this you can use the operator to append a string to an existing one like this:
$str = 'Main string';
$str .= ' plus another string';
echo $str; // Main string plus another string
If you concatenate a string with a number, the number will (automatically) be converted into a string value, so the output will be u201Cstringu201D:
$num = 100;
$str = $num.' is a number';
echo $str; // 100 is a number
Trade Show Displays is the retail division of Quality One Engineering.Hi skyvia and Circuitbomb welcome to the php forum.
Thanks for enlightening us with your summary of concatenation which is the most basic function in php and to be honest who care which is faster. If you really care find Sarah Golemon's blog and find the entry on what is happening deep inside php in concatenation. Having said that there are far easier ways to slow down php that do concatenation incorrectly.
You could read from a database for example. That is bound to be an order of magnitude slower than concatenating strings.
PHP is fun for a lot of reasons.
I hope you guys both enjoy SAP and PHP in good measure and contribute the interesting things that you are learning on the forums.
Cheers,
Nigel
Edited by: Nigel James on Oct 28, 2010 12:56 PM -
PL?SQL block for string concatenation
Hi,
I have written the following procedure for concatenating the strings from different tables. This is working fine if I run this is SQL commands. But If I put the same in HTMLDB report region, I am getting error "Query cannot be parsed within the Builder. If you believe your query is syntactically correct, check the ''generic columns'' checkbox below the region source to proceed without parsing. ORA-06550: line 1, column 8: PLS-00103: Encountered the symbol "" when expecting one of the following: begin function package pragma procedure subtype type use form current cursor"
I am not able to resolve this.. Please help me..
DECLARE
CURSOR C_Lscape
IS
SELECT PL.pl_id pl_id,PL.partner_name partner_name,
PL.area area,PL.region region,PL.country country,
PL.tier tier,PL.type type,PL.category category,
PL.market_segment market_segment,PL.parent parent,
PL.geo_focus geo_focus,PL.opn_id opn_id,PL.opn_level opn_level,
PL.opn_status opn_status,PL.opn_expirydate opn_expirydate,
pd.types types,pd.apac apac,pd.region pd_region,
pd.country pd_country,pd.value value,pd.sub_value sub_value,
acc.acc_territory_assigned acc_territory_assigned,acc.industry industry,
acc.industry_segment industry_segment,acc.solution_segment solution_segment,
acc.product product,acc.solution_name solution_name,acc.apac acc_apac,
acc.region acc_region,acc.country acc_country,
ad.agreement_type agreement_type,ad.adreement_date adreement_date,ad.credithold_status credithold_status,
ad.agreement_number agreement_number
FROM PARTNER_LANDSCAPE_PL PL
,PARTNERLANDSCAPE_DETAILED PD
,AGREEMENT_DETAILS AD
,ACCELERATE_SOLUTION ACC
WHERE PL.pl_id=pd.pl_id
AND ACC.PL_ID=PL.PL_ID
AND AD.PL_ID=PL.PL_ID
AND (( PL.partner_name=:p18_partner
AND PL.partner_name!='%null%')
OR ( PL.country=:p18_country
AND PL.country!='%null%')
OR ( PL.region=:p18_region
AND PL.region!='%null%')
OR ( PL.area=:p18_area
AND PL.area!='%null%')
OR ( PL.category=:p18_category
AND PL.category!='%null%')
OR ( PL.market_segment=:p18_marketsegment
AND PL.market_segment!='%null')
OR ( PL.tier=:p18_tier
AND PL.tier!='%null%')
OR ( PL.GEO_FOCUS=:p18_geofocus
AND PL.GEO_FOCUS!='%null%')
OR ( pd.sub_value=:p18_industry
OR :p18_industry!='')
OR ( pd.value=:p18_gtmi
OR :p18_gtmi!='')
OR ( pd.value=:p18_productfamily
OR :p18_productfamily!='')
OR ( pd.sub_value=:p18_solutionarea
OR :p18_solutionarea!='')
l_lscape VARCHAR2(4000);
BEGIN
FOR i IN C_Lscape
LOOP
l_lscape := i.pl_id||' : '||i.partner_name||' : '||i.area||' : '||i.region||' : '||i.country||' : '||i.tier||' : '||i.type||' : '||i.category
||' : '||i.market_segment||' : '||i.parent||' : '||i.geo_focus||' : '||i.opn_id||' : '||i.opn_level||' : '||i.opn_status
||' : '||i.opn_expirydate||' : '||i.types||' : '||i.apac||' : '||i.region||' : '||i.pd_country
||' : '||i.value||' : '||i.sub_value||' : '||i.acc_territory_assigned||' : '||i.industry
||' : '||i.industry_segment||' : '||i.solution_segment||' : '||i.product||' : '||i.solution_name
||' : '||i.acc_apac||' : '||i.acc_region||' : '||i.acc_country||' : '||i.agreement_type||' : '||i.adreement_date
||' : '||i.credithold_status||' : '||i.agreement_number;
END LOOP;
dbms_output.put_line(l_lscape);
END;
Regards,
PaI'm doing something similar to what you want to accomplish.
First, I created a view that joins the master and detail tables together. The view uses the STRAGG function ahead of time to concatenate multiple details into one "column" (or field).
Next, in my report region, the SQL query lloks like :
SELECT dep_id, dev_st, oper_tp, sig, NAME,
commod, commod_group,
MIN (usgs_num) KEEP (DENSE_RANK FIRST ORDER BY mt_rec ASC) usgs_num,
MIN (model_name) KEEP (DENSE_RANK FIRST ORDER BY mt_rec ASC) model_name,
MIN (country) KEEP (DENSE_RANK FIRST ORDER BY l_line ASC) country,
MIN (state_prov) KEEP (DENSE_RANK FIRST ORDER BY l_line ASC) state_prov,
MIN (county) KEEP (DENSE_RANK FIRST ORDER BY l_line ASC) county,
MIN (lat_dec) KEEP (DENSE_RANK FIRST ORDER BY g_line ASC) lat_dec,
MIN (lon_dec) KEEP (DENSE_RANK FIRST ORDER BY g_line ASC) lon_dec,
mas_id, mrds_id
FROM NEW_MASTER_QUERY1
WHERE dep_id IN
(SELECT dep_id
FROM search_table where &P3_WHERE_CLAUSE. )
&P3_SEARCH_AREA.
GROUP BY dep_id, dev_st, oper_tp, sig, NAME, commod, commod_group, mas_id, mrds_idEach of the lines above with the MIN() function are "fields" which come from different child tables. My view is getting data from 6 tables, and I only display the data in one line.
Hope this helps some.
Bill Ferguson -
Optimizing String Concatenation
send(Command.SHIP_STATUS+"~"+ID+"~"+planetIndex+"~"+Ship.MINI+"~"+x+"~"+y+"~"+xVelocity+"~"+yVelocity+"~"+hp)In this game, the clients and server will be sending messages like the one above very often, so I want to make sure I am doing it the best way possible.
Should i :
1. Let java do the concatenation for me like I do above.
2. Use StringBuilder
Note: I don't think I want to use StringBuffer b/c i dont need it to be synchronized.I believe code like:
StringBuffer sb = new StringBuffer();
sb.append(someVariable1);
sb.append(delimiter);
sb.append(someVariable2);
sb.append(delimiter);
....It easer to maintain than code like:
String a = someVariable1 + delimiter + someVariable2 + delimiter....Using the first approach you can append as many variables as you want and the code is all visible.
Using the second approach you soon "exceed" reasonable line size. I don't believe you should have line sizes of 200 characters. The above example should not be using a hardcoded literal. So as soon as you replace the literal with a variable you line size jumps.
Again, just my preference. -
Efficient string concatenation
Hi,
In my function module, I have to return many values as just one value - a comma seperated string. Performance is important as there could potentially be more than one hundred thousand values being concatenated.
As the values themselves may have commas in them, I need to escape such commas by a "\" character. I then would also need to escape a "\" character by another "\" character. Standard escape mechanism. Nothing special.
I have listed here are some possible options. Although my pseudo code does not show it, I am looping over the data values. mySingleValue holds the current value.
I am inclined towards option 3 being the best in terms of performance. However, I would appreciate your feedback or any newer suggestions that you may have.
Thank you in advance for your help.
Pradeep
Option 1:
data: myReturnValue type string.
REPLACE ALL OCCURENCES OF '' IN mySingleValue BY '\'.
REPLACE ALL OCCURENCES OF ',' IN mySingleValue BY ','.
CONCATENATE myReturnValue mySingleValue INTO myReturnValue SEPARATED BY ','
Option 2:
data: myReturnValue type string.
data: myReturnValueLen type i.
REPLACE ALL OCCURENCES OF '' IN mySingleValue BY '\'.
REPLACE ALL OCCURENCES OF ',' IN mySingleValue BY ','.
WRITE ',' TO myReturnValue+myReturnValueLen.
myReturnValueLen = myReturnValueLen + 1.
WRITE mySingleValue TO myReturnValue.
myReturnValueLen = myReturnValueLen + STRLEN( mySingleValue ).
OPTION 3:
data: myReturnValue type string.
data: myReturnValueLen type i.
data: ch TYPE char1.
WRITE ',' TO myReturnValue+myReturnValueLen.
myReturnValueLen = myReturnValueLen + 1.
len = STRLEN( mySingleValue ).
DO len TIMES
ch = mySingleValue(sy-index).
if ch EQ '' OR ch EQ ','.
WRITE ',' TO myReturnValue+myReturnValueLen.
myReturnValueLen = myReturnValueLen + 1.
ENDIF.
WRITE ch TO myReturnValue+myReturnValueLen.
myReturnValueLen = myReturnValueLen + 1.
ENDDO.Hi,
Why wouldn't you try reg. expr.
See also http://help.sap.com/saphelp_nw2004s/helpdata/en/42/9d6ceabb211d73e10000000a1553f6/frameset.htm
Eddy
PS.
Put yourself on the SDN world map (http://sdn.idizaai.be/sdn_world/sdn_world.html) and earn 25 points.
Spread the wor(l)d! -
String concatenation, Buffers and a bug
Good morning to the almighty forum.
As I saw in this Thread,
http://forum.java.sun.com/thread.jsp?forum=31&thread=269622
a + b + c + d (all strings) is equal to....
new StringBuffer(a).append(b).append(c).append(d).toString().
If this is correct AND, as seen in the bug reports, java 1.4 has a memory leak in the StringBuffer().toString() method, is it safe to assume that if I have a String intensive program where a lot of a + b + c + d is going on I could have a memory leak?
Does anyone else using 1.4 have any problems with this?
ThanksI have a program that relies heavily on string buffers (It reads from a structured text file char by char until it hits a delimeter then stores the string buffer into an object) I havent noticed any major increase in memory on my system, even after loading 35-40 times. Only major increase I notice is the more information the file has... as is to be expected...
-
how to concatenate two strings in plsql
i have varchar2 column in my table
in my plsql code i want all values in that column into one variable when loop runs..
i use cursors
declare
i varchar2(4000):='0';
cursor c1
is
(select * from gl_je_lines
where period_name='Mar-10'
and reference_10='WRITEOFF');
begin
for cur_record in c1
loop
i:=cur_record.reference_2 + ',' + i;
dbms_output.put_line(i);
end loop;
end;
i got error like
ERROR at line 1:
ORA-06502: PL/SQL: numeric or value error: character to number conversion error
ORA-06512: at line 11
please tell me what is the problem in this codeHi,
As Michaels said, it looks like you want String Aggregation.
LISTAGG is the best way to do that if you're using Oracle 11.<b>2</b>; unfortunately, it doesn't work in Oracle 11.1 (or earlier versions).
This page:
http://www.oracle-base.com/articles/10g/StringAggregationTechniques.php
shows several ways to do String Aggregation in various versions.
If the order of the output is unimportant (as in your example), then I recommend the user-defined aggregate function, called string_agg on that page (but more commonly called stragg).
If the order of the output is important, then the SYS_CONNECT_BY_PATH technique is good. -
Variables formed by string concatenations
I think the code pretty much explains it all. I'm just trying
to get the variable formed by the concatenation, but the things
that I have tried will only return the variable name.
e.g. #URL.11# is the variable im looking forThanks. That was what I was looking for.
-
I would like to calculate dynamically a role to pass to the userInRole: #{!securityContext.userInRole['Prefix}#{sessionScope['current']}#{']}. If current in session is ABC, I would like to generate #{!securityContext.userInRole['PrefixABC']} and use it in a rendered attribute.
Hi,
not sure it does resolve embedded EL subs, but if then the correct way to do so would be
#{!securityContext.userInRole['Prefix'+sessionScope['current']']} --- note sure about the '+' but you figure it out
If this doesn't do it, use a managed bean in session scope and then have your call to managedBean.current returning the prefixed string
Frank
Maybe you are looking for
-
How can I recover my accidentaly deleted address book?
I was working in my address book this morning and selected a contact that I wanted to delete. When I pressed the delete button, all of a sudden my entire address book dissapeared. I'm fairly sure I only selected the specific contact, but apparently s
-
Issues with T420s running win 8.1 x64
I'm having the following issues on a T420s that I recently bought with a fresh install of windows 8.1 x64 + Office 2013, after installing most of the available drivers. The exact product ID is 4171 52U. Function keys not working correctly: Function-f
-
It's official: iPhone 3G doesn't work on Rogers/Fido 3G network
I have been experiencing missing calls since I got the phone but it's getting ridiculous lately. Now about 90% of the calls go directly to voice-mail while on 3G. It's been 2.1 will fix it, then 2.2 will fix it. Reset your phone, reset your settings,
-
Compressor Quick Time error: 0
I was sending a sequence from FCP7 to Compressor, but kept getting Failed Quick Time error : 0. Went back to the time line in FCP7 tried to render the sequence but it failed too, after sometime I narrowed down the clip with the problem and found th
-
Lost Chunks of Content After Conversion from .HLP
I have 26 .HLP files that we converted from .HLP into RoboHelp HTML. At first glance everything seemed fine. Then we noticed the stylesheets got a little messed up and colours were changed but those were easy enough to fix. Then we noticed that som