Solved

converting variable  from complex type to simple???

Posted on 2004-09-30
28
259 Views
Last Modified: 2013-12-24
Hi,

How can I convert a complex variable to a simple one.

I am getting this error message when trying to outptu a query.

Attribute validation error for tag cfoutput.  
The value of the attribute query, which is currently "qryResultSet", is invalid.  

I am invoking a CFC, and saving the resultset.

If I do a dump of the CFC, it works, but soon as I try to do a <cfoutput query="queryName">  I get the above message.

I tried doing <cfset newVariable = #cfcResultSet#>

Basically assign a new variable the value that is returned from my cfc, but still no luck...

The query is valid and it does work because the dump outputs the query just fine, but when I do a <cfoutput>, no luck..

Any help appreciated.
0
Comment
Question by:Westside2004
  • 11
  • 8
  • 5
  • +2
28 Comments
 
LVL 17

Expert Comment

by:Tacobell777
Comment Utility
How do you output it?

#queryName.columnName# ??

Can you show some code?

Have you tried isQuery() to see if its really a query?
0
 
LVL 1

Author Comment

by:Westside2004
Comment Utility
I am doing

<cfoutput query="queryName">
<table>
 <tr>
   <td></td>
 </tr>
</cfoutput>

When I use the above, I get the error msg:

Attribute validation error for tag cfoutput.  
The value of the attribute query, which is currently "qryResultSet", is invalid.

It is valid, the problem is its a complex datatype, and its not allowing me to output it..

0
 
LVL 5

Expert Comment

by:smaglio81
Comment Utility
That is a really odd error.

Something that I do more often than I should is forget to place an ending </cfoutput> tag, and that error also comes up.

But to the original point of converthing the query to a simple value. Here is a really hacky way of getting around the strange cfoutput error (I have used this method before, and I have felt ashamed for it .... but whatever, it works!)

<cfscript>
   obj = createObject('component','somecomponent');        // you know, create the component
   q = obj.getQueryResultSet();                                        // get a result set with fields x, y, z
   count = q.RecordCount;                                               // the number of records returned
</cfscript>

// display some header
x, y, z<br />

// loop through the query and output the information
<cfloop index="i" from="1" to="#count#">
   <cfoutput>
       #q.x[i]#, #q.y[i]#, #q.z[i]#<br />
   </cfoutput>
</cfloop>

// and heres some more fun, that uses the same method

// creating a structure that contains the same data
<cfscript>
   // setup a struct for the data
   queryBook = structNew();
   
   // loop through the query
   for( i = 1; i lte count; i = i + 1 ) {
      // create a new structure to hold each record
       record = structNew();

       // fill in the record
       record.x = q.x[i];
       record.y = q.y[i];
       record.z = q.z[i];

        // add to the base structure
        insertStruct( queryBook, i, record );
   }
</cfscript>


The method to output the query is just abusing the direct data maipulation ability of query sets.

The second loop to create the structure does become a useful methodology when making heavy use of components. Since components are CF's way to implement Objects from Java, which can be very useful for abstracting userdata from bussiness logic. If you ever feel the need to use objects to store an individual's information then you will probably come upon a situation where you would need to grab a whole bunch of objects at once. In that situation the second algorithm is useful methodology to organize a group of objects and interact with them as if they were stored in a query/list.

HTH

Steven

PS. I just read back through the last paragraph and it gets kinda confusing. But, I don't really have the energy right now to bore you with another overly explicit example/explination. So, please forgive the obscurity.
0
 
LVL 17

Expert Comment

by:Tacobell777
Comment Utility
When you do a cfdump of qryResultSet right above the loop it is present?

Show the code wher eyou assign the query to a variable, and the CFC..

Are you sure the cfc is set to return a query and not structure or something?
0
 
LVL 5

Expert Comment

by:smaglio81
Comment Utility
Something has been bothering me since my last post.

That error just seems to strange.

You normally get that error when the variables name entered isn't a vaild query. It's like the error says, "Attribute validation error", the attribute is value passed through query="queryName". And when it tries to validate that 'queryName' is a real query then it fails, and the error is produced.

Have you tried to check the query with something like:

<cfoutput>#isQuery( queryName )#</cfoutput>

And if that returns a positive response, then the only thing that would make since is that the variable name is mispelled someplace.

Damn, this is a really strange error.

Steven
0
 
LVL 1

Author Comment

by:Westside2004
Comment Utility
Hi,

I never knew about that IsQuery function..

It returned: NO

Its not a query... its a struct I think

I am sure I am close to getting this now that we know its not a query.....

any thoughts?
0
 
LVL 5

Expert Comment

by:smaglio81
Comment Utility
yeah, like Tacobell was thinking ... could you post the code for the method call in the component. (You know where to hide important information and such). BTW, thanks for the quick replies, this makes the debugging a lot easier.

Steven
0
 
LVL 21

Expert Comment

by:pinaldave
Comment Utility
may sound stupid but quick tip.
Just scope your variable for good reason like do url.variable or queryname.newvalue or something...
Regards,
---Pinal
0
 
LVL 1

Author Comment

by:Westside2004
Comment Utility
Hi,

I wish I could post the code.. hmmmm..

Tacobell is correct, the cfc does not return a query, it returns a structure....

Based on that, how could I convert it?

<cfinvoke component="theComponent" method="checkIt"  returnvariable="myQuery">

The first line is like that... the rest is not really relevant..

so naturally, I tried to <cfoutput query=#myQuery#>

The cfc returns a structure.. so I can't do it like above.. I need to convert it somehow to a simple type... something to that extent..

Wish I could post more, but the above should be enough...

Any ideas?
0
 
LVL 21

Expert Comment

by:pinaldave
Comment Utility
okey buddy... CFC does return us stucture and you can use the structure...
Steven already showed you how to loop through it...
0
 
LVL 5

Accepted Solution

by:
smaglio81 earned 250 total points
Comment Utility
ummm... well thanks Pinal, but heres the explicit way of doing that looping:

Before I start in on the code, I want to go over something that I found interesting (well it interesting to me, for most people it is boring). It has to do with queries and structures. I have been looking into the way that Coldfusion has put together all variables, no matter what they produce. All variables in CF are strings. So lets start with the knowledge that basic variables are strings. From that basic type everything is created ... numerics, booleans, structures ... everything. Numerics are strings that all char values evaluate to numeric values. Booleans are strings that evaluate to '1' or '0' chars. blah blah blah. I always ramble for too long (sorry all =) ).

But anyways, lets look at the structure thing.

So lets say that you are getting back a structre from your component. Then the first thing that you should do is use a <cfdump> to see what the "key" fields are named (those are the ones listed on the left side of the <cfdump> output. For the most part all structures are formed into key/value pairs. If I were to try to relate it ... too what I think is your output of your <cfdump> (from your explination that a cfdump outputs what looks like a query) ... then on the left you have the record numnber and on the right you have another structure. And that structure on the right side has the information you want to output. If this is the case then you want to do this:

<cfscript>
   obj = createObject('component','componentPath');   // create the object
   struct = obj.methodCall();                                      // get the result from the method call
   count = structCount( struct );                                  // get the number of rows in the struct
</cfscript>

// place some header information
// I am going to use the same type of sample as above; where every row in the structure has a key x, y, z
x, y, z<br />

// now lets go through the loop
<cfloop index="i" from="1" to="#count#">

   // lets get the first value/object/record
   record = struct["#i#"];

   // now lets otuput the infromation
   <cfoutput>
      #record.x#, #record.y#, #record.z#<br />
   </cfoutput>
</cfloop>

This would give your view page the right output for a structure that was setup like a query, but I have a feeling like this isn't happening. Something bothers me about the way you say that all the data looks like a query result set when you use <cfdump> (from the original post).

The more I think about it, the more the more I think about object oriented programming. I really want you to think about possibly converting your query into its own method, and just having that method return the query set from its <cfquery>. "Why?", you might ask. And the answer is .... because its simplistic. Every time I see really good code (like the stuff in Bjarne Stroustrup's book). I think "Damn! he abstracted everything!" And I think that is the methodology you should take with you when programming anything in CFMX (because it is based on Object abstraction). The more you abstract any single function or procedure the more re-usability you have in your code, and the more re-usabliity you have, the less time it takes to code a new project.

Now, I can guess that you do some data manipulation with your <cfquery> result set before returning it from the method call; and that is good. But, to harp on a point, you can have the <cfquery> call in its own method before doing the data manipulation.

Well, I have been rambling for too long (one of the reasons why I am teacher ... I think, you would have to ask the students); the whole point is this. You have to use the <cfdump> to find the key/value pairing of the structre that is returned to you. Then using that key as an index you can do a <cfdump> on the structure held within it. Here's an example:

<cfdump var="#theStructure#">'s output:

"structre name"
name                         someValueForTheName
email                          someValueForTheEmail
address                      objForAnAddress

then you can do
<cfdump var="#theStructure.address#">, which output would look like this:

"address component name"
streetLine1                   aStreetAddressLine1
streetLine2                   aStreetAddressLine2(for apartments/foreign addresses)
country                         objCountry
city                               objCity
zip                                 anAmericanZipCode

If you see this kind of output on your cfdump's and what you want is the city, then in the loops you would have:

<cfloop index="i" from="1" to="#count#">
       // grab the address object
       address = theStructure["address"];

       // output the city
       <cfoutput>#address.city#</cfoutput>
</cfloop>

Anyways, I just wrote an anthology; so I will stop there.

Steven
0
 
LVL 17

Expert Comment

by:Tacobell777
Comment Utility
who wrote the cfc? if its you change the cfc, if its not you then you will have to work with the structure.

<cfloop collection="#myQuery#" item="item">
#myQuery.keyName#<br>
</cfloop>

To see what keys there are in the structure do a dump...
0
 
LVL 5

Expert Comment

by:smaglio81
Comment Utility
yes ... YES! YES! YES!!!

Tacobell was probably writing his port while I was writing my thesis (sorry about that all ).

I have been wondering the same thing; westside2004, you dont seem to want to change the data that is being returned is it because you are someone else returned data?

Steven
0
 
LVL 5

Expert Comment

by:smaglio81
Comment Utility
Shoot, let me try that again:

 yes ... YES! YES! YES!!!

Tacobell was probably writing his post while I was writing my thesis (sorry about that al ... yeah, truly sorry ).

I have been wondering the same thing:

westside2004, you dont seem to want to change the data that is being returned. Is it because you are using someone else's returned data?

Steven
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 1

Author Comment

by:Westside2004
Comment Utility
Hi,

I dont know if this makes matters worse, but:

I can simply do a dump like

<cfdump var="#Results#">

And I see my query, I see the db columns, I see the values in each column.

Here is a link to a blurred out screen shot, you can see the dump of the cfc method that I call..

Hopefully just by looking you can see enough...

http://www.brilliantusa.net/qry.jpg

This should clear it up... the query is in PURPLE and you see it says "query"

So again, a simple <cfdump var="#Results#"> works and I see the dump just fine....

I dont think a loop is needed here as there is only one record returned....

-ws

0
 
LVL 5

Expert Comment

by:smaglio81
Comment Utility
Sweet!!!!

That was a great image.

so you query is hidden within the value portion of the structure, heres what you do:

<cfscript>
   obj = createObject('component','compnentName');
   queryResults = obj.calMethod().NameOfTheFieldThatIsInTheLeftColumnThatisBlury;
</cfscript>

<cfoutput query="#queryResults#">
   // code goes here
</cfoutput>

I truly hope this helps, because it looks like you query is just hidden within the structure that you outputed with the <cfdump>.

Steven
0
 
LVL 5

Expert Comment

by:smaglio81
Comment Utility
hahaha, I have been drinking too much; heres the update

<cfoutput query="queryResults">
   // code goes here
</cfoutput>

I apologize to everyone reading this thread. I really should stop drinking ok Thursday's.

Steven
0
 
LVL 17

Expert Comment

by:Tacobell777
Comment Utility
I could not see the image properly, but what stops you from posting the code? do you think you have something wonderful that you cannot share? I dont think there is anything I have not programmed, so no owrries there...

Post the code and we'll get this solved for you in a second..
0
 
LVL 1

Author Comment

by:Westside2004
Comment Utility
Haha, no nothing wonderful, that is last thing I think......

Here is the code block:


<cfinvoke component="theComponent" method="theMethod"  returnvariable="returndata">
      <cfinvokeargument name="firstName" value="'#FORM.firstName#">
      <cfinvokeargument name="lastName" value="'#FORM.lastName#">
</cfinvoke>


<cfoutput query="returndata">
 <table width="100%" border="0" cellpadding="3" cellspacing="3" class="tableborder2">
  <tr>
    <td>#column1#</td>
    <td>#column2#</td>
 </tr>
</table>
</cfoutput>
0
 
LVL 1

Author Comment

by:Westside2004
Comment Utility
With that above code, I get this error:

Attribute validation error for tag cfoutput.  
The value of the attribute query, which is currently "returndata", is invalid.  

I do a <cfdump var="#returndata#"> and it works fine, I see the dump which is in the screenshot....

Also, how can you edit your postings if you make a mistake?  Off topic but was curious..
0
 
LVL 17

Expert Comment

by:Tacobell777
Comment Utility
yeah but thats not the CFC itself...
0
 
LVL 5

Expert Comment

by:smaglio81
Comment Utility
Don't worry about the editing being off topic; because I have been wondering the same thing (as you can see my multiple posts).

But what worries me is that you get the same error.

AHHHHHHHHHHHHHHHHHHH!!!!!!

Okay, here is what I am thinking...

wait .. forget my thinking; lets start the debugging procedure. Let's start with the <cfoutput>#isQuery( returndata )#</cfoutput>. And then if that comes up positive, trying to reference the data out with returndata.fieldName[1] for each field name.

Because if you get a "Yes" from the 'isQuery( queryvariable)#</cfoutput> thing, then CF is doing somethinhg really wrong ,But if you can directly refernce data, then  you can get data from the from the 'returndata.fieldname[1]' thing, and then you can use the loop trick from above.

HTH ( I really do, because this problem is starting to make me think that I am going to have to email Sean Corfield; and he is a busy guy).

Steven
0
 
LVL 1

Author Comment

by:Westside2004
Comment Utility
The isQuery() returns "NO"..

The results are stored in a structure, and I can't figure out how to access the query object that is within the structure...

0
 
LVL 1

Author Comment

by:Westside2004
Comment Utility
Hi,

Well, thanks for all the help.. appreciated.

The CFC is too long, has too much in it.. would open up a new can of worms..

I will struggle with it...

Its also a bit late here.... will post back in morning with an update..

Thanks Tacobell, appreciate the help and the rest of you as well...

If anything comes to mind, let me know....

The IsQuery() returns no, so its not a query.... its a strucutre that is coming back..
0
 
LVL 5

Expert Comment

by:smaglio81
Comment Utility
okay thats it!!!!

Here is my MSN messenger, just lookup "smaglio81@hotmail.com". And for AiM just lookup 'smaglio81'.

I know its generic but its help with all the loging into porn sites. J/K ... I wish I had the money for that.


haha,

Steven
0
 
LVL 5

Expert Comment

by:smaglio81
Comment Utility
Alright, I am going to sleep. You can catch tmrw morning (aroud 7 hourws from now) at work (my boss will be angry; but once I explain its a CF problem he will be cool with it ... he is patrich146 on most forums).

Steven
0
 
LVL 9

Expert Comment

by:digicidal
Comment Utility
I would recommend simply using the cold fusion functions for creating a 'virtual' query from your structure.

Consider the following example from the documentation:

<h3>QueryNew Example</h3>
<p>We will construct a new query with two rows:
<cfset myQuery = QueryNew("name, address, phone")>
<!--- make some rows in the query --->
<cfset newRow  = QueryAddRow(MyQuery, 2)>
<!--- set the cells in the query --->
<cfset temp = QuerySetCell(myQuery, "name", "Fred", 1)>
<cfset temp = QuerySetCell(myQuery, "address", "9 Any Lane", 1)>
<cfset temp = QuerySetCell(myQuery, "phone", "555-1212", 1)>
<cfset temp = QuerySetCell(myQuery, "name", "Jane", 2)>
<cfset temp = QuerySetCell(myQuery, "address", "14 My Street", 2)>
<cfset temp = QuerySetCell(myQuery, "phone", "555-1444", 2)>
<!--- output the query --->
<cfoutput query = "myQuery">
<pre>#name#  #address#  #phone#</pre>
</cfoutput>  
To get any element in the query, we can output it individually
<cfoutput>
  <p>#MyQuery.name[2]#'s phone number: #MyQuery.phone[2]#
</cfoutput>

In this case the entries are static in definition, but you could just as easily loop through your structure variable, and inside the loop...

1) create a row - as in the example or if in CFSCRIPT block by simply adding QueryAddRow(MyVarName,1);
2) populate the appropriate column values by placing the current pointer row of your structure.

that's it... that way you don't have to worry... the functions will create a perfect CF query variable including all the extended information in case you want that in later handling code (MyVarName.RecordCount will return a value as will MyVarName.CurrentRow, etc... just like a SQL populated query) and it's already pre-compiled so it should actually take less time to parse than hand-coded workarounds do!
0
 
LVL 9

Expert Comment

by:digicidal
Comment Utility
As a further aside, yes you can also run a query of queries if you so desired on your 'virtual' query... the only caveat is that, of course, it only resides in memory so you can't just cache it and look it up again without creating it all over again.  Other than that there is no difference in the way CF looks at your 'virtual' query var and a standard SQL queried one.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

In our day to day coding, how many times have we come across a necessity to check whether a URL is a broken link or not? For those of you that answered countless and are using ColdFusion like myself, then this article is for you.  It will show yo…
When it comes to showing a 404 error page to your visitors, you do not want that generic page to show, and you especially do not want your hosting provider’s ad error page to show either. In this article, I will show you how to enable the custom 40…
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

8 Experts available now in Live!

Get 1:1 Help Now