1
2
3
4 """
5 Database interface code for MySQL database servers using the mysqli client
6 libraries. mysqli is included in PHP 5 by default and allows developers to
7 use the advanced features of MySQL 4.1.x, 5.0.x and beyond.
8
9 @package includes
10 @see <a href='http://drupy.net'>Drupy Homepage</a>
11 @see <a href='http://drupal.org'>Drupal Homepage</a>
12 @note Drupy is a port of the Drupal project.
13 @note
14 This file was ported from Drupal's includes/database_mysqli.inc and
15 includes/database-mysql_common.inc
16 @author Brendon Crawford
17 @copyright 2008 Brendon Crawford
18 @contact message144 at users dot sourceforge dot net
19 @created 2008-01-10
20 @version 0.1
21 @note License:
22
23 This program is free software; you can redistribute it and/or
24 modify it under the terms of the GNU General Public License
25 as published by the Free Software Foundation; either version 2
26 of the License, or (at your option) any later version.
27
28 This program is distributed in the hope that it will be useful,
29 but WITHOUT ANY WARRANTY; without even the implied warranty of
30 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 GNU General Public License for more details.
32
33 You should have received a copy of the GNU General Public License
34 along with this program; if not, write to:
35
36 The Free Software Foundation, Inc.,
37 51 Franklin Street, Fifth Floor,
38 Boston, MA 02110-1301,
39 USA
40 """
41
42 __version__ = "$Revision: 1 $"
43
44
45
46
47 from lib.drupy import DrupyPHP as php
48 from lib.drupy import DrupyMySQL
49 import appglobals as lib_appglobals
50 import bootstrap as lib_bootstrap
51 import database as lib_database
52
54 """
55 Report database status.
56 """
57 t = get_t()
58 version = db_version()
59 form['mysql'] = {
60 'title' : t('MySQL database'),
61 'value' : (l(version, 'admin/reports/status/sql') if \
62 (phase == 'runtime') else version),
63 }
64 if (version_compare(version, DRUPAL_MINIMUM_MYSQL) < 0):
65 form['mysql']['severity'] = REQUIREMENT_ERROR
66 form['mysql']['description'] = t(\
67 'Your MySQL Server is too old + Drupal requires at least ' + \
68 'MySQL %version.', {'%version' : DRUPAL_MINIMUM_MYSQL})
69 return form
70
71
72
74 """
75 Returns the version of the database server currently in use.
76
77 @return Database server version
78 """
79 version = php.explode('-', \
80 DrupyMySQL.mysqli_get_server_info(lib_appglobals.active_db))
81 return version
82
83
84
86 """
87 Initialise a database connection.
88
89 Note that mysqli does not support persistent connections.
90 """
91
92 url = php.parse_url(url, 3306)
93
94 url['user'] = php.urldecode(url['user'])
95
96 url['pass'] = (php.urldecode(url['pass']) if php.isset(url, 'pass') else '')
97 url['host'] = php.urldecode(url['host'])
98 url['path'] = php.urldecode(url['path'])
99 if (not php.isset(url, 'port')):
100 url['port'] = None
101 connection = DrupyMySQL.mysqli_real_connect(\
102 url['host'], url['user'], url['pass'], php.substr(url['path'], 1), \
103 url['port'], '', DrupyMySQL.MYSQLI_CLIENT_FOUND_ROWS)
104 if (DrupyMySQL.mysqli_connect_errno() > 0):
105 _db_error_page(DrupyMySQL.mysqli_connect_error())
106
107 DrupyMySQL.mysqli_query(connection, 'SET NAMES "utf8"')
108
109 DrupyMySQL.mysqli_query(connection, "SET php.SESSION sql_mode='ANSI'")
110 return connection
111
112
113
114 -def _query(query_, debug = 0):
115 """
116 Helper function for db_query().
117 """
118 if (lib_bootstrap.variable_get('dev_query', 0)):
119 usec,sec = php.explode(' ', php.microtime())
120 timer = float(usec) + float(sec)
121
122
123
124
125
126 bt = debug_backtrace()
127
128 name = (lib_appglobals.user.name if (lib_appglobals.user.uid > 0) else \
129 variable_get('anonymous', 'Anonymous'))
130
131
132 name = php.str_replace(['*', '/'], '', name)
133 query_ = '/* ' + name + ' : ' . bt[2]['function'] + ' */ ' + query_
134 result = DrupyMySQL.mysqli_query(lib_appglobals.active_db, query_)
135 if (lib_bootstrap.variable_get('dev_query', 0)):
136 query_ = bt[2]['function'] + "\n" + query_
137 usec,sec = php.explode(' ', php.microtime())
138 stop = float(usec) + float(sec)
139 diff = stop - timer
140 lib_appglobals.queries.append( [query_, diff] )
141 if (debug):
142 print '<p>query: ' + query_ + '<br />error:' + \
143 DrupyMySQL.mysqli_error(lib_appglobals.active_db) + '</p>'
144 if (not DrupyMySQL.mysqli_errno(lib_appglobals.active_db)):
145 return result
146 else:
147
148 DB_ERROR = True
149 php.trigger_error(lib_bootstrap.check_plain(\
150 DrupyMySQL.mysqli_error(lib_appglobals.active_db) + \
151 "\nquery: " + query_), php.E_USER_WARNING)
152 return False
153
154
155
157 """
158 Fetch one result row from the previous query as an object.
159
160 @param result
161 A database query result resource, as returned from db_query().
162 @return
163 An object representing the next row of the result,
164 or False. The attributes
165 of this object are the table fields selected by the query.
166 """
167 if (result):
168 object_ = DrupyMySQL.mysqli_fetch_object(result)
169 return (object_ if (object_ != None) else False)
170
171
172
173
175 """
176 Fetch one result row from the previous query as an array.
177
178 @param result
179 A database query result resource, as returned from db_query().
180 @return
181 An associative array representing the next row of the result, or False.
182 The keys of this object are the names of the table fields selected by the
183 query, and the values are the field values for this result row.
184 """
185 if (result):
186 array_ = DrupyMySQL.mysqli_fetch_array(result, DrupyMySQL.MYSQLI_ASSOC)
187 return (array_ if (array_ != None) else False)
188
189
190
192 """
193 Return an individual result field from the previous query.
194
195 Only use this function if exactly one field is being selected; otherwise,
196 use db_fetch_object() or db_fetch_array().
197
198 @param result
199 A database query result resource, as returned from db_query().
200 @return
201 The resulting field or False.
202 """
203 if (result and DrupyMySQL.mysqli_num_rows(result) > 0):
204
205
206
207 array_ = DrupyMySQL.mysqli_fetch_row(result)
208 return array_[0]
209 return False
210
211
212
218
219
220
221
227
228
229
231 """
232 Runs a limited-range query in the active database.
233
234 Use this as a substitute for db_query() when a subset of the query is to be
235 returned. User-supplied arguments to the query should be passed in as
236 separate parameters so that they can be properly escaped to avoid SQL
237 injection attacks.
238
239 @param query
240 A string containing an SQL query.
241 @param ...
242 A variable number of arguments which are substituted into the query
243 using printf() syntax. The query arguments can be enclosed in one
244 array instead.
245 Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
246 in '') and %%.
247 NOTE: using this syntax will cast None and False values to decimal 0,
248 and True values to decimal 1.
249 @param from
250 The first result row to return.
251 @param count
252 The maximum number of result rows to return.
253 @return
254 A database query result resource, or False if the query was not executed
255 correctly.
256 """
257 args = func_get_args()
258 count = php.array_pop(args)
259 from_ = php.array_pop(args)
260 php.array_shift(args)
261 query = db_prefix_tables(query)
262
263 if (php.isset(args, 0) and php.is_array(args, 0)):
264 args = args[0]
265 _db_query_callback(args, True)
266 query = php.preg_replace_callback(DB_QUERY_REGEXP, \
267 '_db_query_callback', query)
268 query += ' LIMIT ' + int(from_) + ', ' . int(count)
269 return _db_query(query)
270
271
272
273
275 """
276 Runs a SELECT query and stores its results in a temporary table.
277
278 Use this as a substitute for db_query() when the results need to stored
279 in a temporary table. Temporary tables exist for the duration of the page
280 request.
281 User-supplied arguments to the query should be passed in as
282 separate parameters
283 so that they can be properly escaped to avoid SQL injection attacks.
284
285 Note that if you need to know how many results were returned, you should do
286 a SELECT COUNT(*) on the temporary table afterwards. db_affected_rows() does
287 not give consistent result across different database types in this case.
288
289 @param query
290 A string containing a normal SELECT SQL query.
291 @param ...
292 A variable number of arguments which are substituted into the query
293 using printf() syntax. The query arguments can be enclosed in one
294 array instead.
295 Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
296 in '') and %%.
297
298 NOTE: using this syntax will cast None and False values to decimal 0,
299 and True values to decimal 1.
300
301 @param table
302 The name of the temporary table to select into. This name will not be
303 prefixed as there is no risk of collision.
304 @return
305 A database query result resource, or False if the query was not executed
306 correctly.
307 """
308 args = func_get_args()
309 tablename = php.array_pop(args)
310 php.array_shift(args)
311 query = php.preg_replace('/^SELECT/i', 'CREATE TEMPORARY TABLE ' + \
312 tablename + ' Engine=HEAP SELECT', db_prefix_tables(query))
313
314 if (php.isset(args, 0) and php.is_array(args, 0)):
315 args = args[0]
316 _db_query_callback(args, True)
317 query = php.preg_replace_callback(DB_QUERY_REGEXP, \
318 '_db_query_callback', query)
319 return _db_query(query)
320
321
322
324 """
325 Returns a properly formatted Binary Large Object value.
326
327 @param data
328 Data to encode.
329 @return
330 Encoded data.
331 """
332 return "'" + DrupyMySQL.mysqli_real_escape_string(\
333 lib_appglobals.active_db, data) + "'"
334
335
336
338 """
339 Returns text from a Binary Large OBject value.
340
341 @param data
342 Data to decode.
343 @return
344 Decoded data.
345 """
346 return data
347
348
355
356
357
359 """
360 Lock a table.
361 """
362 db_query('LOCK TABLES {' + db_escape_table(table) + '} WRITE')
363
364
365
366
368 """
369 Unlock all locked tables.
370 """
371 db_query('UNLOCK TABLES')
372
373
375 """
376 Check if a table exists.
377 """
378 return bool(lib_database.fetch_object(\
379 lib_database.query("SHOW TABLES LIKE '{" + \
380 lib_database.escape_table(table) + "}'")))
381
382
384 """
385 Check if a column exists in the given table.
386 """
387 return bool(lib_database.fetch_object(\
388 lib_database.query("SHOW COLUMNS FROM {" + \
389 lib_database.escape_table(table) + "} LIKE '" + \
390 lib_database.escape_table(column) + "'")))
391
392
394 """
395 Wraps the given table.field entry with a DISTINCT(). The wrapper is added to
396 the SELECT list entry of the given query and the resulting query is
397 returned. This function only applies the wrapper if a DISTINCT doesn't
398 already exist in the query.
399
400 @param table Table containing the field to set as DISTINCT
401 @param field Field to set as DISTINCT
402 @param query Query to apply the wrapper to
403 @return SQL query with the DISTINCT wrapper surrounding the given
404 table.field.
405 """
406 field_to_select = 'DISTINCT(' + table + '.' + field + ')'
407
408
409 return php.preg_replace('/(SELECT.*)(?:' + table + \
410 '\.|\s)(?<not DISTINCT\()(?<not DISTINCT\(' + table + '\.)' + field + \
411 '(.*FROM )/AUsi', '\1 ' + field_to_select + '\2', query)
412
413
414
415
416
417
418
419
420
421
422
423
424 -def query(query_, *args):
425 """
426 Runs a basic query in the active database.
427
428 User-supplied arguments to the query should be passed in as separate
429 parameters so that they can be properly escaped to avoid SQL injection
430 attacks.
431
432 @param query
433 A string containing an SQL query.
434 @param ...
435 A variable number of arguments which are substituted into the query
436 using printf() syntax. Instead of a variable number of query arguments,
437 you may also pass a single array containing the query arguments.
438
439 Valid %-modifiers are: %s, %d, %f, %b (binary data, do not enclose
440 in '') and %%.
441
442 NOTE: using this syntax will cast None and False values to decimal 0,
443 and True values to decimal 1.
444
445 @return
446 A database query result resource, or False if the query was not
447 executed correctly.
448 """
449 this_query = lib_database.prefix_tables(query_)
450
451 if (php.isset(args, 0) and php.is_array(args[0])):
452 args = args[0]
453 lib_database._query_callback(args, True)
454 this_query = php.preg_replace_callback(lib_database.DB_QUERY_REGEXP, \
455 lib_database._query_callback, this_query)
456
457
458
459
460 return _query(this_query)
461
462
463
464
465
466
467
469 """
470 Generate SQL to create a new table from a Drupal schema definition.
471
472 @param name
473 The name of the table to create.
474 @param table
475 A Schema API table definition array.
476 @return
477 An array of SQL statements to create the table.
478 """
479 if (php.empty(table['mysql_suffix'])):
480 table['mysql_suffix'] = "/*not 40100 DEFAULT CHARACTER SET UTF8 */"
481 sql = "CREATE TABLE {" + name + "} (\n"
482
483 for field_name,field in table['fields'].items():
484 sql += _db_create_field_sql(field_name, _db_process_field(field)) + ", \n"
485
486 keys = _db_create_keys_sql(table)
487 if (php.count(keys)):
488 sql += php.implode(", \n", keys) + ", \n"
489
490 sql = php.substr(sql, 0, -3) + "\n) "
491 sql += table['mysql_suffix']
492 return array(sql)
493
494
495
497 keys = {}
498 if (not php.empty(spec['primary key'])):
499 keys.append( 'PRIMARY KEY (' + \
500 _db_create_key_sql(spec['primary key']) + ')' )
501 if (not php.empty(spec['unique keys'])):
502 for key,fields in spec['unique keys'].items():
503 keys.append( 'UNIQUE KEY ' + key + \
504 ' (' + _db_create_key_sql(fields) + ')' )
505 if (not php.empty(spec['indexes'])):
506 for index,fields in spec['indexes'].items():
507 keys.append( 'INDEX ' + index + ' (' + \
508 _db_create_key_sql(fields) + ')' )
509 return keys
510
511
512
513
515 ret = []
516 for field in fields:
517 if (php.is_array(field)):
518 ret.append( field[0] + '(' + field[1] + ')' )
519 else:
520 ret.append( field )
521 return php.implode(', ', ret)
522
523
525 """
526 Set database-engine specific properties for a field.
527
528 @param field
529 A field description array, as specified in the schema documentation.
530 """
531 if (not php.isset(field, 'size')):
532 field['size'] = 'normal'
533
534 if (not php.isset(field, 'mysql_type')):
535 map_ = db_type_map()
536 field['mysql_type'] = map_[field['type'] + ':' + field['size']]
537 if (field['type'] == 'serial'):
538 field['auto_increment'] = True
539 return field
540
541
542
544 """
545 Create an SQL string for a field to be used in table creation or alteration.
546
547 Before passing a field out of a schema definition into this function it has
548 to be processed by _db_process_field().
549
550 @param name
551 Name of the field.
552 @param spec
553 The field specification, as per the schema data structure format.
554 """
555 sql = "`" + name + "` " . spec['mysql_type']
556 if (php.isset(spec, 'length')):
557 sql += '(' + spec['length'] + ')'
558 elif (php.isset(spec, 'precision') and php.isset(spec, 'scale')):
559 sql += '(' + spec['precision'] + ', ' + spec['scale'] + ')'
560 if (not php.empty(spec['unsigned'])):
561 sql += ' unsigned'
562 if (not php.empty(spec['not None'])):
563 sql += ' NOT None'
564 if (not php.empty(spec['auto_increment'])):
565 sql += ' auto_increment'
566 if (php.isset(spec, 'default')):
567 if (is_string(spec['default'])):
568 spec['default'] = "'" + spec['default'] + "'"
569 sql += ' DEFAULT ' + spec['default']
570 if (php.empty(spec['not None']) and not php.isset(spec, 'default')):
571 sql += ' DEFAULT None'
572 return sql
573
574
575
576
577
579 """
580 This maps a generic data type in combination with its data size
581 to the engine-specific data type.
582 """
583
584
585
586 map_ = {
587 'varchar:normal' : 'VARCHAR',
588 'char:normal' : 'CHAR',
589 'text:tiny' : 'TINYTEXT',
590 'text:small' : 'TINYTEXT',
591 'text:medium' : 'MEDIUMTEXT',
592 'text:big' : 'LONGTEXT',
593 'text:normal' : 'TEXT',
594 'serial:tiny' : 'TINYINT',
595 'serial:small' : 'SMALLINT',
596 'serial:medium' : 'MEDIUMINT',
597 'serial:big' : 'BIGINT',
598 'serial:normal' : 'INT',
599 'int:tiny' : 'TINYINT',
600 'int:small' : 'SMALLINT',
601 'int:medium' : 'MEDIUMINT',
602 'int:big' : 'BIGINT',
603 'int:normal' : 'INT',
604 'float:tiny' : 'FLOAT',
605 'float:small' : 'FLOAT',
606 'float:medium' : 'FLOAT',
607 'float:big' : 'DOUBLE',
608 'float:normal' : 'FLOAT',
609 'numeric:normal' : 'DECIMAL',
610 'blob:big' : 'LONGBLOB',
611 'blob:normal' : 'BLOB',
612 'datetime:normal' : 'DATETIME'
613 }
614 return map_
615
616
617
619 """
620 Rename a table.
621
622 @param ret
623 Array to which query results will be added.
624 @param table
625 The table to be renamed.
626 @param new_name
627 The new name for the table.
628 """
629 php.Reference.check(ref)
630 ret.append( update_sql('ALTER TABLE {' + table + '} RENAME TO {' + \
631 new_name + '}') )
632
633
634
636 """
637 Drop a table.
638
639 @param ret
640 Array to which query results will be added.
641 @param table
642 The table to be dropped.
643 """
644 php.Reference.check(ref)
645 php.array_merge( update_sql('DROP TABLE {' + table + '}'), ret, True )
646
647
648
649 -def add_field(ret, table, field, spec, keys_new = []):
650 """
651 Add a new field to a table.
652
653 @param ret
654 Array to which query results will be added.
655 @param table
656 Name of the table to be altered.
657 @param field
658 Name of the field to be added.
659 @param spec
660 The field specification array, as taken from a schema definition.
661 The specification may also contain the key 'initial', the newly
662 created field will be set to the value of the key in all rows.
663 This is most useful for creating NOT None columns with no default
664 value in existing tables.
665 @param keys_new
666 Optional keys and indexes specification to be created on the
667 table along with adding the field. The format is the same as a
668 table specification but without the 'fields' element. If you are
669 adding a type 'serial' field, you MUST specify at least one key
670 or index including it in this array. @see db_change_field for more
671 explanation why.
672 """
673 php.Reference.check(ret)
674 fixNone = False
675 if (not php.empty(spec['not None']) and not php.isset(spec, 'default')):
676 fixNone = True
677 spec['not None'] = False
678 query = 'ALTER TABLE {' + table + '} ADD '
679 query += _db_create_field_sql(field, _db_process_field(spec))
680 if (php.count(keys_new)):
681 query += ', ADD ' + php.implode(', ADD ', _db_create_keys_sql(keys_new))
682 ret.append( update_sql(query) )
683 if (php.isset(spec, 'initial')):
684
685 sql = 'UPDATE {' + table + '} SET ' + field + ' = ' + \
686 db_type_placeholder(spec['type'])
687 result = db_query(sql, spec['initial'])
688 ret.append( {'success' : result != False, \
689 'query' : check_plain(sql + ' (' + spec['initial'] + ')')})
690 if (fixNone):
691 spec['not None'] = True
692 db_change_field(ret, table, field, field, spec)
693
694
695
697 """
698 Drop a field.
699
700 @param ret
701 Array to which query results will be added.
702 @param table
703 The table to be altered.
704 @param field
705 The field to be dropped.
706 """
707 php.Reference.check(ret)
708 ret.append( update_sql('ALTER TABLE {' + table + '} DROP ' + field) )
709
710
712 """
713 Set the default value for a field.
714
715 @param ret
716 Array to which query results will be added.
717 @param table
718 The table to be altered.
719 @param field
720 The field to be altered.
721 @param default
722 Default value to be set. None for 'default None'.
723 """
724 php.Reference.check(ret)
725 if (default == None):
726 default = 'None'
727 else:
728 default = ("'default'" if is_string(default) else default)
729 ret.append( update_sql('ALTER TABLE {' + table + \
730 '} ALTER COLUMN ' + field + ' SET DEFAULT ' + default) )
731
732
733
735 """
736 Set a field to have no default value.
737
738 @param ret
739 Array to which query results will be added.
740 @param table
741 The table to be altered.
742 @param field
743 The field to be altered.
744 """
745 php.Reference.check(ret)
746 ret.append( update_sql('ALTER TABLE {' + table + \
747 '} ALTER COLUMN ' + field + ' DROP DEFAULT') )
748
749
750
751
753 """
754 Add a primary key.
755
756 @param ret
757 Array to which query results will be added.
758 @param table
759 The table to be altered.
760 @param fields
761 Fields for the primary key.
762 """
763 php.Reference.check(ret)
764 ret.append( update_sql('ALTER TABLE {' + table + \
765 '} ADD PRIMARY KEY (' + _db_create_key_sql(fields) + ')') )
766
767
768
770 """
771 Drop the primary key.
772
773 @param ret
774 Array to which query results will be added.
775 @param table
776 The table to be altered.
777 """
778 php.Reference.check(ret)
779 ret.append( update_sql('ALTER TABLE {' + table + \
780 '} DROP PRIMARY KEY') )
781
782
783
785 """
786 Add a unique key.
787
788 @param ret
789 Array to which query results will be added.
790 @param table
791 The table to be altered.
792 @param name
793 The name of the key.
794 @param fields
795 An array of field names.
796 """
797 php.Reference.check(ret)
798 ret.val.append( update_sql('ALTER TABLE {' + table + \
799 '} ADD UNIQUE KEY ' + name + ' (' + _db_create_key_sql(fields) + ')') )
800
801
802
804 """
805 Drop a unique key.
806
807 @param ret
808 Array to which query results will be added.
809 @param table
810 The table to be altered.
811 @param name
812 The name of the key.
813 """
814 php.Reference.check(ret)
815 ret.append( update_sql('ALTER TABLE {' + table + \
816 '} DROP KEY ' + name) )
817
818
819
821 """
822 Add an index.
823
824 @param ret
825 Array to which query results will be added.
826 @param table
827 The table to be altered.
828 @param name
829 The name of the index.
830 @param fields
831 An array of field names.
832 """
833 php.Reference.check(ret)
834 query = 'ALTER TABLE {' + table + '} ADD INDEX ' + name + \
835 ' (' + _db_create_key_sql(fields) + ')'
836 ret.append( update_sql(query) )
837
838
839
841 """
842 Drop an index.
843
844 @param ret
845 Array to which query results will be added.
846 @param table
847 The table to be altered.
848 @param name
849 The name of the index.
850 """
851 php.Reference.check(ret)
852 ret.append( update_sql('ALTER TABLE {' + table + \
853 '} DROP INDEX ' + name) )
854
855
856
857 -def change_field(ret, table, field, field_new, spec, keys_new = []):
858 """
859 Change a field definition.
860
861 IMPORTANT NOTE: To maintain database portability, you have to explicitly
862 recreate all indices and primary keys that are using the changed field.
863
864 That means that you have to drop all affected keys and indexes with
865 db_drop_{primary_key,unique_key,index}() before calling db_change_field().
866 To recreate the keys and indices, pass the key definitions as the
867 optional keys_new argument directly to db_change_field().
868
869 For example, suppose you have:
870 @code
871 schema['foo'] = array(
872 'fields' : array(
873 'bar' : array('type' : 'int', 'not None' : True)
874 ),
875 'primary key' : array('bar')
876 )
877 @endcode
878 and you want to change foo.bar to be type serial, leaving it as the
879 primary key. The correct sequence is:
880 @code
881 db_drop_primary_key(ret, 'foo')
882 db_change_field(ret, 'foo', 'bar', 'bar',
883 array('type' : 'serial', 'not None' : True),
884 array('primary key' : array('bar')))
885 @endcode
886
887 The reasons for this are due to the different database engines:
888
889 On PostgreSQL, changing a field definition involves adding a new field
890 and dropping an old one which* causes any indices, primary keys and
891 sequences (from serial-type fields) that use the changed field to be
892 dropped.
893
894 On MySQL, all type 'serial' fields must be part of at least one key
895 or index as soon as they are created. You cannot use
896 db_add_{primary_key,unique_key,index}() for this purpose because
897 the ALTER TABLE command will fail to add the column without a key
898 or index specification. The solution is to use the optional
899 keys_new argument to create the key or index at the same time as
900 field.
901
902 You could use db_add_{primary_key,unique_key,index}() in all cases
903 unless you are converting a field to be type serial. You can use
904 the keys_new argument in all cases.
905
906 @param ret
907 Array to which query results will be added.
908 @param table
909 Name of the table.
910 @param field
911 Name of the field to change.
912 @param field_new
913 New name for the field (set to the same as field if you don't want to
914 change the name).
915 @param spec
916 The field specification for the new field.
917 @param keys_new
918 Optional keys and indexes specification to be created on the
919 table along with changing the field. The format is the same as a
920 table specification but without the 'fields' element.
921 """
922 php.Reference.check(ret)
923 sql = 'ALTER TABLE {' + table + '} CHANGE ' + field + ' ' + \
924 _db_create_field_sql(field_new, _db_process_field(spec))
925 if (php.count(keys_new) > 0):
926 sql += ', ADD ' + php.implode(', ADD ', _db_create_keys_sql(keys_new))
927 ret.append( update_sql(sql) )
928
929
931 """
932 Returns the last insert id.
933
934 @param table
935 The name of the table you inserted into.
936 @param field
937 The name of the autoincrement field.
938 """
939 return db_result(db_query('SELECT LAST_INSERT_ID()'))
940
941
942
948
949
950
951
952
953
954 fetch_assoc = fetch_array
955