Max 5 API Reference
00001 /* 00002 ext_database.c 00003 Copyright 2008 - Cycling '74 00004 Timothy Place, tim@cycling74.com 00005 */ 00006 00007 #include "ext.h" 00008 #include "ext_obex.h" 00009 #include "ext_database.h" 00010 #include "ext_strings.h" 00011 00012 00013 #define DATABASE_SQL_MAXLEN 4096 00014 // Define the macro below to enable debug code 00015 //#define DATABASE_DEBUG 00016 00017 00018 t_max_err db_open(t_symbol *dbname, const char *fullpath, t_database **db) 00019 { 00020 long ac=0; 00021 t_atom av[6]; 00022 00023 if (*db) 00024 object_free(*db); 00025 00026 if (fullpath) { 00027 char coercedpath[MAX_PATH_CHARS]; 00028 short err; 00029 char dbpath[MAX_PATH_CHARS]; 00030 #ifdef MAC_VERSION 00031 char *temppath; 00032 #endif 00033 00034 err = path_nameconform((char*)fullpath, coercedpath, PATH_STYLE_NATIVE_PLAT, PATH_TYPE_ABSOLUTE); 00035 if (err) 00036 strncpy_zero(coercedpath, fullpath, MAX_PATH_CHARS); 00037 00038 #ifdef MAC_VERSION 00039 temppath = strchr(coercedpath, ':'); 00040 *temppath = '\0'; 00041 temppath += 1; 00042 00043 // at this point temppath points to the path after the volume, and coercedpath has the volume 00044 snprintf(dbpath, MAX_PATH_CHARS, "/Volumes/%s%s", coercedpath, temppath); 00045 #else // WIN_VERSION 00046 strncpy_zero(dbpath, coercedpath, MAX_PATH_CHARS); 00047 #endif 00048 00049 atom_setsym(av+ac, gensym("@rambased")); 00050 ac++; 00051 atom_setlong(av+ac, 0); 00052 ac++; 00053 atom_setsym(av+ac, gensym("@filename")); 00054 ac++; 00055 atom_setsym(av+ac, gensym(dbpath)); 00056 ac++; 00057 } 00058 atom_setsym(av+ac, gensym("@db")); 00059 ac++; 00060 atom_setsym(av+ac, dbname); 00061 ac++; 00062 00063 *db = (t_database*)object_new_typed(_sym_nobox, _sym_sqlite, ac, av); 00064 if (!*db) 00065 return MAX_ERR_GENERIC; 00066 00067 return MAX_ERR_NONE; 00068 } 00069 00070 t_max_err db_close(t_database **db) 00071 { 00072 object_free(*db); 00073 *db = NULL; 00074 return MAX_ERR_NONE; 00075 } 00076 00077 00078 t_max_err db_query(t_database *db, t_db_result **dbresult, const char *s, ...) 00079 { 00080 char sql[DATABASE_SQL_MAXLEN+2]; 00081 va_list ap; 00082 int err = 0; 00083 int len = 0; 00084 00085 if (db) { 00086 va_start(ap, s); 00087 00088 len = vsnprintf(sql, DATABASE_SQL_MAXLEN, s, ap); 00089 sql[DATABASE_SQL_MAXLEN] = '\0'; 00090 if (len >= DATABASE_SQL_MAXLEN) { 00091 cpost("DB: Query Overrun!\n"); 00092 return MAX_ERR_GENERIC; 00093 } 00094 err = (int)object_method(db, _sym_execstring, sql, dbresult); 00095 #ifdef DATABASE_DEBUG 00096 cpost("SQL: %s\n", sql); 00097 if (err) 00098 cpost(" ERROR: %i\n", err); 00099 #endif // DATABASE_DEBUG 00100 } 00101 return err; 00102 } 00103 00104 t_max_err db_query_silent(t_database *db, t_db_result **dbresult, const char *s, ...) 00105 { 00106 char sql[DATABASE_SQL_MAXLEN+2]; 00107 va_list ap; 00108 long logging = false; 00109 t_max_err err; 00110 00111 va_start(ap, s); 00112 vsnprintf(sql, DATABASE_SQL_MAXLEN, s, ap); 00113 sql[DATABASE_SQL_MAXLEN] = '\0'; 00114 00115 logging = object_attr_getlong(db, _sym_log); 00116 object_attr_setlong(db, _sym_log, 0); 00117 err = db_query(db, dbresult, sql, NULL); 00118 object_attr_setlong(db, _sym_log, logging); 00119 return err; 00120 } 00121 00122 t_max_err db_query_getlastinsertid(t_database *db, long *id) 00123 { 00124 *id = (long)object_method(db, _sym_getlastinsertid); 00125 return MAX_ERR_NONE; 00126 } 00127 00128 00129 t_max_err db_query_table_new(t_database *db, const char *tablename) 00130 { 00131 char idname[256]; 00132 00133 // SQLite won't let us add primary keys later, so we have to add it now. 00134 strncpy_zero(idname, tablename, 256); 00135 00136 // singularize 00137 if (idname[strlen(idname)-1 == 's']) 00138 idname[strlen(idname)-1] = 0; 00139 00140 return db_query(db, NULL, "CREATE TABLE IF NOT EXISTS %s ( %s_id INTEGER PRIMARY KEY NOT NULL )", tablename, idname); 00141 } 00142 00143 t_max_err db_query_table_addcolumn(t_database *db, const char *tablename, const char *columnname, const char *columntype, const char *flags) 00144 { 00145 if (flags) 00146 return db_query_silent(db, NULL, "ALTER TABLE %s ADD COLUMN %s %s %s", tablename, columnname, columntype, flags); 00147 else 00148 return db_query_silent(db, NULL, "ALTER TABLE %s ADD COLUMN %s %s", tablename, columnname, columntype); 00149 } 00150 00151 00152 t_max_err db_transaction_start(t_database *db) 00153 { 00154 return (t_max_err)object_method(db, _sym_starttransaction); 00155 } 00156 00157 t_max_err db_transaction_end(t_database *db) 00158 { 00159 return (t_max_err)object_method(db, _sym_endtransaction); 00160 } 00161 00162 t_max_err db_transaction_flush(t_database *db) 00163 { 00164 return (t_max_err)object_method(db, _sym_flush); 00165 } 00166 00167 00168 // DB VIEWS 00169 00170 t_max_err db_view_create(t_database *db, const char *sql, t_db_view **dbview) 00171 { 00172 *dbview = NULL; 00173 00174 if(sql && sql[0]) 00175 *dbview = (t_db_view *)object_method(db, gensym("createview"), gensym((char*)sql)); 00176 else 00177 *dbview = (t_db_view *)object_method(db, gensym("createview"), NULL); 00178 00179 if (!*dbview) 00180 return MAX_ERR_GENERIC; 00181 00182 return MAX_ERR_NONE; 00183 } 00184 00185 t_max_err db_view_remove(t_database *db, t_db_view **dbview) 00186 { 00187 if (db && *dbview) 00188 object_method(db, gensym("removeview"), *dbview); 00189 *dbview = NULL; 00190 return MAX_ERR_NONE; 00191 } 00192 00193 t_max_err db_view_getresult(t_db_view *dbview, t_db_result **result) 00194 { 00195 if (result){ 00196 *result = (t_db_view *)object_method(dbview, gensym("getresult")); 00197 return MAX_ERR_NONE; 00198 } 00199 return MAX_ERR_GENERIC; 00200 } 00201 00202 t_max_err db_view_setquery(t_db_view *dbview, char *newquery) 00203 { 00204 if (dbview) 00205 return object_attr_setsym(dbview, _sym_query, gensym(newquery)); 00206 else 00207 return MAX_ERR_GENERIC; 00208 } 00209 00210 00211 // DB RESULTS 00212 00213 char** db_result_nextrecord(t_db_result *result) 00214 { 00215 if (result) 00216 return (char **)object_method(result, _sym_nextrecord); 00217 else 00218 return NULL; 00219 } 00220 00221 void db_result_reset(t_db_result *result) 00222 { 00223 object_method(result, _sym_reset); 00224 } 00225 00226 void db_result_clear(t_db_result *result) 00227 { 00228 object_method(result, _sym_clear); 00229 } 00230 00231 long db_result_numrecords(t_db_result *result) 00232 { 00233 if (result) 00234 return (long)object_method(result, _sym_numrecords); 00235 else 00236 return 0; 00237 } 00238 00239 long db_result_numfields(t_db_result *result) 00240 { 00241 if (result) 00242 return (long)object_method(result, _sym_numfields); 00243 else 00244 return 0; 00245 } 00246 00247 char* db_result_fieldname(t_db_result *result, long fieldindex) 00248 { 00249 return (char *)object_method(result, _sym_fieldnamebyindex, fieldindex); 00250 } 00251 00252 char* db_result_string(t_db_result *result, long recordindex, long fieldindex) 00253 { 00254 return (char *)object_method(result, _sym_valuebyindex, recordindex, fieldindex); 00255 } 00256 00257 long db_result_long(t_db_result *result, long recordindex, long fieldindex) 00258 { 00259 char* c = (char *)object_method(result, _sym_valuebyindex, recordindex, fieldindex); 00260 long l = 0; 00261 00262 if (c) 00263 sscanf(c, "%ld", &l); 00264 return l; 00265 } 00266 00267 float db_result_float(t_db_result *result, long recordindex, long fieldindex) 00268 { 00269 char* c = (char *)object_method(result, _sym_valuebyindex, recordindex, fieldindex); 00270 float f = 0; 00271 00272 if (c) 00273 sscanf(c, "%f", &f); 00274 return f; 00275 } 00276 00277 unsigned long db_result_datetimeinseconds(t_db_result *result, long recordindex, long fieldindex) 00278 { 00279 char *str = db_result_string(result, recordindex, fieldindex); 00280 unsigned long seconds = 0; 00281 00282 if (str) 00283 db_util_stringtodate(str, &seconds); 00284 return seconds; 00285 } 00286 00287 00288 // UTILITIES 00289 00290 void db_util_stringtodate(const char *string, unsigned long *date) 00291 { 00292 t_datetime datetime; 00293 00294 sscanf(string, "%4lu-%02lu-%02lu %02lu:%02lu:%02lu", 00295 &datetime.year, &datetime.month, &datetime.day, 00296 &datetime.hour, &datetime.minute, &datetime.second); 00297 *date = systime_datetoseconds(&datetime); 00298 } 00299 00300 void db_util_datetostring(const unsigned long date, char *string) 00301 { 00302 t_datetime datetime; 00303 00304 systime_secondstodate(date, &datetime); 00305 sprintf(string, "%4lu-%02lu-%02lu %02lu:%02lu:%02lu", 00306 datetime.year, datetime.month, datetime.day, 00307 datetime.hour, datetime.minute, datetime.second); 00308 } 00309
Copyright © 2008, Cycling '74