001: package simpleorm.core;
002:
003: /** This contains MS SQL Server specific code.
004: *
005: * CHAR, VARCHAR max 8,000. TEXT 2^31. NVARCHAR/NCHAR UTF16, max size 4,000.
006: */
007:
008: public class SDriverMSSQL extends SDriver {
009:
010: protected String driverName() {
011: return "SQLServer";
012: }
013:
014: /* paging
015: selectSQL(...) {
016: * 0 = SQL string
017: * 1 = Page int -> LastUnwantedRecord
018: * 2 = RecsPerPage int
019: * 3 = unique column
020: * 4 = Sort
021: Select TOP @RecsPerPage * FROM (@SQL) T WHERE T.@ID NOT IN
022: (select TOP ((@RecsPerPage*(@Page-1)) @ID FROM (@SQL) T9 ORDER BY @Sort) order by @Sort
023:
024: Params : String pageid, int pageindex, int recsperpage )
025: * /
026: // for now we can only page if there is only one primary key
027: SFieldMeta sfmKey = null;
028: int iPKeyCount = 0;
029: for (int i = 0; i < from.keySFieldMetas.size(); i++)
030: {
031: sfmKey = (SFieldMeta)from.keySFieldMetas.get(i);
032: if (sfmKey.sFieldReference == null)
033: iPKeyCount++;
034: }
035: if (iPKeyCount != 1)
036: throw new SException.Error("Cannot page a query that has multiple primary keys (for now) " + this);
037:
038: String strSQL = "SELECT TOP {2,number,integer} * FROM ({0}) T WHERE T.{3} NOT IN "
039: + "(select TOP {1,number,integer} {3} FROM ({0}) T9 {4}) {4}";
040: Object[] args = {
041: ret.ToString(),
042: sps.getOffset();
043: sps.getLimit();
044:
045: new Long(recsperpage * (pageindex - 1)),
046: new Long(recsperpage),
047: sfmKey.getString(sfmKey.SCOLUMN_NAME),
048: " ORDER BY " + (orderBy != null ? orderBy : sfmKey.getString(sfmKey.SCOLUMN_NAME))
049: };
050: return java.text.MessageFormat.format(strSQL,args);
051: / * paging */
052:
053: /** Apparantly need DATETIME instead of TIMESTAMP */
054: protected String columnTypeSQL(SFieldMeta field) {
055:
056: if (((String) field.getProperty(SDATA_TYPE))
057: .equals("TIMESTAMP"))
058: return "DATETIME";
059: else if (((String) field.getProperty(SDATA_TYPE))
060: .equals("DATE"))
061: return "DATETIME";
062: else if (((String) field.getProperty(SDATA_TYPE))
063: .equals("TIME"))
064: return "DATETIME";
065: else if (((String) field.getProperty(SDATA_TYPE))
066: .equals("NUMERIC(18,0)"))
067: return "BIGINT";
068: else if (((String) field.getProperty(SDATA_TYPE))
069: .equals("BYTES"))
070: return "IMAGE"; // Ie. just a byte array.
071: else
072: return super .columnTypeSQL(field);
073:
074: }
075:
076: protected String forUpdateSQL(boolean forUpdate) {
077: return "";
078: }
079:
080: /** XLOCK is not strictly necessary in MS SQL because it does not
081: provide Oracle-like data versioning.<p>
082:
083: But having XLOCK should reduce deadlocks. More importantly,
084: 2005 is supposed to be providing data versioning
085: ("Snapshots").<p>
086:
087: However, Jorge says that it is unnecessary and makes SimpleORM
088: fail, but it works for me.
089:
090: @see SDriver#forUpdateSQL for discussion.
091:
092: */
093: protected String postFromSQL(boolean forUpdate,
094: boolean unrepeatableRead) {
095: if (unrepeatableRead)
096: return " WITH (NOLOCK)";
097: else if (forUpdate && xLockEnabled)
098: return " WITH (XLOCK)";
099: return "";
100: }
101:
102: boolean xLockEnabled = false;
103:
104: /** Enables WITH (XLOCK) for updatable queries.
105: * Should reduce deadlocks but apparantly can cause bugs.
106: * (Not supported in SQL 7? Something about HOLDLOCK?)
107: */
108: public void setXLockEnabled(boolean xlock) {
109: xLockEnabled = xlock;
110: }
111:
112: public boolean getXLockEnabled() {
113: return xLockEnabled;
114: }
115:
116: public String alterTableAddColumnSQL(SFieldMeta field) {
117: StringBuffer sql = new StringBuffer();
118:
119: sql.append("\nALTER TABLE ");
120: sql.append(field.sRecordMeta.getString(STABLE_NAME));
121: sql.append(" ADD ");
122: sql.append(wholeColumnSQL(field));
123: sql.append(clauseSeparator(" "));
124:
125: return sql.toString();
126: }
127:
128: // ### We need a key generator here!
129: }
|