/* *************************************************************************
**   (c) Copyright IBM Corp. 2007 All rights reserved.
**   
**   The following sample of source code ("Sample") is owned by International 
**   Business Machines Corporation or one of its subsidiaries ("IBM") and is 
**   copyrighted and licensed, not sold. You may use, copy, modify, and 
**   distribute the Sample in any form without payment to IBM, for the purpose of 
**   assisting you in the development of your applications.
**   
**   The Sample code is provided to you on an "AS IS" basis, without warranty of 
**   any kind. IBM HEREBY EXPRESSLY DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR 
**   IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
**   MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Some jurisdictions do 
**   not allow for the exclusion or limitation of implied warranties, so the above 
**   limitations or exclusions may not apply to you. IBM shall not be liable for 
**   any damages you suffer as a result of using, copying, modifying or 
**   distributing the Sample, even if IBM has been advised of the possibility of 
**   such damages.
** *************************************************************************
**                                                                          
**  SAMPLE FILE NAME: xupdate.sqc                                          
**                                                                          
**  PURPOSE:  To demonstrate how to insert, delete, update, replace, and rename 
**            one or more XML documents or document fragments using transform 
**            expressions. 
**                                                                          
**  USAGE SCENARIO: The orders made by customers are stored in the existing 
**                  PurchaseOrder system. A customer has ordered some items initially, 
**                  and now the customer wants to add some more items and remove some 
**                  items from the list. This sample will show how the order is modified 
**                  using the XQuery transform expression and updating expressions.                 
**                                                                          
**  PREREQUISITE: NONE
**                                                                          
**  EXECUTION:    bldapp xupdate       (Build the sample)
**                xupdate              (Run the sample)   
**                                                                          
**  INPUTS:       NONE
**                                                                          
**  OUTPUTS:      Successful updation of the purchase orders.
**                                                                          
**                           
**                                     
**  SQL STATEMENTS USED:
**        INSERT
**        UPDATE  
**        DROP   
**
**  SQL/XML FUNCTIONS USED:                                                  
**        XMLQUERY                                                       
**  
*****************************************************************************
**
** For more information on the sample programs, see the README file.
**
** For information on developing embedded SQL applications see the Developing Embedded SQL Applications book.
**
** For information on using SQL statements, see the SQL Reference.
**
** For information on DB2 APIs, see the Administrative API Reference.
**
** For the latest information on programming, building, and running DB2
** applications, visit the DB2 Information Center:
**     http:**www.software.ibm.com/data/db2/udb/ad
****************************************************************************
**
**  SAMPLE DESCRIPTION                                                      
**
** *************************************************************************
**  1. Insert Expression  -- Insert a new element to the existing XML document/fragment.
**  2. Delete Expression  -- Delete some elements from the exisitng XML document/fragment.
**  3. Replace value of Expression -- i)  Replace the value of an element
**                                    ii) Replace the value of attribute
**  4. Replace Expression -- Replace an element and attribute
**  5. Rename Expression  -- i)  Rename an element in the existing XML document/fragment.
**                           ii) Rename an attribute in the existing XML document/fragment.
**  6. Insert and Replace Expressions -- Combination of transform expressions.
** *************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sqlenv.h>
#include <sqlcodes.h>
#include <sqlutil.h>
#include "utilemb.h"

EXEC SQL BEGIN DECLARE SECTION;
  char stmt[1684];
  SQL TYPE IS XML AS BLOB( 10K ) xmlblob;
EXEC SQL END DECLARE SECTION;

int main(int argc, char *argv[])
{
  int rc = 0;
  char dbAlias[SQL_ALIAS_SZ + 1];
  char user[USERID_SZ + 1];
  char pswd[PSWD_SZ + 1];
  /* check the command line arguments */
  rc = CmdLineArgsCheck1(argc, argv, dbAlias, user, pswd);
  if (rc != 0)
  {
    return rc;
  }
   /* connect to database */
  rc = DbConn(dbAlias, user, pswd);
  if (rc != 0)
  {
    return rc;
  }

  rc=insertExpr();
  rc=deleteExpr();
  rc=renameExpr();
  rc=replaceExpr();
  rc=combinationExprr();

  return 0;
} /* main */

int insertExpr()
{
   int rc = 0;
  struct sqlca sqlca;
  printf("\n*******************************************************************************");
  printf("\n Insert Expression -- Insert a new element to the existing XML document/fragment.");
  printf("\n*******************************************************************************");
  sprintf(stmt,"SELECT  xmlquery('transform copy $po := $order modify do insert document { <item> <partid>100-103-01</partid> <name>Snow Shovel, Super Deluxe 26 inch</name> <quantity>2</quantity> <price>49.99</price> </item> } as last into $po return  $po' passing purchaseorder.porder as \"order\") from purchaseorder where poid=5004");

  printf("\n\n Query: \n %s", stmt);
  EXEC SQL PREPARE s1 FROM :stmt;
  EMB_SQL_CHECK("prepare -- statement");

  EXEC SQL DECLARE c1 CURSOR FOR s1;
  EMB_SQL_CHECK("declare -- cusrsor");

  EXEC SQL OPEN c1;
  EMB_SQL_CHECK("cursor -- open");

  EXEC SQL FETCH c1 INTO :xmlblob;
  EMB_SQL_CHECK("cursor -- fetch");

  printf("\n\n Data after insert:");
  /* Print the result */
  while( sqlca.sqlcode == SQL_RC_OK )
  {
    xmlblob.data[xmlblob.length]='\0';
    printf("\n%s",xmlblob.data);
    EXEC SQL FETCH c1 INTO :xmlblob;
    EMB_SQL_CHECK("cursor -- fetch");
  }
  EXEC SQL CLOSE c1;
  EXEC SQL COMMIT;
  EMB_SQL_CHECK("cursor -- close");
  return 0;

}

int deleteExpr()
{
   int rc = 0;
  struct sqlca sqlca;
  printf("\n\n*******************************************************************************");
  printf("\n Delete Expression  -- Delete some elements from the exisitng XML document/fragment.");
  printf("\n*******************************************************************************");
  sprintf( stmt,"UPDATE purchaseorder SET porder = xmlquery('transform copy $po := $order modify do delete $po/PurchaseOrder/item[partid = ''100-201-01''] return  $po' passing porder as \"order\") WHERE poid=5004");

  printf("\n\n Query: \n%s",stmt);
  EXEC SQL EXECUTE IMMEDIATE :stmt;
  EMB_SQL_CHECK("Update -- statement");

  sprintf( stmt, "SELECT porder FROM purchaseorder WHERE poid=5004");
  EXEC SQL PREPARE s2 FROM :stmt;
  EXEC SQL DECLARE c11 CURSOR FOR s2;
  EMB_SQL_CHECK("declare -- cusrsor");

  EXEC SQL OPEN c11;
  EMB_SQL_CHECK("cursor -- open");

  EXEC SQL FETCH c11 INTO :xmlblob;
  EMB_SQL_CHECK("cursor -- fetch");

  printf("\n\n Data after delete: ");
  /* Print the result */
  while( sqlca.sqlcode == SQL_RC_OK )
  {
    xmlblob.data[xmlblob.length]='\0';
    printf("\n%s",xmlblob.data);
    EXEC SQL FETCH c11 INTO :xmlblob;
    EMB_SQL_CHECK("cursor -- fetch");
  }
  EXEC SQL CLOSE c11;
  EXEC SQL COMMIT;
  EMB_SQL_CHECK("cursor -- close");
  return 0;

}  //deleteExpr

int replaceExpr()
{
  int rc = 0;
  struct sqlca sqlca;
  printf("\n\n*******************************************************************************");
  printf("\n Replace value of Expression --  Replace the value of an element");
  printf("\n*******************************************************************************");

  sprintf( stmt,"UPDATE purchaseorder SET porder = xmlquery('transform copy  $po := $order modify for $i in $po/PurchaseOrder[@OrderDate = \"2006-02-18\"]//price return do replace value of $i  with $i*0.8 return  $po' passing porder as \"order\")");

  printf("\n\n Query: \n%s",stmt);
  EXEC SQL EXECUTE IMMEDIATE :stmt;
  EMB_SQL_CHECK("Update -- statement");

  sprintf( stmt, "SELECT porder FROM purchaseorder ORDER BY poid");
  
  EXEC SQL PREPARE s3 FROM :stmt;
  EXEC SQL DECLARE c111 CURSOR FOR s3;
  EMB_SQL_CHECK("declare -- cusrsor");

  EXEC SQL OPEN c111;
  EMB_SQL_CHECK("cursor -- open");

  EXEC SQL FETCH c111 INTO :xmlblob;
  EMB_SQL_CHECK("cursor -- fetch");

  /* Print the result */
  printf("\n\n Data after replace value of an element:"); 
  while( sqlca.sqlcode == SQL_RC_OK )
  {
    xmlblob.data[xmlblob.length]='\0';
    printf("\n%s",xmlblob.data);
    EXEC SQL FETCH c111 INTO :xmlblob;
    EMB_SQL_CHECK("cursor -- fetch");
  }
  EXEC SQL CLOSE c111;
  EXEC SQL COMMIT;
  EMB_SQL_CHECK("cursor -- close");

  
  
  printf("\n\n*******************************************************************************");
  printf("\n Replace value of Expression -- Replace the value of attribute");
  printf("\n*******************************************************************************");
  sprintf( stmt,"UPDATE purchaseorder SET porder = xmlquery('transform copy $po := $order modify do replace value of $po/PurchaseOrder/@Status with \"Shipped\" return $po' passing porder as \"order\") WHERE poid = 5002");

  printf("\n\n Query: \n%s",stmt);
  EXEC SQL EXECUTE IMMEDIATE :stmt;
  EMB_SQL_CHECK("Update -- statement");

  sprintf( stmt, "SELECT porder FROM purchaseorder WHERE poid = 5002");
  EXEC SQL PREPARE s4 FROM :stmt; 
  EXEC SQL DECLARE c2 CURSOR FOR s4;
  EMB_SQL_CHECK("declare -- cusrsor");

  EXEC SQL OPEN c2;
  EMB_SQL_CHECK("cursor -- open");

  EXEC SQL FETCH c2 INTO :xmlblob;
  EMB_SQL_CHECK("cursor -- fetch");

  /* Print the result */ 
  printf("\n\n Data after replace value of an attribute:");
  while( sqlca.sqlcode == SQL_RC_OK )
  {
    xmlblob.data[xmlblob.length]='\0';
    printf("\n%s",xmlblob.data);
    EXEC SQL FETCH c2 INTO :xmlblob;
    EMB_SQL_CHECK("cursor -- fetch");
  }
  EXEC SQL CLOSE c2;
  EXEC SQL COMMIT;
  EMB_SQL_CHECK("cursor -- close");


  printf("\n\n*******************************************************************************");
  printf("\n Replace Expression -- Replace an element and attribute."); 
  printf("\n*******************************************************************************");
  
  sprintf( stmt,"XQUERY for $k in db2-fn:sqlquery(\"select porder from purchaseorder where poid = 5004\") return transform copy $i := $k modify (do replace $i//PurchaseOrder/@OrderDate with ( attribute BilledDate {\"12-12-2007\"}), do replace $i//item[1]/price with $k//item[1]/price) return $i//PurchaseOrder");

  printf("\n\n Query: \n%s",stmt);
  EXEC SQL PREPARE s5 FROM :stmt;
  EMB_SQL_CHECK("prepare -- statement");

  EXEC SQL DECLARE c3 CURSOR FOR s5;
  EMB_SQL_CHECK("declare -- cusrsor");

  EXEC SQL OPEN c3;
  EMB_SQL_CHECK("cursor -- open");

  EXEC SQL FETCH c3 INTO :xmlblob;
  EMB_SQL_CHECK("cursor -- fetch");

  /* Print the result */
  printf("\n\n Data after replacing an element and attribute:");
  while( sqlca.sqlcode == SQL_RC_OK )
  {
    xmlblob.data[xmlblob.length]='\0';
    printf("\n%s",xmlblob.data);
    EXEC SQL FETCH c3 INTO :xmlblob;
    EMB_SQL_CHECK("cursor -- fetch");
  }
  EXEC SQL CLOSE c3;
  EXEC SQL COMMIT;
  EMB_SQL_CHECK("cursor -- close");

  return 0;

}  //replaceExpr


int renameExpr()
{
  int rc = 0;
  struct sqlca sqlca;
  printf("\n\n*******************************************************************************");
  printf("\n Rename Expression  --  Rename an element in the existing XML document/fragment.");
  printf("\n*******************************************************************************");

  sprintf( stmt,"UPDATE purchaseorder SET porder = xmlquery('transform copy $po := $order modify for $i in $po//item[quantity > 1] return do rename $i as \"items\" return  $po' passing porder as \"order\") WHERE poid=5002");

  printf("\n\n Query: \n%s",stmt);
  EXEC SQL EXECUTE IMMEDIATE :stmt;
  EMB_SQL_CHECK("Update -- statement");

  sprintf( stmt, "SELECT porder FROM purchaseorder WHERE poid=5002");
  EXEC SQL PREPARE s6 FROM :stmt;   
  EXEC SQL DECLARE c5 CURSOR FOR s6;
  EMB_SQL_CHECK("declare -- cusrsor");

  EXEC SQL OPEN c5;
  EMB_SQL_CHECK("cursor -- open");

  EXEC SQL FETCH c5 INTO :xmlblob;
  EMB_SQL_CHECK("cursor -- fetch");

  /* Print the result */
  printf("\n\n Data after renaming an element:");
  while( sqlca.sqlcode == SQL_RC_OK )
  {
    xmlblob.data[xmlblob.length]='\0';
    printf("\n%s",xmlblob.data);
    EXEC SQL FETCH c5 INTO :xmlblob;
    EMB_SQL_CHECK("cursor -- fetch");
  }
  EXEC SQL CLOSE c5;
  EXEC SQL COMMIT;
  EMB_SQL_CHECK("cursor -- close");

  printf("\n\n*******************************************************************************");
  printf("\n Rename Expression  -- Rename an attribute in the existing XML document/fragment.");
  printf("\n*******************************************************************************");

  sprintf(stmt, "XQUERY for $k in db2-fn:sqlquery(\"select porder from purchaseorder where poid=5003\") return transform copy $i := $k modify (do rename $i//*:PurchaseOrder/@OrderDate as \"BilledDate\", do insert attribute Totalcost {\"405.99\"} into $i//*:PurchaseOrder, do rename $i//*:PurchaseOrder//*:partid as \"productid\") return $i//*:PurchaseOrder");

  printf("\n\n Query: \n%s",stmt);
  EXEC SQL PREPARE s7 FROM :stmt;
  EMB_SQL_CHECK("prepare -- statement");

  EXEC SQL DECLARE c21 CURSOR FOR s7;
  EMB_SQL_CHECK("declare -- cusrsor");

  EXEC SQL OPEN c21;
  EMB_SQL_CHECK("cursor -- open");

  EXEC SQL FETCH c21 INTO :xmlblob;
  EMB_SQL_CHECK("cursor -- fetch");

  /* Print the result */
  printf("\n\n Data after renaming an attribute and an element:");
  while( sqlca.sqlcode == SQL_RC_OK )
  {
    xmlblob.data[xmlblob.length]='\0';
    printf("\n%s",xmlblob.data);
    EXEC SQL FETCH c21 INTO :xmlblob;
    EMB_SQL_CHECK("cursor -- fetch");
  }
  EXEC SQL CLOSE c21;
  EXEC SQL COMMIT;
  EMB_SQL_CHECK("cursor -- close");

  return 0;

}  //renameExpr


int combinationExprr()
{
  int rc = 0;
  struct sqlca sqlca;
  printf("\n\n*******************************************************************************");
  printf("\n Insert and Replace Expressions -- Combination of transform expressions.");
  printf("\n*******************************************************************************");

  sprintf( stmt,"UPDATE purchaseorder SET porder = xmlquery ('transform copy   $po := $order modify ( for $i in $po/PurchaseOrder[@OrderDate = ''2006-02-18'']//price return do replace value of $i with $i*0.8, do  insert document { <item> <partid>100-103-01</partid> <name>Snow Shovel, Super Deluxe 26 inch</name> <quantity>2</quantity> <price>49.99</price> </item> } as last into $po/PurchaseOrder) return  $po' passing porder as \"order\") WHERE poid = 5004 ");

  printf("\n\n Query: \n%s",stmt);
  EXEC SQL EXECUTE IMMEDIATE :stmt;
  EMB_SQL_CHECK("Update -- statement");

  sprintf( stmt, "SELECT porder FROM purchaseorder WHERE poid=5004");
  EXEC SQL PREPARE s8 FROM :stmt; 
  EXEC SQL DECLARE c4 CURSOR FOR s8;
  EMB_SQL_CHECK("declare -- cusrsor");

  EXEC SQL OPEN c4;
  EMB_SQL_CHECK("cursor -- open");

  EXEC SQL FETCH c4 INTO :xmlblob;
  EMB_SQL_CHECK("cursor -- fetch");

  /* Print the result */
  printf("\n\n Data after insert and replace:");
  while( sqlca.sqlcode == SQL_RC_OK )
  {
    xmlblob.data[xmlblob.length]='\0';
    printf("\n%s",xmlblob.data);
    EXEC SQL FETCH c4 INTO :xmlblob;
    EMB_SQL_CHECK("cursor -- fetch");
  }
  EXEC SQL CLOSE c4;
  EXEC SQL COMMIT;
  EMB_SQL_CHECK("cursor -- close");

  return 0;
}  //combinationExprr