PageRenderTime 955ms CodeModel.GetById 38ms RepoModel.GetById 0ms app.codeStats 0ms

/wheels/model/adapters/Oracle.cfc

http://cfwheels.googlecode.com/
ColdFusion CFScript | 238 lines | 220 code | 12 blank | 6 comment | 21 complexity | eae4a8e28e17b09c4a68ad198d92965a MD5 | raw file
Possible License(s): Apache-2.0, CPL-1.0
  1. <cfcomponent extends="Base" output="false">
  2. <cffunction name="$generatedKey" returntype="string" access="public" output="false">
  3. <cfreturn "rowid">
  4. </cffunction>
  5. <cffunction name="$randomOrder" returntype="string" access="public" output="false">
  6. <cfreturn "dbms_random.value()">
  7. </cffunction>
  8. <cffunction name="$getType" returntype="string" access="public" output="false">
  9. <cfargument name="type" type="string" required="true">
  10. <cfargument name="scale" type="string" required="true">
  11. <cfscript>
  12. var loc = {};
  13. switch(arguments.type)
  14. {
  15. case "blob": case "bfile": {loc.returnValue = "cf_sql_blob"; break;}
  16. case "char": case "nchar": {loc.returnValue = "cf_sql_char"; break;}
  17. case "clob": case "nclob": {loc.returnValue = "cf_sql_clob"; break;}
  18. case "date": case "timestamp": {loc.returnValue = "cf_sql_timestamp"; break;}
  19. case "binary_double": {loc.returnValue = "cf_sql_double"; break;}
  20. case "number": case "float": case "binary_float":
  21. {
  22. // integer datatypes are represented by number(38,0)
  23. if (val(arguments.scale) == 0)
  24. {
  25. loc.returnValue = "cf_sql_integer";
  26. }
  27. else
  28. {
  29. loc.returnValue = "cf_sql_float";
  30. }
  31. break;
  32. }
  33. case "long": {loc.returnValue = "cf_sql_longvarchar"; break;}
  34. case "raw": {loc.returnValue = "cf_sql_varbinary"; break;}
  35. case "varchar2": case "nvarchar2": {loc.returnValue = "cf_sql_varchar"; break;}
  36. }
  37. </cfscript>
  38. <cfreturn loc.returnValue>
  39. </cffunction>
  40. <cffunction name="$query" returntype="struct" access="public" output="false">
  41. <cfargument name="sql" type="array" required="true">
  42. <cfargument name="limit" type="numeric" required="false" default=0>
  43. <cfargument name="offset" type="numeric" required="false" default=0>
  44. <cfargument name="parameterize" type="boolean" required="true">
  45. <cfargument name="$primaryKey" type="string" required="false" default="">
  46. <cfscript>
  47. var loc = {};
  48. arguments.sql = $removeColumnAliasesInOrderClause(arguments.sql);
  49. arguments.sql = $addColumnsToSelectAndGroupBy(arguments.sql);
  50. if (arguments.limit > 0)
  51. {
  52. loc.beforeWhere = "SELECT #arguments.$primaryKey# FROM (SELECT tmp.#arguments.$primaryKey#, rownum rnum FROM (";
  53. loc.afterWhere = ") tmp WHERE rownum <=" & arguments.limit+arguments.offset & ")" & " WHERE rnum >" & arguments.offset;
  54. ArrayPrepend(arguments.sql, loc.beforeWhere);
  55. ArrayAppend(arguments.sql, loc.afterWhere);
  56. }
  57. // oracle doesn't support limit and offset in sql
  58. StructDelete(arguments, "limit", false);
  59. StructDelete(arguments, "offset", false);
  60. loc.returnValue = $performQuery(argumentCollection=arguments);
  61. loc.returnValue = $handleTimestampObject(loc.returnValue);
  62. </cfscript>
  63. <cfreturn loc.returnValue>
  64. </cffunction>
  65. <cffunction name="$identitySelect" returntype="any" access="public" output="false">
  66. <cfargument name="queryAttributes" type="struct" required="true">
  67. <cfargument name="result" type="struct" required="true">
  68. <cfargument name="primaryKey" type="string" required="true">
  69. <cfset var loc = {}>
  70. <cfset var query = {}>
  71. <cfset loc.sql = Trim(arguments.result.sql)>
  72. <cfif Left(loc.sql, 11) IS "INSERT INTO">
  73. <cfset loc.startPar = Find("(", loc.sql) + 1>
  74. <cfset loc.endPar = Find(")", loc.sql)>
  75. <cfset loc.columnList = ReplaceList(Mid(loc.sql, loc.startPar, (loc.endPar-loc.startPar)), "#Chr(10)#,#Chr(13)#, ", ",,")>
  76. <cfif NOT ListFindNoCase(loc.columnList, ListFirst(arguments.primaryKey))>
  77. <cfset loc.returnValue = {}>
  78. <cfset loc.tbl = SpanExcluding(Right(loc.sql, Len(loc.sql)-12), " ")>
  79. <cfif !StructKeyExists(arguments.result, $generatedKey()) || application.wheels.serverName IS NOT "Adobe ColdFusion">
  80. <!---
  81. there isn't a way in oracle to tell what (if any) sequences exists
  82. on a table. hence we'll just have to perform a guess for now.
  83. TODO: in 1.2 we need to look at letting the developer specify the sequence
  84. name through a setting in the model
  85. --->
  86. <cftry>
  87. <cfquery attributeCollection="#arguments.queryAttributes#">SELECT #loc.tbl#_seq.currval AS lastId FROM dual</cfquery>
  88. <cfcatch type="any">
  89. <!--- in case the sequence doesn't exists return a blank string for the expected value --->
  90. <cfset query.name.lastId = "">
  91. </cfcatch>
  92. </cftry>
  93. <cfelse>
  94. <cfquery attributeCollection="#arguments.queryAttributes#">SELECT #arguments.primaryKey# AS lastId FROM #loc.tbl# WHERE ROWID = '#arguments.result[$generatedKey()]#'</cfquery>
  95. </cfif>
  96. <cfset loc.lastId = Trim(query.name.lastId)>
  97. <cfif len(query.name.lastId)>
  98. <cfset loc.returnValue[$generatedKey()] = Trim(loc.lastid)>
  99. <cfreturn loc.returnValue>
  100. </cfif>
  101. <cfelse>
  102. <!--- since Oracle always returns rowid we need to delete it in those cases where we have manually inserted the primary key, if we don't do this we'll end up setting the rowid value to the object --->
  103. <cfif StructKeyExists(arguments.result, "rowid")>
  104. <cfset StructDelete(arguments.result, "rowid")>
  105. </cfif>
  106. <cfif StructKeyExists(arguments.result, "generatedkey")>
  107. <cfset StructDelete(arguments.result, "generatedkey")>
  108. </cfif>
  109. </cfif>
  110. </cfif>
  111. </cffunction>
  112. <cffunction name="$getColumnInfo" returntype="query" access="public" output="false">
  113. <cfargument name="table" type="string" required="true">
  114. <cfargument name="datasource" type="string" required="true">
  115. <cfargument name="username" type="string" required="true">
  116. <cfargument name="password" type="string" required="true">
  117. <cfscript>
  118. var loc = {};
  119. loc.args = duplicate(arguments);
  120. StructDelete(loc.args, "table");
  121. if (!Len(loc.args.username))
  122. {
  123. StructDelete(loc.args, "username");
  124. }
  125. if (!Len(loc.args.password))
  126. {
  127. StructDelete(loc.args, "password");
  128. }
  129. loc.args.name = "loc.returnValue";
  130. </cfscript>
  131. <cfquery attributeCollection="#loc.args#">
  132. SELECT
  133. TC.COLUMN_NAME
  134. ,TC.DATA_TYPE AS TYPE_NAME
  135. ,TC.NULLABLE AS IS_NULLABLE
  136. ,CASE WHEN PKC.COLUMN_NAME IS NULL THEN 0 ELSE 1 END AS IS_PRIMARYKEY
  137. ,0 AS IS_FOREIGNKEY
  138. ,'' AS REFERENCED_PRIMARYKEY
  139. ,'' AS REFERENCED_PRIMARYKEY_TABLE
  140. ,NVL(TC.DATA_PRECISION, TC.DATA_LENGTH) AS COLUMN_SIZE
  141. ,TC.DATA_SCALE AS DECIMAL_DIGITS
  142. ,TC.DATA_DEFAULT AS COLUMN_DEFAULT_VALUE
  143. ,TC.DATA_LENGTH AS CHAR_OCTET_LENGTH
  144. ,TC.COLUMN_ID AS ORDINAL_POSITION
  145. ,'' AS REMARKS
  146. FROM
  147. ALL_TAB_COLUMNS TC
  148. LEFT JOIN ALL_CONSTRAINTS PK
  149. ON (PK.CONSTRAINT_TYPE = 'P'
  150. AND PK.TABLE_NAME = TC.TABLE_NAME
  151. AND TC.OWNER = PK.OWNER)
  152. LEFT JOIN ALL_CONS_COLUMNS PKC
  153. ON (PK.CONSTRAINT_NAME = PKC.CONSTRAINT_NAME
  154. AND TC.COLUMN_NAME = PKC.COLUMN_NAME
  155. AND TC.OWNER = PKC.OWNER)
  156. WHERE
  157. TC.TABLE_NAME = '#UCase(arguments.table)#'
  158. ORDER BY
  159. TC.COLUMN_ID
  160. </cfquery>
  161. <!---
  162. wheels catches the error and raises a Wheels.TableNotFound error
  163. to mimic this we will throw an error if the query result is empty
  164. --->
  165. <cfif !loc.returnValue.RecordCount>
  166. <cfthrow/>
  167. </cfif>
  168. <cfreturn loc.returnValue>
  169. </cffunction>
  170. <cffunction name="$handleTimestampObject" hint="Oracle will return timestamp as an object. you need to call timestampValue() to get the string representation">
  171. <cfargument name="results" type="struct" required="true">
  172. <cfscript>
  173. var loc = {};
  174. // depending on the driver and engine used with oracle, timestamps can be returned as
  175. // objects instead of strings.
  176. if (StructKeyExists(arguments.results, "query"))
  177. {
  178. // look for all timestamp columns
  179. loc.query = arguments.results.query;
  180. loc.rows = loc.query.RecordCount;
  181. if (loc.rows gt 0)
  182. {
  183. loc.metadata = GetMetaData(loc.query);
  184. loc.columns = [];
  185. loc.iEnd = ArrayLen(loc.metadata);
  186. for (loc.i = 1; loc.i lte loc.iEnd; loc.i++)
  187. {
  188. loc.column = loc.metadata[loc.i];
  189. if (loc.column.typename eq "timestamp")
  190. {
  191. ArrayAppend(loc.columns, loc.column.name);
  192. }
  193. }
  194. // if we have any timestamp columns
  195. if (!ArrayIsEmpty(loc.columns))
  196. {
  197. loc.iEnd = ArrayLen(loc.columns);
  198. for (loc.i = 1; loc.i lte loc.iEnd; loc.i++)
  199. {
  200. loc.column = loc.columns[loc.i];
  201. for (loc.row = 1; loc.row lte loc.rows; loc.row++)
  202. {
  203. if (IsObject(loc.query[loc.column][loc.row]))
  204. {// call timestampValue() on objects to convert to string
  205. loc.query[loc.column][loc.row] = loc.query[loc.column][loc.row].timestampValue();
  206. }
  207. else if (IsSimpleValue(loc.query[loc.column][loc.row]) && Len(loc.query[loc.column][loc.row]))
  208. {// if the driver does the conversion automatically, there is no need to continue
  209. break;
  210. }
  211. }
  212. }
  213. }
  214. arguments.results.query = loc.query;
  215. }
  216. }
  217. return arguments.results;
  218. </cfscript>
  219. </cffunction>
  220. <cffunction name="$tableAliasForJoin" returntype="string" access="public" output="false">
  221. <cfargument name="table" type="string" required="true">
  222. <cfargument name="alias" type="string" required="true">
  223. <cfreturn "#arguments.table# #arguments.alias#">
  224. </cffunction>
  225. <cfinclude template="../../plugins/injection.cfm">
  226. </cfcomponent>