CFPROCPARAM 500 Points !

Looking to improve the below code so that the first stored procedure and the CF Insert are done in one transaction, if  anything goes wrong a rollback is executed?

I tried my best to get the <cfquery datasource="IntranetBeta"> INSERT INTO CVs.... converted to a stored procedure but I had massive issues trying to get the cfprocparam type="In" cfsqltype="CF_SQL_BLOB"  to work.

I found that others were having the same issues (From Macromedia's Website under cfprocparam description :  -

No screen name said on Nov 7, 2003 at 8:01 AM :
The "cf_sql_blob" value for the "cfsqltype" attribute for <cfprocparam> returns the following error (from SQL Server 2000):

Description:
Attribute validation error for tag CFPROCPARAM.The value of the attribute VALUE is invalid. The value cannot be converted to a string because it is not a simple value.Simple values are booleans, numbers, strings, and date-time values.

Detail:
The value of the attribute VALUE is invalid. The value cannot be converted to a string because it is not a simple value.Simple values are booleans, numbers, strings, and date-time values.

When a <cfqueryparam> is used with the equivalent values, it works. Go figure.



My Code : -

<cfif IsDefined("process")>

<!--- Multi-parameter stored procedure --->
<cfstoredproc procedure="AddCand" datasource="IntranetBeta">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="Title" value="#Form.Title#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="FirstName" value="#Form.FirstName#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="MiddleName" value="#Form.MiddleName#"null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="LastName" value="#Form.LastName#" null="No">
<cfprocparam type="I n" cfsqltype="CF_SQL_VARCHAR" dbvarname="JobTitle" value="#Form.JobTitle#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="Address" value="#Form.Address#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="TownCity" value="#Form.TownCity#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="Country" value="#Form.Country#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="PostCode" value="#Form.PostCode#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="HomeNo" value="#Form.HomeNo#" null="No"
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="MobileNo" value="#Form.MobileNo#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="WorkNo" value="#Form.WorkNo#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="EmergencyNo" value="#Form.EmergencyNo#" null="No">
 <cfprocparam type="In" cfsqltype="CF_SQL_TINYINT" dbvarname="NoticePeriod" value="#Form.NoticePeriod#" null="No">     <cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="MaritalStatus" value="#Form.MaritalStatus#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="Email" value="#Form.Email#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_DATETIME" dbvarname="DOB" value="#Form.DOB#" null="NO">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="Gender" value="#Form.Gender#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="Status" value="#Form.Status#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_INTEGER" dbvarname="SalaryFrom" value="#Form.SalaryFrom#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_INTEGER" dbvarname="SalaryTo" value="#Form.SalaryTo#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="LastUpdatedUser" value="#getauthuser()#" null="No">
<cfprocparam type="out" cfsqltype="CF_SQL_INTEGER" variable="CandID">
</cfstoredproc>



<cfoutput>
      <h3>'#form.lastname#' inserted into candidate Table. The CANDID is #CandID#.</h3>
</cfoutput>

<cfif IsDefined('form.CVFile')>
<cffile action="upload" destination="d:\temp\" filefield="CVFile" nameconflict="makeunique">
     <cfset VARIABLES.ClientFile = CFFILE.ClientFile>
     <cfset VARIABLES.FullMimeType = "#CFFILE.ContentType#/#CFFILE.ContentSubType#">
     <cffile action="readbinary" file="#CFFILE.ServerDirectory#\#CFFILE.ServerFile#" variable="VARIABLES.FileBinaryContent">
     <cfquery datasource="IntranetBeta">
          INSERT INTO CVs (CandIDFK, FileName, FileType, FileContent)
VALUES (
                    <cfqueryparam cfsqltype="cf_sql_integer" value="#CandID#">,
                    <cfqueryparam cfsqltype="cf_sql_varchar" value="#VARIABLES.ClientFile#">,
                    <cfqueryparam cfsqltype="cf_sql_char" value="#VARIABLES.FullMimeType#">,
                    <cfqueryparam cfsqltype="cf_sql_blob" value="#VARIABLES.FileBinaryContent#">
               )
     </cfquery>
     <cffile action="delete" file="#CFFILE.ServerDirectory#\#CFFILE.ServerFile#">
   <cfoutput>done</cfoutput>
</cfif>

 
<cfelse>

<cfform name="CandAdd" action="CandAdd.cfm" method="post" enctype="multipart/form-data">

<input type="hidden" name="Process" value="1">

 <table width="100%"  border="0" cellspacing="20" cellpadding="0" align="center">
  <tr>
    <td colspan="2"><table width="100%"  border="0" cellspacing="0" cellpadding="0" bgcolor="f2f1ee">
      <tr bgcolor="422184">
        <td valign="middle" colspan="4" align="center"><font class="menuhead">REGISTER CANDIDATE</font></td>
         </tr>
        <tr bgcolor="cccccc">
        <td colspan="4"><font class="mainBlack">Personal Details</font></td>
      </tr>
      <tr>
        <td width="19%"><font class="smallBlack">Title</font></td>
        <td width="32%"><cfinput class="text" name="Title" type="text"size="35"></td>
        <td width="16%"><font class="smallBlack">DOB</font></td>
        <td width="33%"><cfinput class="text" name="DOB" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">First Name</font></td>
        <td><cfinput class="text" name="FirstName" type="text"size="35"></td>
        <td><font class="smallBlack">Gender</font></td>
        <td><cfinput class="text" name="Gender" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Middle Name</font></td>
        <td><cfinput class="text" name="MiddleName" type="text"size="35"></td>
        <td><font class="smallBlack">Marital Status</font></td>
        <td><cfinput class="text" name="MaritalStatus" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Last Name</font></td>
        <td><cfinput class="text" name="LastName" type="text"size="35"></td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
    </table></td>
  </tr>
  <tr>
    <td width="50%"><table width="100%"  border="0" cellspacing="0" cellpadding="0" bgcolor="f2f1ee">
      <tr bgcolor="cccccc" >
        <td colspan="2"><font class="mainBlack">Address Details</font></td>
        </tr>
      <tr>
        <td width="39%"><font class="smallBlack">Address</font></td>
        <td width="61%"><cfinput class="text" name="Address" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Town/City</font></td>
        <td><cfinput class="text" name="TownCity" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Country</font></td>
        <td><cfinput class="text" name="Country" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Post Code</font></td>
        <td><cfinput class="text" name="PostCode" type="text"size="35"></td>
      </tr>
    </table></td>
    <td width="50%"><table width="100%"  border="0" cellspacing="0" cellpadding="0"bgcolor="f2f1ee" >
      <tr bgcolor="cccccc">
        <td colspan="2"><font class="mainBlack">Career Details</font></td>
        </tr>
      <tr>
        <td><font class="smallBlack">Sector Experience</font></td>
        <td><cfinput class="text" name="SectorExp" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Job Title</font></td>
        <td><cfinput class="text" name="JobTitle" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Salary Expectations</font></td>
        <td><cfinput class="text" name="SalaryFrom" type="text"size="20">
        to
          <cfinput class="text" name="SalaryTo" type="text"size="20"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Notice Period</font></td>
        <td><cfinput class="text" name="NoticePeriod" type="text"size="35"></td>
      </tr>
    </table></td>
  </tr>
  <tr>
    <td><table width="100%"  border="0" cellspacing="0" cellpadding="0" bgcolor="f2f1ee">
      <tr bgcolor="cccccc">
        <td colspan="2"><font class="mainBlack">Contact Details</font></td>
        </tr>
      <tr>
        <td width="39%"><font class="smallBlack">Home No</font></td>
        <td width="61%"><cfinput class="text" name="HomeNo" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Mobile No</font></td>
        <td><cfinput class="text" name="MobileNo" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Work No</font></td>
        <td><cfinput class="text" name="WorkNo" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Emergency No</font></td>
        <td><cfinput class="text" name="EmergencyNo" type="text" size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Email Address</font></td>
        <td><cfinput class="text" type="text" name="Email" size="35"></td>
      </tr>
    </table></td>
    <td width="50%"><div align="center">
      <table width="100%"  border="0" cellspacing="20" cellpadding="0">
        <tr>
          <td width="24%"><font class="smallBlack">Attach CV</font></td>
          <td width="76%"><input type="file" name="CVFile"></td>
            </tr>
        <tr>
          <td colspan="2"><div align="center"><font class="smallBlack">Status</font></div><cfinput class="text" name="Status" type="text"size="35"></td>
          </tr>
      </table>
    </div></td>
  </tr>
</table>

<table width="90%"  border="0" cellspacing="0" cellpadding="0">
  <tr>
    <td align="right"><input class="text" type="Submit" value="Add Candidate"></td>
  </tr>
</table>

</cfform>
</cfif>


The above code works fine I just want to make it a bit more slicker ie if one query fails everything is rolled back


500 Points for Grabs !!  (Ohh I have updated CF 6.1 with the lastest updater)

Jonny
jturkingtonAsked:
Who is Participating?
 
hartCommented:
ok how about this...

you put everything into the stored proc...
i understand that u r having problems in the blob field.

instead of inserting the whole file data... why not keep it in a folder and just store the path of the folder in the database...
this way only thing u have to read is the path and the file name from the db and then just read the data from the file..

And your transaction checks also can be put in the stored procedure...
by error catching in the stored proc itself...

Regards
Hart
0
 
mrichmonCommented:
place inside <cftransaction action="begin">

Then <cftransaction action="commit"></cftransaction> at the end.


With queries this autorolls back when one fails.  I am not sure how it will work with a stored proceedure.  

Another solution is to send the parameters to the proc for the insert too and have the proc do both...
0
 
jturkingtonAuthor Commented:
Tried sending the parameters to the proc, cant use the CF_SQL_BLOB with cfprocparam as mentioned above

Jonny
0
Free Tool: IP Lookup

Get more info about an IP address or domain name, such as organization, abuse contacts and geolocation.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
mrichmonCommented:
oh I see that is in the insert portions - sorry overlooked that.

Well then try the cftransaction method, but as I mentioned I do not know if it can rollback a transaction....
0
 
mrichmonCommented:
You could manually test by putting <cftransaction action="rollback"> instead of commit and see if it properly rolled back since this would force a rollback every time.

Then put it back if it dooes work and you will know that on a fialure it will successfully rollback....
0
 
jturkingtonAuthor Commented:
Can you tell me where exactly to stick the cftransaction tags in my code as im having no success

Thanks for your help

Jonny
0
 
mrichmonCommented:
Well it is kind of hard because your CF code is intermixed with the html portion of the page which is generally a bad idea, and I am having trouble matching the cfifs since it is hard to see indenting on this site, but here is a shot....

<cfif IsDefined("process")>

<cftransaction action="begin">

<!--- Multi-parameter stored procedure --->
<cfstoredproc procedure="AddCand" datasource="IntranetBeta">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="Title" value="#Form.Title#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="FirstName" value="#Form.FirstName#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="MiddleName" value="#Form.MiddleName#"null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="LastName" value="#Form.LastName#" null="No">
<cfprocparam type="I n" cfsqltype="CF_SQL_VARCHAR" dbvarname="JobTitle" value="#Form.JobTitle#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="Address" value="#Form.Address#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="TownCity" value="#Form.TownCity#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="Country" value="#Form.Country#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="PostCode" value="#Form.PostCode#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="HomeNo" value="#Form.HomeNo#" null="No"
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="MobileNo" value="#Form.MobileNo#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="WorkNo" value="#Form.WorkNo#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="EmergencyNo" value="#Form.EmergencyNo#" null="No">
 <cfprocparam type="In" cfsqltype="CF_SQL_TINYINT" dbvarname="NoticePeriod" value="#Form.NoticePeriod#" null="No">     <cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="MaritalStatus" value="#Form.MaritalStatus#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="Email" value="#Form.Email#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_DATETIME" dbvarname="DOB" value="#Form.DOB#" null="NO">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="Gender" value="#Form.Gender#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_CHAR" dbvarname="Status" value="#Form.Status#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_INTEGER" dbvarname="SalaryFrom" value="#Form.SalaryFrom#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_INTEGER" dbvarname="SalaryTo" value="#Form.SalaryTo#" null="No">
<cfprocparam type="In" cfsqltype="CF_SQL_VARCHAR" dbvarname="LastUpdatedUser" value="#getauthuser()#" null="No">
<cfprocparam type="out" cfsqltype="CF_SQL_INTEGER" variable="CandID">
</cfstoredproc>




<cfif IsDefined('form.CVFile')>
<cffile action="upload" destination="d:\temp\" filefield="CVFile" nameconflict="makeunique">
     <cfset VARIABLES.ClientFile = CFFILE.ClientFile>
     <cfset VARIABLES.FullMimeType = "#CFFILE.ContentType#/#CFFILE.ContentSubType#">
     <cffile action="readbinary" file="#CFFILE.ServerDirectory#\#CFFILE.ServerFile#" variable="VARIABLES.FileBinaryContent">
     <cfquery datasource="IntranetBeta">
          INSERT INTO CVs (CandIDFK, FileName, FileType, FileContent)
VALUES (
                    <cfqueryparam cfsqltype="cf_sql_integer" value="#CandID#">,
                    <cfqueryparam cfsqltype="cf_sql_varchar" value="#VARIABLES.ClientFile#">,
                    <cfqueryparam cfsqltype="cf_sql_char" value="#VARIABLES.FullMimeType#">,
                    <cfqueryparam cfsqltype="cf_sql_blob" value="#VARIABLES.FileBinaryContent#">
               )
     </cfquery>
     <cffile action="delete" file="#CFFILE.ServerDirectory#\#CFFILE.ServerFile#">
<cftransaction action="commit">
</cftransaction>


<cfoutput>
     <h3>'#form.lastname#' inserted into candidate Table. The CANDID is #CandID#.</h3>
</cfoutput>
   <cfoutput>done</cfoutput>
</cfif>

 
<cfelse>

<cfform name="CandAdd" action="CandAdd.cfm" method="post" enctype="multipart/form-data">

<input type="hidden" name="Process" value="1">

 <table width="100%"  border="0" cellspacing="20" cellpadding="0" align="center">
  <tr>
    <td colspan="2"><table width="100%"  border="0" cellspacing="0" cellpadding="0" bgcolor="f2f1ee">
      <tr bgcolor="422184">
        <td valign="middle" colspan="4" align="center"><font class="menuhead">REGISTER CANDIDATE</font></td>
        </tr>
       <tr bgcolor="cccccc">
        <td colspan="4"><font class="mainBlack">Personal Details</font></td>
      </tr>
      <tr>
        <td width="19%"><font class="smallBlack">Title</font></td>
        <td width="32%"><cfinput class="text" name="Title" type="text"size="35"></td>
        <td width="16%"><font class="smallBlack">DOB</font></td>
        <td width="33%"><cfinput class="text" name="DOB" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">First Name</font></td>
        <td><cfinput class="text" name="FirstName" type="text"size="35"></td>
        <td><font class="smallBlack">Gender</font></td>
        <td><cfinput class="text" name="Gender" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Middle Name</font></td>
        <td><cfinput class="text" name="MiddleName" type="text"size="35"></td>
        <td><font class="smallBlack">Marital Status</font></td>
        <td><cfinput class="text" name="MaritalStatus" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Last Name</font></td>
        <td><cfinput class="text" name="LastName" type="text"size="35"></td>
        <td>&nbsp;</td>
        <td>&nbsp;</td>
      </tr>
    </table></td>
  </tr>
  <tr>
    <td width="50%"><table width="100%"  border="0" cellspacing="0" cellpadding="0" bgcolor="f2f1ee">
      <tr bgcolor="cccccc" >
        <td colspan="2"><font class="mainBlack">Address Details</font></td>
        </tr>
      <tr>
        <td width="39%"><font class="smallBlack">Address</font></td>
        <td width="61%"><cfinput class="text" name="Address" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Town/City</font></td>
        <td><cfinput class="text" name="TownCity" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Country</font></td>
        <td><cfinput class="text" name="Country" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Post Code</font></td>
        <td><cfinput class="text" name="PostCode" type="text"size="35"></td>
      </tr>
    </table></td>
    <td width="50%"><table width="100%"  border="0" cellspacing="0" cellpadding="0"bgcolor="f2f1ee" >
      <tr bgcolor="cccccc">
        <td colspan="2"><font class="mainBlack">Career Details</font></td>
        </tr>
      <tr>
        <td><font class="smallBlack">Sector Experience</font></td>
        <td><cfinput class="text" name="SectorExp" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Job Title</font></td>
        <td><cfinput class="text" name="JobTitle" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Salary Expectations</font></td>
        <td><cfinput class="text" name="SalaryFrom" type="text"size="20">
        to
          <cfinput class="text" name="SalaryTo" type="text"size="20"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Notice Period</font></td>
        <td><cfinput class="text" name="NoticePeriod" type="text"size="35"></td>
      </tr>
    </table></td>
  </tr>
  <tr>
    <td><table width="100%"  border="0" cellspacing="0" cellpadding="0" bgcolor="f2f1ee">
      <tr bgcolor="cccccc">
        <td colspan="2"><font class="mainBlack">Contact Details</font></td>
        </tr>
      <tr>
        <td width="39%"><font class="smallBlack">Home No</font></td>
        <td width="61%"><cfinput class="text" name="HomeNo" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Mobile No</font></td>
        <td><cfinput class="text" name="MobileNo" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Work No</font></td>
        <td><cfinput class="text" name="WorkNo" type="text"size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Emergency No</font></td>
        <td><cfinput class="text" name="EmergencyNo" type="text" size="35"></td>
      </tr>
      <tr>
        <td><font class="smallBlack">Email Address</font></td>
        <td><cfinput class="text" type="text" name="Email" size="35"></td>
      </tr>
    </table></td>
    <td width="50%"><div align="center">
      <table width="100%"  border="0" cellspacing="20" cellpadding="0">
        <tr>
          <td width="24%"><font class="smallBlack">Attach CV</font></td>
          <td width="76%"><input type="file" name="CVFile"></td>
          </tr>
        <tr>
          <td colspan="2"><div align="center"><font class="smallBlack">Status</font></div><cfinput class="text" name="Status" type="text"size="35"></td>
         </tr>
      </table>
    </div></td>
  </tr>
</table>

<table width="90%"  border="0" cellspacing="0" cellpadding="0">
  <tr>
    <td align="right"><input class="text" type="Submit" value="Add Candidate"></td>
  </tr>
</table>

</cfform>
</cfif>
0
 
jturkingtonAuthor Commented:
No go error received :-

The tag &lt;cfif&gt;, on line 50, column 2, requires an end tag.  
The &lt;cfif&gt; tag requires an end tag to nest within &lt;cftransaction&gt;, which began on line 13, column 2

Any other suggestions or maybe a better way to structure the code ie separate CF code from HTML ?

Thanks for your help

Jonny
0
 
mrichmonCommented:
Well that error is not related to what I added.  I also moved the cfoutput, but that shouldn't have done anything.

But you can see where I put the cftransaction tags.

Try just putting those tags into your actual code....
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.