This file is indexed.

/usr/share/pyshared/pymssql.py is in python-pymssql 1.0.2+dfsg-1build1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
"""DB-SIG compliant module for communicating with MS SQL servers"""
#***************************************************************************
#                          pymssql.py  -  description
#
#    begin                : 2003-03-03
#    copyright            : (C) 2003-03-03 by Joon-cheol Park
#    email                : jooncheol@gmail.com
#    current developer    : Andrzej Kukula <akukula@gmail.com>
#    homepage             : http://pymssql.sourceforge.net
#
#***************************************************************************
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
# MA  02110-1301  USA
#***************************************************************************

__author__ = "Joon-cheol Park <jooncheol@gmail.com>, Andrzej Kukula <akukula@gmail.com>"
__version__ = '1.0.2'
import _mssql, types, string, time, datetime, warnings

### module constants

# compliant with DB SIG 2.0
apilevel = '2.0'

# module may be shared, but not connections
threadsafety = 1

# this module use extended python format codes
paramstyle = 'pyformat'

#export column type names from _mssql

class DBAPITypeObject:
	def __init__(self,*values):
		self.values = values
	def __cmp__(self,other):
		if other in self.values:
			return 0
		if other < self.values:
			return 1
		else:
			return -1

STRING = DBAPITypeObject(_mssql.STRING)
BINARY = DBAPITypeObject(_mssql.BINARY)
NUMBER = DBAPITypeObject(_mssql.NUMBER)
DATETIME = DBAPITypeObject(_mssql.DATETIME)
DECIMAL = DBAPITypeObject(_mssql.DECIMAL)

### exception hierarchy

class Warning(StandardError):
	pass

class Error(StandardError):
	pass

class InterfaceError(Error):
	pass

class DatabaseError(Error):
	pass

class DataError(DatabaseError):
	pass

class OperationalError(DatabaseError):
	pass

class IntegrityError(DatabaseError):
	pass

class InternalError(DatabaseError):
	pass

class ProgrammingError(DatabaseError):
	pass

class NotSupportedError(DatabaseError):
	pass


### cursor object

class pymssqlCursor(object):
	"""
	This class represent a database cursor, which is used to issue queries
	and fetch results from a database connection.
	"""

	def __init__(self, src, as_dict):
		"""
		Initialize a Cursor object. 'src' is a pymssqlCnx object instance.
		"""
		self.__source = src
		self.description = None
		self._batchsize = 1
		self._rownumber = 0
		self.as_dict = as_dict

	@property
	def _source(self):
		"""
		INTERNAL PROPERTY. Returns the pymssqlCnx object, and raise
		exception if it's set to None. It's easier than adding necessary
		checks to every other method.
		"""
		if self.__source == None:
			raise InterfaceError, "Cursor is closed."
		return self.__source

	@property
	def rowcount(self):
		"""
		Returns number of rows affected by last operation. In case
		of SELECTs it returns meaningful information only after
		all rows has been fetched.
		"""
		return self._source.rows_affected

	@property
	def connection(self):
		"""
		Returns a reference to the connection object on which the cursor
		was created. This is the extension of the DB-API specification.
		"""
		#warnings.warn("DB-API extension cursor.connection used", SyntaxWarning, 2)
		return self._source

	@property
	def lastrowid(self):
		"""
		Returns identity value of last inserted row. If previous operation
		did not involve inserting a row into a table with identity column,
		None is returned. This is the extension of the DB-API specification.
		"""
		#warnings.warn("DB-API extension cursor.lastrowid used", SyntaxWarning, 2)
		return self._source.identity

	@property
	def rownumber(self):
		"""
		Returns current 0-based index of the cursor in the result set.
		This is the extension of the DB-API specification.
		"""
		#warnings.warn("DB-API extension cursor.rownumber used", SyntaxWarning, 2)
		return self._rownumber

	def close(self):
		"""
		Closes the cursor. The cursor is unusable from this point.
		"""
		self.__source = None
		self.description = None

	def execute(self, operation, *args):
		"""
		Prepare and execute a database operation (query or command).
		Parameters may be provided as sequence or mapping and will be
		bound to variables in the operation. Parameter style for pymssql
		is %-formatting, as in:
		cur.execute('select * from table where id=%d', id)
		cur.execute('select * from table where strname=%s', name)
		Please consult online documentation for more examples and
		guidelines.
		"""
		self.description = None
		self._rownumber = 0  # don't raise warning

		# for this method default value for params cannot be None,
		# because None is a valid value for format string.

		if (args != () and len(args) != 1):
			raise TypeError, "execute takes 1 or 2 arguments (%d given)" % (len(args) + 1,)

		try:
			if args == ():
				self._source.execute_query(operation)
			else:
				self._source.execute_query(operation, args[0])

			self.description = self._source.get_header()
		except _mssql.MssqlDatabaseException, e:
			raise OperationalError, e[0]
		except _mssql.MssqlDriverException, e:
			raise InterfaceError, e[0]

	def executemany(self, operation, param_seq):
		"""
		Execute a database operation repeatedly for each element in the
		parameter sequence. Example:
		cur.executemany("INSERT INTO table VALUES(%s)", [ 'aaa', 'bbb' ])
		"""
		self.description = None

		for params in param_seq:
			self.execute(operation, params)

	def nextset(self):
		"""
		This method makes the cursor skip to the next available result set,
		discarding any remaining rows from the current set. Returns true
		value if next result is available, or None if not.
		"""
		try:
			if self._source.nextresult():
				self._rownumber = 0
				self.description = self._source.get_header()
				return 1
		except _mssql.MssqlDatabaseException, e:
			raise OperationalError, e[0]
		except _mssql.MssqlDriverException, e:
			raise InterfaceError, e[0]

		return None

	def fetchone(self):
		"""
		Fetch the next row of a query result, returning a tuple,
		or None when no more data is available. Raises OperationalError
		if previous call to execute*() did not produce any result set
		or no call was issued yet.
		"""
		if self._source.get_header() == None:
			raise OperationalError, "No data available."

		try:
			if self.as_dict:
				row = iter(self._source).next()
				self._rownumber += 1
				return row
			else:
				row = iter(self._source).next()
				self._rownumber += 1
				return tuple([row[r] for r in sorted(row.keys()) if type(r) == int])

		except StopIteration:
			return None
		except _mssql.MssqlDatabaseException, e:
			raise OperationalError, e[0]
		except _mssql.MssqlDriverException, e:
			raise InterfaceError, e[0]

	def fetchmany(self, size=None):
		"""
		Fetch the next batch of rows of a query result, returning them
		as a list of tuples. An empty list is returned if no more rows
		are available. You can adjust the batch size using the 'size'
		parameter, which is preserved across many calls to this method.
		Raises OperationalError if previous call to execute*() did not
		produce any result set or no call was issued yet.
		"""
		if self._source.get_header() == None:
			raise OperationalError, "No data available."

		if size == None:
			size = self._batchsize

		self._batchsize = size

		try:
			list = []
			for i in xrange(size):
				try:
					row = iter(self._source).next()
					if self.as_dict:
						t = row  # pass through
					else:
						t = tuple([row[r] for r in sorted(row.keys()) if type(r) == int])
					self._rownumber += 1
					list.append(t)
				except StopIteration:
					break
			return list
		except _mssql.MssqlDatabaseException, e:
			raise OperationalError, e[0]
		except _mssql.MssqlDriverException, e:
			raise InterfaceError, e[0]

	def fetchall(self):
		"""
		Fetch all remaining rows of a query result, returning them
		as a list of tuples. An empty list is returned if no more rows
		are available. Raises OperationalError if previous call to
		execute*() did not produce any result set or no call was
		issued yet.
		"""
		if self._source.get_header() == None:
			raise OperationalError, "No data available."

		try:
			if self.as_dict:
				list = [ row for row in self._source ]
			else:
				list = [tuple([row[r] for r in sorted(row.keys()) if type(r) == int]) for row in self._source]
			self._rownumber += len(list)
			return list
		except _mssql.MssqlDatabaseException, e:
			raise OperationalError, e[0]
		except _mssql.MssqlDriverException, e:
			raise InterfaceError, e[0]

	def __iter__(self):
		"""
		Return self to make cursors compatible with
		Python iteration protocol.
		"""
		#warnings.warn("DB-API extension cursor.__iter__() used", SyntaxWarning, 2)
		return self

	def next(self):
		"""
		This method supports Python iterator protocol. It returns next
		row from the currently executing SQL statement. StopIteration
		exception is raised when the result set is exhausted.
		With this method you can iterate over cursors:
		    cur.execute('SELECT * FROM persons')
		    for row in cur:
		        print row[0]
		"""
		#warnings.warn("DB-API extension cursor.next() used", SyntaxWarning, 2)
		try:
			row = iter(self._source).next()
			self._rownumber += 1
			return tuple([row[r] for r in sorted(row.keys()) if type(r) == int])
		except _mssql.MssqlDatabaseException, e:
			raise OperationalError, e[0]
		except _mssql.MssqlDriverException, e:
			raise InterfaceError, e[0]

	def fetchone_asdict(self):
		"""
		Warning: this method is not part of Python DB-API.
		Fetch the next row of a query result, returning a dictionary,
		or None when no more data is available. Data can be accessed
		by 0-based numeric column index, or by column name.
		Raises OperationalError if previous call to execute*() did not
		produce any result set or no call was issued yet.
		"""
		if self._source.get_header() == None:
			raise OperationalError, "No data available."
		
		try:
			row = iter(self._source).next()
			self._rownumber += 1
			return row
		except StopIteration:
			return None
		except _mssql.MssqlDatabaseException, e:
			raise OperationalError, e[0]
		except _mssql.MssqlDriverException, e:
			raise InterfaceError, e[0]

	def fetchmany_asdict(self, size=None):
		"""
		Warning: this method is not part of Python DB-API.
		Fetch the next batch of rows of a query result, returning them
		as a list of dictionaries. An empty list is returned if no more
		rows are available. You can adjust the batch size using the
		'size' parameter, which is preserved across many calls to this
		method. Data can be accessed by 0-based numeric column index,
		or by column name.
		Raises OperationalError if previous call to execute*() did not
		produce any result set or no call was issued yet.
		"""
		if self._source.get_header() == None:
			raise OperationalError, "No data available."

		if size == None:
			size = self._batchsize

		self._batchsize = size

		try:
			list = []
			for i in xrange(size):
				try:
					row = iter(self._source).next()
					self._rownumber += 1
					list.append(row)
				except StopIteration:
					break
			return list
		except _mssql.MssqlDatabaseException, e:
			raise OperationalError, e[0]
		except _mssql.MssqlDriverException, e:
			raise InterfaceError, e[0]

	def fetchall_asdict(self):
		"""
		Warning: this method is not part of Python DB-API.
		Fetch all remaining rows of a query result, returning them
		as a list of dictionaries. An empty list is returned if
		no more rows are available. Data can be accessed by 0-based
		numeric column index, or by column name.
		Raises OperationalError if previous call to execute*() did not
		produce any result set or no call was issued yet.
		"""
		if self._source.get_header() == None:
			raise OperationalError, "No data available."

		try:
			return [ row for row in self._source ]
		except _mssql.MssqlDatabaseException, e:
			raise OperationalError, e[0]
		except _mssql.MssqlDriverException, e:
			raise InterfaceError, e[0]

	def setinputsizes(self, sizes=None):
		"""
		This method does nothing, as permitted by DB-API specification.
		"""
		pass

	def setoutputsize(self, size=None, column=0):
		"""
		This method does nothing, as permitted by DB-API specification.
		"""
		pass

### connection object

class pymssqlCnx:
	"""
	This class represent an MS SQL database connection.
	"""
	def __init__(self, cnx, as_dict):
		self.__cnx = cnx
		self._autocommit = False
		self.as_dict = as_dict
		try:
			self._cnx.execute_non_query("BEGIN TRAN")
		except Exception, e:
			raise OperationalError, "cannot start transaction." + e[0]

	@property
	def _cnx(self):
		"""
		INTERNAL PROPERTY. Returns the _mssql.MssqlConnection object,
		and raise exception if it's set to None. It's easier than adding
		necessary checks to every other method.
		"""

		if self.__cnx == None:
			raise InterfaceError, "Connection is closed."
		return self.__cnx

	def __del__(self):
		if self.__cnx:
			self.__cnx.close()
			self.__cnx = None

	def close(self):
		"""
		Close connection to the database.
		"""
		if self.__cnx:
			self.__cnx.close()
		self.__cnx = None

	def commit(self):
		"""
		Commit transaction which is currently in progress.
		"""

		if self._autocommit == True:
			return
		try:
			self._cnx.execute_non_query("COMMIT TRAN")
			self._cnx.execute_non_query("BEGIN TRAN")
		except Exception, e:
			raise OperationalError, "cannot commit transaction." + e[0]

	def rollback(self):
		"""
		Roll back transaction which is currently in progress.
		"""
		if self._autocommit == True:
			return
		try:
			self._cnx.execute_non_query("ROLLBACK TRAN")
			self._cnx.execute_non_query("BEGIN TRAN")
		except Exception, e:
			raise OperationalError, "cannot roll back transaction: " + e[0]

	def cursor(self):
		"""
		Return cursor object that can be used to make queries and fetch
		results from the database.
		"""
		return pymssqlCursor(self._cnx, self.as_dict)

	def autocommit(self,status):
		"""
		Turn autocommit ON or OFF.
		"""
		if status:
			if self._autocommit == False:
				self._cnx.execute_non_query("ROLLBACK TRAN")
				self._autocommit = True
		else:
			if self._autocommit == True:
				self._cnx.execute_non_query("BEGIN TRAN")
				self._autocommit = False


# connects to a database
def connect(dsn = None, user = "sa", password = "", host = ".", database = "", 
		    timeout = 0, login_timeout = 60, trusted = False, charset = None,
		    as_dict = False, max_conn = 25):
	"""
	Constructor for creating a connection to the database. Returns
	a connection object. Paremeters are as follows:

	dsn       colon-delimited string in form host:dbase:user:pass:opt:tty
	          primarily for compatibility with previous versions of pymssql.
	user      database user to connect as
	password  user's password
	trusted   whether to use Windows Integrated Authentication to connect 
	          instead of SQL autentication with user and password [Win]
	host      database host and instance, valid examples are:
	          r'.\SQLEXPRESS'       - named instance on local machine [Win]
	          r'(local)\SQLEXPRESS' - same as above [Win]
	          r'SQLHOST'            - default instance and port [Win]
	          r'SQLHOST'            - instance set up in freetds.conf [Lnx]
	          r'SQLHOST,1433'       - specified TCP port at a host [ALL]
	          r'SQLHOST:1433'       - same as above [ALL]
	          r'SQLHOST,5000'       - if you have set up an instance
	                                  to listen on port 5000 [ALL]
	          r'SQLHOST:5000'       - same as above [ALL]
	          '.' is assumed is host is not provided
	database  the database you want initially to connect to
	timeout   query timeout in seconds, default 0 (no timeout)
	login_timeout
	          timeout for connection and login in seconds, default 60
	charset
	          character set with which to connect to the database
	as_dict   whether rows should be returned as dictionaries instead of tuples
	max_conn  how many simultaneous connections to allow; default is 25
	
	Examples:
	con = pymssql.connect(host=r'DBHOST,1433', user='username',
                              password='P@ssw0rd', database='MYDB')
	con = pymssql.connect(host=r'DBHOST\INSTANCE',trusted=True)
	"""
	# first try to get params from DSN
	dbhost = ""
	dbbase = ""
	dbuser = ""
	dbpasswd = ""
	dbopt = ""
	dbtty = ""
	try:
		params = string.split(dsn, ":")
		dbhost = params[0]
		dbbase = params[1]
		dbuser = params[2]
		dbpasswd = params[3]
		dbopt = params[4]
		dbtty = params[5]
	except:
		pass

	# override if necessary
	if user != "":
		dbuser = user
	if password != "":
		dbpasswd = password
	if database != "":
		dbbase = database
	if host != "":
		dbhost = host

	# empty host is localhost
	if dbhost == "":
		dbhost = "."
	if dbuser == "":
		dbuser = "sa"

	# add default port
	# it will be deleted, it doesn't work well for different names
	# of local machine; it forces TCP/IP communication for them [on windows]
	#	if ":" not in dbhost and "," not in dbhost and "\\" not in dbhost:
	#		dbhost += ",1433"

	_mssql.login_timeout = login_timeout

	# open the connection
	try:
		if dbbase != "":
			con = _mssql.connect(dbhost, dbuser, dbpasswd, trusted, charset, database, max_conn=max_conn)
		else:
			con = _mssql.connect(dbhost, dbuser, dbpasswd, trusted, charset, max_conn=max_conn)
	except _mssql.MssqlDatabaseException, e:
		raise OperationalError, e[0]
	except _mssql.MssqlDriverException, e:
		raise InterfaceError, e[0]
	
	# default query timeout
	try:
		timeout = int(timeout)
	except ValueError, e:
		timeout = 0

	if timeout != 0:
		con.query_timeout = timeout

	return pymssqlCnx(con, as_dict)