4a3f3df9cab079354e8a9f4cf6c56f616f1ea0ab kent Fri Apr 6 16:29:22 2012 -0700 Removing MySQL linking dependency. diff --git src/hg/autoSql/autoSql.c src/hg/autoSql/autoSql.c deleted file mode 100644 index 88ba3af..0000000 --- src/hg/autoSql/autoSql.c +++ /dev/null @@ -1,1946 +0,0 @@ -/* autoSql - automatically generate SQL and C code for saving - * and loading entities in database. - * - * This module is pretty ugly. It seems to work within some - * limitations (described in the autoSql.doc). Rather than do major - * changes from here I'd rewrite it though. The tokenizer is - * pretty sound, the parser isn't bad (though the language it - * parses is quirky), but the code generator is u-g-l-y. - * - * This file is copyright 2002-2005 Jim Kent, but license is hereby - * granted for all use - public, private or commercial. */ - -#include "common.h" -#include "errabort.h" -#include "linefile.h" -#include "obscure.h" -#include "dystring.h" -#include "asParse.h" -#include "options.h" - - -boolean withNull = FALSE; -boolean makeJson = FALSE; -boolean makeDjango = FALSE; - -void usage() -/* Explain usage and exit. */ -{ -errAbort("autoSql - create SQL and C code for permanently storing\n" - "a structure in database and loading it back into memory\n" - "based on a specification file\n" - "usage:\n" - " autoSql specFile outRoot {optional: -dbLink -withNull -json} \n" - "This will create outRoot.sql outRoot.c and outRoot.h based\n" - "on the contents of specFile. \n" - "\n" - "options:\n" - " -dbLink - optionally generates code to execute queries and\n" - " updates of the table.\n" - " -withNull - optionally generates code and .sql to enable\n" - " applications to accept and load data into objects\n" - " with potential 'missing data' (NULL in SQL)\n" - " situations.\n" - " -django - generate method to output object as django model Python code\n" - " -json - generate method to output the object in JSON (JavaScript) format.\n"); -} - -static struct optionSpec optionSpecs[] = { - {"dbLink", OPTION_BOOLEAN}, - {"withNull", OPTION_BOOLEAN}, - {"json", OPTION_BOOLEAN}, - {"django", OPTION_BOOLEAN}, - {NULL, 0} -}; - -void sqlColumn(struct asColumn *col, FILE *f) -/* Print out column in SQL. */ -{ -fprintf(f, " %s ", col->name); -struct dyString *type = asColumnToSqlType(col); -fprintf(f, "%s", type->string); -if (!withNull) - fprintf(f, " not null"); -fputc(',', f); -fprintf(f, "\t# %s\n", col->comment); -dyStringFree(&type); -} - -void sqlTable(struct asObject *table, FILE *f) -/* Print out structure of table in SQL. */ -{ -struct asColumn *col; - -fprintf(f, "\n#%s\n", table->comment); -fprintf(f, "CREATE TABLE %s (\n", table->name); -for (col = table->columnList; col != NULL; col = col->next) - sqlColumn(col, f); - -fprintf(f," #Indices\n"); -fprintf(f, " PRIMARY KEY(%s)\n", table->columnList->name); -fprintf(f, ");\n"); -} - -void djangoEnumChoices(struct asColumn *col, FILE *f) -/* Write out a list of choices to use with a django enum. */ -{ -fprintf(f, " %sChoices = (\n", col->name); -struct slName *val; -for (val = col->values; val != NULL; val = val->next) - fprintf(f, " ('%s', '%s'),\n", val->name, val->name); -fprintf(f, " )\n"); -} - -int longestValue(struct asColumn *col) -/* Return length of longest value in col->values list */ -{ -int longest = 0; -struct slName *val; -for (val = col->values; val != NULL; val = val->next) - { - int len = strlen(val->name); - if (len > longest) - longest = len; - } -return longest; -} - -void djangoColumn(struct asColumn *col, FILE *f) -/* Print out column in Django flavored python. */ -{ -fprintf(f, " %s = models.", col->name); -struct asTypeInfo *lt = col->lowType; -if (lt->type == t_enum) - fprintf(f, "CharField(max_length=%d choices=%sChoices)", longestValue(col), col->name); -else if (lt->type == t_set) - { - warn("Set type fields such as '%s' are not tested in Django and are unlikely to work.", - col->name); - fprintf(f, "TextField() # A set in autoSql"); - } -else if (col->isList || col->isArray) - fprintf(f, "TextField()"); -else if (lt->type == t_char) - fprintf(f, "CharField(max_length=%d)", col->fixedSize ? col->fixedSize : 1); -else if (lt->type == t_string) - fprintf(f, "CharField(max_length=255)"); -else - fprintf(f, "%s()", lt->djangoName); -fprintf(f, "\t# %s\n", col->comment); -} - -void djangoModel(struct asObject *table, FILE *f) -/* Print out structure of table in Django flavored python */ -{ -fprintf(f, "class %s(models.Model):\n"); -struct asColumn *col; -for (col = table->columnList; col != NULL; col = col->next) - if (col->lowType->type == t_enum) - djangoEnumChoices(col, f); -for (col = table->columnList; col != NULL; col = col->next) - djangoColumn(col, f); -fprintf(f, "\n"); -} - -static void cSymTypePrName(struct asObject *dbObj, char *name, FILE *f) -/* print the C type name, prefixed with the object name */ -{ -char cname[1024]; -safef(cname, sizeof(cname), "%s%c%s", dbObj->name, toupper(name[0]), name+1); -// Fix name so that it is a valid C identifier. -char *c; -for (c = cname; *c != '\0'; c++) - { - if (!(isalnum(*c) || (*c == '_'))) - *c = '_'; - } -fputs(cname, f); -} - -void cSymTypeDef(struct asObject *dbObj, struct asColumn *col, FILE *f) -/* print out C enum for enum or set columns. enum and value names are - * prefixed with structure names to prevent collisions */ -{ -boolean isEnum = (col->lowType->type == t_enum); -fprintf(f, "enum "); -cSymTypePrName(dbObj, col->name, f); -fprintf(f, "\n {\n"); -unsigned value = isEnum ? 0 : 1; -struct slName *val; -for (val = col->values; val != NULL; val = val->next) - { - fprintf(f, " "); - cSymTypePrName(dbObj, val->name, f); - if (isEnum) - { - fprintf(f, " = %d,\n", value); - value++; - } - else - { - fprintf(f, " = 0x%.4x,\n", value); - value = value << 1; - } - } -fprintf(f, " };\n"); -} - -void cObjColumn(struct asColumn *col, FILE *f) -/* Print out an object column in C. */ -{ -if (col->lowType->type == t_object) - fprintf(f, " struct %s *%s", col->obType->name, col->name); -else if (col->lowType->type == t_simple) - { - if (col->isArray) - { - if (col->fixedSize) - fprintf(f, " struct %s %s[%d]", - col->obType->name, col->name, col->fixedSize); - else - fprintf(f, " struct %s *%s", - col->obType->name, col->name); - } - else - fprintf(f, " struct %s %s", col->obType->name, col->name); - } -else - assert(FALSE); -} - -void cCharColumn(struct asColumn *col, FILE *f) -/* Print out a char column in C. */ -{ -fprintf(f, " %s", col->lowType->cName); -if (col->fixedSize > 0) - fprintf(f, " %s[%d]", col->name, col->fixedSize+1); -else if (col->isList) - fprintf(f, " *%s", col->name); -else - fprintf(f, " %s", col->name); -} - -void cEnumColumn(struct asObject *dbObj, struct asColumn *col, FILE *f) -/* print out enum column def in C */ -{ -fprintf(f, " enum "); -cSymTypePrName(dbObj, col->name, f); -fprintf(f, " %s", col->name); -} - -void cOtherColumn(struct asColumn *col, FILE *f) -/* Print out other types of column in C. */ -{ -fprintf(f, " %s", col->lowType->cName); -if (!withNull) - { - if (!col->lowType->stringy) - fputc(' ',f); - } -else - { - if (!col->lowType->stringy) - { - fputc(' ',f); - fputc('*',f); - } - } - -if (col->isList && !col->fixedSize) - fputc('*', f); -fprintf(f, "%s", col->name); -if (col->isList && col->fixedSize) - fprintf(f, "[%d]", col->fixedSize); -} - -void cColumn(struct asObject *dbObj, struct asColumn *col, FILE *f) -/* Print out a column in C. */ -{ -if (col->obType != NULL) - cObjColumn(col, f); -else if (col->lowType->type == t_char) - cCharColumn(col, f); -else if (col->lowType->type == t_enum) - cEnumColumn(dbObj, col, f); -else - cOtherColumn(col, f); -fprintf(f, ";\t/* %s */\n", col->comment); -} - -void cTable(struct asObject *dbObj, FILE *f) -/* Print out structure of dbObj in C. */ -{ -struct asColumn *col; -char defineName[256]; - -splitPath(dbObj->name, NULL, defineName, NULL); -touppers(defineName); -fprintf(f, "#define %s_NUM_COLS %d\n\n", defineName, - slCount(dbObj->columnList)); - -for (col = dbObj->columnList; col != NULL; col = col->next) - { - if ((col->lowType->type == t_enum) || (col->lowType->type == t_set)) - cSymTypeDef(dbObj, col, f); - } - -fprintf(f, "struct %s\n", dbObj->name); -fprintf(f, "/* %s */\n", dbObj->comment); -fprintf(f, " {\n"); -if (!dbObj->isSimple) - fprintf(f, " struct %s *next; /* Next in singly linked list. */\n", dbObj->name); -for (col = dbObj->columnList; col != NULL; col = col->next) - cColumn(dbObj, col, f); -fprintf(f, " };\n\n"); -} - -static boolean trueFalse[] = {TRUE, FALSE}; - -void makeCommaInColumn(char *indent, struct asColumn *col, FILE *f, bool isArray) -/* Make code to read in one column from a comma separated set. */ -{ -struct asObject *obType = col->obType; -struct asTypeInfo *lt = col->lowType; -char *arrayRef = (isArray ? "[i]" : ""); - -if (obType != NULL) - { - if (lt->type == t_object) - { - fprintf(f, "%ss = sqlEatChar(s, '{');\n", indent); - fprintf(f, "%sif(s[0] != '}')",indent); - fprintf(f, "%s slSafeAddHead(&ret->%s, %sCommaIn(&s,NULL));\n", indent, - col->name, obType->name); - fprintf(f, "%ss = sqlEatChar(s, '}');\n", indent); - fprintf(f, "%ss = sqlEatChar(s, ',');\n", indent); - } - else if (lt->type == t_simple) - { - fprintf(f, "%ss = sqlEatChar(s, '{');\n", indent); - fprintf(f, "%sif(s[0] != '}')",indent); - fprintf(f, "%s %sCommaIn(&s, &ret->%s%s);\n", indent, - obType->name, col->name, arrayRef); - fprintf(f, "%ss = sqlEatChar(s, '}');\n", indent); - fprintf(f, "%ss = sqlEatChar(s, ',');\n", indent); - } - else - { - assert(FALSE); - } - } -else if ((lt->type == t_enum) || (lt->type == t_set)) - { - if (!withNull) - { - fprintf(f, "%sret->%s = sql%sComma(&s, values_%s, &valhash_%s);\n", indent, - col->name, lt->nummyName, col->name, col->name); - } - else - { - fprintf(f, "%sret->%s = needMem(sizeof(*(ret->%s)));\n", indent, col->name, col->name); - fprintf(f, "%s*(ret->%s) = sql%sComma(&s, values_%s, &valhash_%s);\n", indent, - col->name, lt->nummyName, col->name, col->name); - } - } -else if (lt->stringy) - fprintf(f, "%sret->%s%s = sqlStringComma(&s);\n", indent, col->name, arrayRef); -else if (lt->isUnsigned) - { - if (!withNull) - { - fprintf(f, "%sret->%s%s = sqlUnsignedComma(&s);\n", indent, col->name, arrayRef); - } - else - { - fprintf(f, "%sret->%s = needMem(sizeof(unsigned));\n", indent, col->name); - fprintf(f, "%s*(ret->%s%s) = sqlUnsignedComma(&s);\n", indent, col->name, arrayRef); - } - } -else if (lt->type == t_char) - { - if (col->fixedSize > 0) - fprintf(f, "%ssqlFixedStringComma(&s, ret->%s%s, sizeof(ret->%s%s));\n", - indent, col->name, arrayRef, col->name, arrayRef); - else if (col->isList) - fprintf(f, "%sret->%s%s = sqlCharComma(&s);\n", - indent, col->name, arrayRef); - else - fprintf(f, "%ssqlFixedStringComma(&s, &(ret->%s), sizeof(ret->%s));\n", - indent, col->name, col->name); - } -else - { - if (!withNull) - { - fprintf(f, "%sret->%s%s = sql%sComma(&s);\n", indent, col->name, arrayRef, lt->nummyName); - } - else - { - fprintf(f, "%sret->%s = needMem(sizeof(*(ret->%s)));\n", indent, col->name, col->name); - fprintf(f, "%s*(ret->%s%s) = sql%sComma(&s);\n", indent, col->name, arrayRef, lt->nummyName); - } - } -} - - -void loadColumn(struct asColumn *col, int colIx, boolean isDynamic, boolean isSizeLink, - FILE *f) -/* Print statement to load column. */ -{ -char *staDyn = (isDynamic ? "Dynamic" : "Static"); - -if (col->isSizeLink == isSizeLink) - { - struct asTypeInfo *lt = col->lowType; - enum asTypes type = lt->type; - struct asObject *obType = col->obType; - if (col->isList || col->isArray) - { - char *lName; - if ((lName = lt->listyName) == NULL) - errAbort("Sorry, lists of %s not implemented.", lt->name); - if (obType) - { - fprintf(f, "{\n"); - fprintf(f, "int i;\n"); - fprintf(f, "char *s = row[%d];\n", colIx); - if (col->fixedSize) - { - fprintf(f, "for (i=0; i<%d; ++i)\n", col->fixedSize); - } - else - { - if (type == t_simple) - { - fprintf(f, "AllocArray(ret->%s, ret->%s);\n", col->name, - col->linkedSize->name); - } - fprintf(f, "for (i=0; i%s; ++i)\n", col->linkedSize->name); - } - fprintf(f, " {\n"); - fprintf(f, " s = sqlEatChar(s, '{');\n"); - if (type == t_object) - { - fprintf(f, " slSafeAddHead(&ret->%s, %sCommaIn(&s, NULL));\n", - col->name, obType->name); - } - else if (type == t_simple) - { - fprintf(f, " %sCommaIn(&s, &ret->%s[i]);\n", obType->name, col->name); - } - else - assert(FALSE); - fprintf(f, " s = sqlEatChar(s, '}');\n"); - fprintf(f, " s = sqlEatChar(s, ',');\n"); - fprintf(f, " }\n"); - if (type == t_object) - fprintf(f, "slReverse(&ret->%s);\n", col->name); - fprintf(f, "}\n"); - } - else - { - if (col->fixedSize) - { - if (isDynamic && lt->stringy) - { - fprintf(f, "{\n"); - fprintf(f, "char *s = cloneString(row[%d]);\n", colIx); - fprintf(f, "sql%sArray(s, ret->%s, %d);\n", - lName, col->name, col->fixedSize); - fprintf(f, "}\n"); - } - else - { - fprintf(f, "sql%sArray(row[%d], ret->%s, %d);\n", - lName, colIx, col->name, col->fixedSize); - } - } - else - { - struct asColumn *ls; - fprintf(f, "{\n"); - fprintf(f, "int sizeOne;\n"); - fprintf(f, "sql%s%sArray(row[%d], &ret->%s, &sizeOne);\n", - lName, staDyn, colIx, col->name); - if ((ls = col->linkedSize) != NULL) - fprintf(f, "assert(sizeOne == ret->%s);\n", ls->name); - fprintf(f, "}\n"); - } - } - } - else - { - switch (type) - { - case t_float: - if (!withNull) - { - fprintf(f, "ret->%s = sqlFloat(row[%d]);\n", col->name, colIx); - } - else - { - fprintf(f, "if (row[%d] != NULL)\n", colIx); - fprintf(f, " {\n"); - fprintf(f, " ret->%s = needMem(sizeof(float));\n", col->name); - fprintf(f, " *(ret->%s) = sqlFloat(row[%d]);\n", col->name, colIx); - fprintf(f, " }\n"); - } - - break; - case t_double: - fprintf(f, "ret->%s = sqlDouble(row[%d]);\n", col->name, colIx); - break; - case t_string: - case t_lstring: - if (isDynamic) - fprintf(f, "ret->%s = cloneString(row[%d]);\n", col->name, colIx); - else - fprintf(f, "ret->%s = row[%d];\n", col->name, colIx); - break; - case t_char: - if (col->fixedSize > 0) - fprintf(f, "safecpy(ret->%s, sizeof(ret->%s), row[%d]);\n", col->name, col->name, colIx); - else - fprintf(f, "ret->%s = row[%d][0];\n", col->name, colIx); - break; - case t_object: - { - struct asObject *obj = col->obType; - fprintf(f, "{\n"); - fprintf(f, "char *s = row[%d];\n", colIx); - fprintf(f, "if(s != NULL && differentString(s, \"\"))\n"); - fprintf(f, " ret->%s = %sCommaIn(&s, NULL);\n", col->name, obj->name); - fprintf(f, "}\n"); - break; - } - case t_simple: - { - struct asObject *obj = col->obType; - fprintf(f, "{\n"); - fprintf(f, "char *s = row[%d];\n", colIx); - fprintf(f, "if(s != NULL && differentString(s, \"\"))\n"); - fprintf(f, " %sCommaIn(&s, &ret->%s);\n", obj->name, col->name); - fprintf(f, "}\n"); - break; - } - case t_enum: - case t_set: - { - fprintf(f, "ret->%s = sql%sParse(row[%d], values_%s, &valhash_%s);\n", col->name, - col->lowType->nummyName, colIx, col->name, col->name); - break; - } - default: - { - if (!withNull) - { - fprintf(f, "ret->%s = sql%s(row[%d]);\n", - col->name, lt->nummyName, colIx); - } - else - { - fprintf(f, "if (row[%d] != NULL)\n", colIx); - fprintf(f, " {\n"); - fprintf(f, " ret->%s = needMem(sizeof(*(ret->%s)));\n", col->name, col->name); - fprintf(f, " *(ret->%s) = sql%s(row[%d]);\n", - col->name, lt->nummyName, colIx); - fprintf(f, " }\n"); - fprintf(f, "else\n"); - fprintf(f, " {\n"); - fprintf(f, " ret->%s = NULL;\n", col->name); - fprintf(f, " }\n"); - } - - break; - } - } - } - } -} - -void makeCommaIn(struct asObject *table, FILE *f, FILE *hFile) -/* Make routine that loads object from comma separated file. */ -{ -char *tableName = table->name; -struct asColumn *col; - -fprintf(hFile, "struct %s *%sCommaIn(char **pS, struct %s *ret);\n", - tableName, tableName, tableName); -fprintf(hFile, "/* Create a %s out of a comma separated string. \n", tableName); -fprintf(hFile, " * This will fill in ret if non-null, otherwise will\n"); -fprintf(hFile, " * return a new %s */\n\n", tableName); - -fprintf(f, "struct %s *%sCommaIn(char **pS, struct %s *ret)\n", - tableName, tableName, tableName); -fprintf(f, "/* Create a %s out of a comma separated string. \n", tableName); -fprintf(f, " * This will fill in ret if non-null, otherwise will\n"); -fprintf(f, " * return a new %s */\n", tableName); -fprintf(f, "{\n"); -fprintf(f, "char *s = *pS;\n"); -fprintf(f, "\n"); -fprintf(f, "if (ret == NULL)\n"); -fprintf(f, " AllocVar(ret);\n"); - -for (col = table->columnList; col != NULL; col = col->next) - { - if (col->isList) - { - fprintf(f, "{\n"); - fprintf(f, "int i;\n"); - fprintf(f, "s = sqlEatChar(s, '{');\n"); - if (col->fixedSize) - { - fprintf(f, "for (i=0; i<%d; ++i)\n", col->fixedSize); - } - else - { - if (!col->obType) - fprintf(f, "AllocArray(ret->%s, ret->%s);\n", col->name, col->linkedSizeName); - fprintf(f, "for (i=0; i%s; ++i)\n", col->linkedSizeName); - } - fprintf(f, " {\n"); - makeCommaInColumn(" ", col, f, col->obType == NULL); - fprintf(f, " }\n"); - if (col->obType) - fprintf(f, "slReverse(&ret->%s);\n", col->name); - fprintf(f, "s = sqlEatChar(s, '}');\n"); - fprintf(f, "s = sqlEatChar(s, ',');\n"); - fprintf(f, "}\n"); - } - else if (col->isArray) - { - fprintf(f, "{\n"); - fprintf(f, "int i;\n"); - fprintf(f, "s = sqlEatChar(s, '{');\n"); - if (col->fixedSize) - { - fprintf(f, "for (i=0; i<%d; ++i)\n", col->fixedSize); - } - else - { - fprintf(f, "AllocArray(ret->%s, ret->%s);\n", col->name, col->linkedSizeName); - fprintf(f, "for (i=0; i%s; ++i)\n", col->linkedSizeName); - } - fprintf(f, " {\n"); - makeCommaInColumn(" ", col, f, TRUE); - fprintf(f, " }\n"); - fprintf(f, "s = sqlEatChar(s, '}');\n"); - fprintf(f, "s = sqlEatChar(s, ',');\n"); - fprintf(f, "}\n"); - } - else - { - makeCommaInColumn("",col, f, FALSE); - } - } -fprintf(f, "*pS = s;\n"); -fprintf(f, "return ret;\n"); -fprintf(f, "}\n\n"); -} - - -boolean objectHasVariableLists(struct asObject *table) -/* Returns TRUE if object has any list members. */ -{ -struct asColumn *col; -for (col = table->columnList; col != NULL; col = col->next) - { - if ((col->isList || col->isArray) && !col->fixedSize) - return TRUE; - } -return FALSE; -} - -boolean objectHasSubObjects(struct asObject *table) -/* Returns TRUE if object has any object members. */ -{ -struct asColumn *col; -for (col = table->columnList; col != NULL; col = col->next) - { - if (col->lowType->type == t_object) - return TRUE; - } -return FALSE; -} - -void staticLoadRow(struct asObject *table, FILE *f, FILE *hFile) -/* Create C code to load a static instance from a row. - * Only generated if no lists... */ -{ -int i; -char *tableName = table->name; -struct asColumn *col; -boolean isSizeLink; -int tfIx; - -if (!withNull) - { - fprintf(hFile, "void %sStaticLoad(char **row, struct %s *ret);\n", tableName, tableName); - } -else - { - fprintf(hFile, "void %sStaticLoadWithNull(char **row, struct %s *ret);\n", tableName, tableName); - } - -fprintf(hFile, "/* Load a row from %s table into ret. The contents of ret will\n", tableName); -fprintf(hFile, " * be replaced at the next call to this function. */\n\n"); - -if (!withNull) - { - fprintf(f, "void %sStaticLoad(char **row, struct %s *ret)\n", tableName, tableName); - } -else - { - fprintf(f, "void %sStaticLoadWithNull(char **row, struct %s *ret)\n", tableName, tableName); - } -fprintf(f, "/* Load a row from %s table into ret. The contents of ret will\n", tableName); -fprintf(f, " * be replaced at the next call to this function. */\n"); -fprintf(f, "{\n"); -fprintf(f, "\n"); -for (tfIx = 0; tfIx < 2; ++tfIx) - { - isSizeLink = trueFalse[tfIx]; - for (i=0,col = table->columnList; col != NULL; col = col->next, ++i) - { - loadColumn(col, i, FALSE, isSizeLink, f); - } - } -fprintf(f, "}\n\n"); -} - -void dynamicLoadRow(struct asObject *table, FILE *f, FILE *hFile) -/* Create C code to load an instance from a row into dynamically - * allocated memory. */ -{ -int i; -char *tableName = table->name; -struct asColumn *col; -boolean isSizeLink; -int tfIx; - -if (!withNull) - { - fprintf(hFile, "struct %s *%sLoad(char **row);\n", tableName, tableName); - } -else - { - fprintf(hFile, "struct %s *%sLoadWithNull(char **row);\n", tableName, tableName); - } - -fprintf(hFile, "/* Load a %s from row fetched with select * from %s\n", tableName, tableName); -fprintf(hFile, " * from database. Dispose of this with %sFree(). */\n\n", tableName); - -if (!withNull) - { - fprintf(f, "struct %s *%sLoad(char **row)\n", tableName, tableName); - } -else - { - fprintf(f, "struct %s *%sLoadWithNull(char **row)\n", tableName, tableName); - } - -fprintf(f, "/* Load a %s from row fetched with select * from %s\n", tableName, tableName); -fprintf(f, " * from database. Dispose of this with %sFree(). */\n", tableName); -fprintf(f, "{\n"); -fprintf(f, "struct %s *ret;\n", tableName); -fprintf(f, "\n"); -fprintf(f, "AllocVar(ret);\n"); -for (tfIx = 0; tfIx < 2; ++tfIx) - { - isSizeLink = trueFalse[tfIx]; - for (i=0,col = table->columnList; col != NULL; col = col->next, ++i) - { - loadColumn(col, i, TRUE, isSizeLink, f); - } - } -fprintf(f, "return ret;\n"); -fprintf(f, "}\n\n"); -} - -void dynamicLoadAll(struct asObject *table, FILE *f, FILE *hFile) -/* Create C code to load a all objects from a tab separated file. */ -{ -char *tableName = table->name; - -fprintf(hFile, "struct %s *%sLoadAll(char *fileName);\n", tableName, tableName); -fprintf(hFile, "/* Load all %s from whitespace-separated file.\n", tableName); -fprintf(hFile, " * Dispose of this with %sFreeList(). */\n\n", tableName); - -fprintf(f, "struct %s *%sLoadAll(char *fileName) \n", tableName, tableName); -fprintf(f, "/* Load all %s from a whitespace-separated file.\n", tableName); -fprintf(f, " * Dispose of this with %sFreeList(). */\n", tableName); -fprintf(f, "{\n"); -fprintf(f, "struct %s *list = NULL, *el;\n", tableName); -fprintf(f, "struct lineFile *lf = lineFileOpen(fileName, TRUE);\n"); -fprintf(f, "char *row[%d];\n", slCount(table->columnList)); -fprintf(f, "\n"); -fprintf(f, "while (lineFileRow(lf, row))\n"); -fprintf(f, " {\n"); -if (!withNull) - { - fprintf(f, " el = %sLoad(row);\n", tableName); - } -else - { - fprintf(f, " el = %sLoadWithNull(row);\n", tableName); - } - -fprintf(f, " slAddHead(&list, el);\n"); -fprintf(f, " }\n"); -fprintf(f, "lineFileClose(&lf);\n"); -fprintf(f, "slReverse(&list);\n"); -fprintf(f, "return list;\n"); -fprintf(f, "}\n\n"); -} - -void dynamicLoadAllByChar(struct asObject *table, FILE *f, FILE *hFile) -/* Create C code to load a all objects from a tab separated file. */ -{ -char *tableName = table->name; - -fprintf(hFile, "struct %s *%sLoadAllByChar(char *fileName, char chopper);\n", tableName, tableName); -fprintf(hFile, "/* Load all %s from chopper separated file.\n", tableName); -fprintf(hFile, " * Dispose of this with %sFreeList(). */\n\n", tableName); - -fprintf(hFile, "#define %sLoadAllByTab(a) %sLoadAllByChar(a, '\\t');\n", tableName, tableName); -fprintf(hFile, "/* Load all %s from tab separated file.\n", tableName); -fprintf(hFile, " * Dispose of this with %sFreeList(). */\n\n", tableName); - -fprintf(f, "struct %s *%sLoadAllByChar(char *fileName, char chopper) \n", tableName, tableName); -fprintf(f, "/* Load all %s from a chopper separated file.\n", tableName); -fprintf(f, " * Dispose of this with %sFreeList(). */\n", tableName); -fprintf(f, "{\n"); -fprintf(f, "struct %s *list = NULL, *el;\n", tableName); -fprintf(f, "struct lineFile *lf = lineFileOpen(fileName, TRUE);\n"); -fprintf(f, "char *row[%d];\n", slCount(table->columnList)); -fprintf(f, "\n"); -fprintf(f, "while (lineFileNextCharRow(lf, chopper, row, ArraySize(row)))\n"); -fprintf(f, " {\n"); -if (!withNull) - { - fprintf(f, " el = %sLoad(row);\n", tableName); - } -else - { - fprintf(f, " el = %sLoadWithNull(row);\n", tableName); - } -fprintf(f, " slAddHead(&list, el);\n"); -fprintf(f, " }\n"); -fprintf(f, "lineFileClose(&lf);\n"); -fprintf(f, "slReverse(&list);\n"); -fprintf(f, "return list;\n"); -fprintf(f, "}\n\n"); -} - -void dynamicLoadByQueryPrintPrototype(char *tableName, FILE *f, boolean addSemi) -/* Print out function prototype and opening comment. */ -{ -fprintf(f, - "struct %s *%sLoadByQuery(struct sqlConnection *conn, char *query)%s\n", - tableName, tableName, - (addSemi ? ";" : "")); -fprintf(f, "/* Load all %s from table that satisfy the query given. \n", tableName); -fprintf(f, " * Where query is of the form 'select * from example where something=something'\n"); -fprintf(f, " * or 'select example.* from example, anotherTable where example.something = \n"); -fprintf(f, " * anotherTable.something'.\n"); -fprintf(f, " * Dispose of this with %sFreeList(). */\n", tableName); -} - -void dynamicLoadByQuery(struct asObject *table, FILE *f, FILE *hFile) -/* Create C code to build a list from a query to database. */ -{ -char *tableName = table->name; -dynamicLoadByQueryPrintPrototype(tableName, hFile, TRUE); -fprintf(hFile, "\n"); -dynamicLoadByQueryPrintPrototype(tableName, f, FALSE); -fprintf(f, "{\n"); -fprintf(f, "struct %s *list = NULL, *el;\n", tableName); -fprintf(f, "struct sqlResult *sr;\n"); -fprintf(f, "char **row;\n"); -fprintf(f, "\n"); -fprintf(f, "sr = sqlGetResult(conn, query);\n"); -fprintf(f, "while ((row = sqlNextRow(sr)) != NULL)\n"); -fprintf(f, " {\n"); -if (!withNull) - { - fprintf(f, " el = %sLoad(row);\n", tableName); - } -else - { - fprintf(f, " el = %sLoadWithNull(row);\n", tableName); - } - -fprintf(f, " slAddHead(&list, el);\n"); -fprintf(f, " }\n"); -fprintf(f, "slReverse(&list);\n"); -fprintf(f, "sqlFreeResult(&sr);\n"); -fprintf(f, "return list;\n"); -fprintf(f, "}\n\n"); -} - -void dynamicSaveToDbPrintPrototype(char *tableName, FILE *f, boolean addSemi) -/* Print out function prototype and opening comment. */ -{ -fprintf(f, - "void %sSaveToDb(struct sqlConnection *conn, struct %s *el, char *tableName, int updateSize)%s\n", - tableName, tableName, (addSemi ? ";" : "")); -fprintf(f, - "/* Save %s as a row to the table specified by tableName. \n", tableName); -fprintf(f, " * As blob fields may be arbitrary size updateSize specifies the approx size\n"); -fprintf(f, " * of a string that would contain the entire query. Arrays of native types are\n"); -fprintf(f, " * converted to comma separated strings and loaded as such, User defined types are\n"); -fprintf(f, " * inserted as NULL. Note that strings must be escaped to allow insertion into the database.\n"); -fprintf(f, " * For example \"autosql's features include\" --> \"autosql\\'s features include\" \n"); -fprintf(f, " * If worried about this use %sSaveToDbEscaped() */\n", tableName); -} - -boolean lastArrayType(struct asColumn *colList) -/* if there are any more string types returns TRUE else returns false */ -{ -struct asColumn *col; -for(col = colList; col != NULL; col = col->next) - { - struct asTypeInfo *lt = col->lowType; - enum asTypes type = lt->type; - if((col->isArray || col->isList) && type != t_object && type != t_simple) - return FALSE; - } -return TRUE; -} - -boolean noMoreColumnsToInsert(struct asColumn *colList) -{ -struct asColumn *col; -for(col = colList; col != NULL; col = col->next) - { - if(col->obType == NULL) - return FALSE; - } -return TRUE; -} - -void dynamicSaveToDb(struct asObject *table, FILE *f, FILE *hFile) -/* create C code that will save a table structure to the database */ -{ -char *tableName = table->name; -struct asColumn *col; -struct dyString *colInsert = newDyString(1024); /* code to associate columns with printf format characters the insert statement */ -struct dyString *stringDeclarations = newDyString(1024); /* code to declare necessary strings */ -struct dyString *stringFrees = newDyString(1024); /* code to free necessary strings */ -struct dyString *update = newDyString(1024); /* code to do the update statement itself */ -struct dyString *stringArrays = newDyString(1024); /* code to convert arrays to strings */ -boolean hasArray = FALSE; -dynamicSaveToDbPrintPrototype(tableName, hFile, TRUE); -fprintf(hFile, "\n"); -dynamicSaveToDbPrintPrototype(tableName, f, FALSE); -fprintf(f, "{\n"); -fprintf(f, "struct dyString *update = newDyString(updateSize);\n"); -dyStringPrintf(update, "dyStringPrintf(update, \"insert into %%s values ( "); -dyStringPrintf(stringDeclarations, "char "); -for (col = table->columnList; col != NULL; col = col->next) - { - char *colName = col->name; - char *outString = NULL; /* printf formater for column, i.e. %d for int, '%s' for string */ - struct asTypeInfo *lt = col->lowType; - enum asTypes type = lt->type; - char colInsertBuff[256]; /* what variable name matches up with the printf format character in outString */ - boolean colInsertFlag = TRUE; /* if column is not a native type insert NULL with no associated variable */ - switch(type) - { - case t_char: - outString = (col->fixedSize > 0) ? "'%s'" : "'%c'"; - break; - case t_string: - outString = "'%s'"; - break; - default: - outString = lt->outFormat; - break; - } - - switch(type) - { - case t_char: - case t_string: - case t_lstring: - sprintf(colInsertBuff, " el->%s", colName); - break; - default: - if (withNull) - sprintf(colInsertBuff, " *(el->%s)", colName); - else - sprintf(colInsertBuff, " el->%s", colName); - break; - } - - /* it gets pretty ugly here as we have to handle arrays of objects.. */ - if(col->isArray || col->isList || type == t_object || type == t_simple) - { - /* if we have a basic array type convert it to a string representation and insert into db */ - if(type != t_object && type != t_simple ) - { - hasArray = TRUE; - outString = "'%s'"; - /* if this is the last array put a semi otherwise a comment */ - if(lastArrayType(col->next)) - dyStringPrintf(stringDeclarations, " *%sArray;", colName); - else - dyStringPrintf(stringDeclarations, " *%sArray,", colName); - /* set up call to convert array to char * */ - if(col->fixedSize) - dyStringPrintf(stringArrays, "%sArray = sql%sArrayToString(el->%s, %d);\n", - colName, lt->listyName, colName, col->fixedSize); - else - dyStringPrintf(stringArrays, "%sArray = sql%sArrayToString(el->%s, el->%s);\n", - colName, lt->listyName, colName, col->linkedSizeName); - /* code to free allocated strings */ - dyStringPrintf(stringFrees, "freez(&%sArray);\n", colName); - sprintf(colInsertBuff, " %sArray ", colName); - } - /* if we have an object, or simple data type just insert NULL, - * don't wrap the whole thing up into one string.*/ - else - { - warn("The user defined type \"%s\" in table \"%s\" will be saved to the database as NULL.", - col->obType->name, tableName); - outString = " NULL "; - colInsertFlag = FALSE; - } - } - /* can't have a comma at the end of the list */ - if(col->next == NULL) - dyStringPrintf(update, "%s", outString); - else - dyStringPrintf(update, "%s,",outString); - - /* if we still have more columns to insert add a comma */ - if(!noMoreColumnsToInsert(col->next)) - strcat(colInsertBuff, ", "); - - /* if we have a column to append do so */ - if(colInsertFlag) - dyStringPrintf(colInsert, "%s", colInsertBuff); - } -if(hasArray) - { - fprintf(f, "%s\n", stringDeclarations->string); - } -fprintf(f, "%s", stringArrays->string); -fprintf(f, "%s", update->string); -fprintf(f, ")\", \n\ttableName, "); -fprintf(f, "%s);\n", colInsert->string); -fprintf(f, "sqlUpdate(conn, update->string);\n"); -fprintf(f, "freeDyString(&update);\n"); -if(hasArray) - { - fprintf(f, "%s", stringFrees->string); - } -fprintf(f, "}\n\n"); -dyStringFree(&colInsert); -dyStringFree(&stringDeclarations); -dyStringFree(&stringFrees); -dyStringFree(&update); -} - -void dynamicSaveToDbEscapedPrintPrototype(char *tableName, FILE *f, boolean addSemi) -/* Print out function prototype and opening comment. */ -{ -fprintf(f, - "void %sSaveToDbEscaped(struct sqlConnection *conn, struct %s *el, char *tableName, int updateSize)%s\n", - tableName, tableName, (addSemi ? ";" : "")); -fprintf(f, - "/* Save %s as a row to the table specified by tableName. \n", tableName); -fprintf(f, " * As blob fields may be arbitrary size updateSize specifies the approx size.\n"); -fprintf(f, " * of a string that would contain the entire query. Automatically \n"); -fprintf(f, " * escapes all simple strings (not arrays of string) but may be slower than %sSaveToDb().\n", tableName); -fprintf(f, " * For example automatically copies and converts: \n"); -fprintf(f, " * \"autosql's features include\" --> \"autosql\\'s features include\" \n"); -fprintf(f, " * before inserting into database. */ \n"); -} - -boolean lastStringType(struct asColumn *colList) -/* if there are any more string types returns TRUE else returns false */ -{ -struct asColumn *col; -for(col = colList; col != NULL; col = col->next) - { - struct asTypeInfo *lt = col->lowType; - enum asTypes type = lt->type; - if(type == t_char || type == t_string || type == t_lstring || ((col->isArray || col->isList) && type != t_object && type != t_simple)) - return FALSE; - } -return TRUE; -} - -void dynamicSaveToDbEscaped(struct asObject *table, FILE *f, FILE *hFile) -/* create C code that will save a table structure to the database with - * all strings escaped. */ -{ -char *tableName = table->name; -struct asColumn *col; -/* We need to do a lot of things with the string datatypes use - * these buffers to only cycle through columns once */ -struct dyString *colInsert = newDyString(1024); /* code to associate columns with printf format characters the insert statement */ -struct dyString *stringDeclarations = newDyString(1024); /* code to declare necessary strings */ -struct dyString *stringFrees = newDyString(1024); /* code to free necessary strings */ -struct dyString *update = newDyString(1024); /* code to do the update statement itself */ -struct dyString *stringEscapes = newDyString(1024); /* code to escape strings */ -struct dyString *stringArrays = newDyString(1024); /* code to convert arrays to strings */ -boolean hasString = FALSE; -boolean hasArray = FALSE; -dynamicSaveToDbEscapedPrintPrototype(tableName, hFile, TRUE); -fprintf(hFile, "\n"); -dynamicSaveToDbEscapedPrintPrototype(tableName, f, FALSE); -fprintf(f, "{\n"); -fprintf(f, "struct dyString *update = newDyString(updateSize);\n"); -dyStringPrintf(update, "dyStringPrintf(update, \"insert into %%s values ( "); -dyStringPrintf(stringDeclarations, "char "); - -/* loop through each of the columns and add things appropriately */ -for (col = table->columnList; col != NULL; col = col->next) - { - char *colName = col->name; - char *outString = NULL; /* printf formater for column, i.e. %d for int, '%s' for string */ - struct asTypeInfo *lt = col->lowType; - enum asTypes type = lt->type; - char colInsertBuff[256]; /* what variable name matches up with the printf format character in outString */ - boolean colInsertFlag = TRUE; /* if column is not a native type insert NULL with no associated variable */ - switch(type) - { - case t_char: - case t_string: - case t_lstring: - /* if of string type have to do all the work of declaring, escaping, - * and freeing */ - if(!col->isArray && !col->isList) - { - hasString = TRUE; - outString = "'%s'"; - /* code to escape strings */ - dyStringPrintf(stringEscapes, "%s = sqlEscapeString(el->%s);\n", colName, colName); - /* code to free strings */ - dyStringPrintf(stringFrees, "freez(&%s);\n", colName); - sprintf(colInsertBuff, " %s", colName); - if(lastStringType(col->next)) - dyStringPrintf(stringDeclarations, " *%s;", colName); - else - dyStringPrintf(stringDeclarations, " *%s,", colName); - } - break; - default: - outString = lt->outFormat; - if (withNull) - sprintf(colInsertBuff, " *(el->%s)", colName); - else - sprintf(colInsertBuff, " el->%s", colName); - break; - } - if(col->isArray || col->isList || type == t_object || type == t_simple) - { - /* if we have a basic array type convert it to a string representation and insert into db */ - if(type != t_object && type != t_simple ) - { - hasArray = TRUE; - outString = "'%s'"; - if(lastStringType(col->next) && lastArrayType(col->next)) - dyStringPrintf(stringDeclarations, " *%sArray;", colName); - else - dyStringPrintf(stringDeclarations, " *%sArray,", colName); - if(col->fixedSize) - dyStringPrintf(stringArrays, "%sArray = sql%sArrayToString(el->%s, %d);\n", colName, lt->listyName, colName, col->fixedSize); - else - dyStringPrintf(stringArrays, "%sArray = sql%sArrayToString(el->%s, el->%s);\n", colName, lt->listyName, colName, col->linkedSizeName); - dyStringPrintf(stringFrees, "freez(&%sArray);\n", colName); - sprintf(colInsertBuff, " %sArray ", colName); - } - /* if we have an object, or simple data type just insert NULL, don't wrap the whole thing up into one string.*/ - else - { - warn("The user defined type \"%s\" in table \"%s\" will be saved to the database as NULL.", col->obType->name, tableName); - outString = " NULL "; - colInsertFlag = FALSE; - } - } - /* can't have comma at the end of the insert */ - if(col->next == NULL) - dyStringPrintf(update, "%s", outString); - else - dyStringPrintf(update, "%s,",outString); - - /* if we still have more columns to insert add a comma */ - if(!noMoreColumnsToInsert(col->next)) - strcat(colInsertBuff, ", "); - /* if we have a column to append do so */ - if(colInsertFlag) - dyStringPrintf(colInsert, "%s", colInsertBuff); - } -if(hasString || hasArray) - { - fprintf(f, "%s\n", stringDeclarations->string); - fprintf(f, "%s\n", stringEscapes->string); - } -fprintf(f, "%s", stringArrays->string); -fprintf(f, "%s", update->string); -fprintf(f, ")\", \n\ttableName, "); -fprintf(f, "%s);\n", colInsert->string); -fprintf(f, "sqlUpdate(conn, update->string);\n"); -fprintf(f, "freeDyString(&update);\n"); -if(hasString) - { - fprintf(f, "%s", stringFrees->string); - } -fprintf(f, "}\n\n"); -dyStringFree(&colInsert); -dyStringFree(&stringDeclarations); -dyStringFree(&stringEscapes); -dyStringFree(&stringFrees); -dyStringFree(&update); -} - -boolean internalsNeedFree(struct asObject *table) -/* Return TRUE if the fields of a table contain strings, - * dynamically sized arrays, objects, or anything else that - * needs freeing. */ -{ -struct asColumn *col; -for (col = table->columnList; col != NULL; col = col->next) - { - struct asTypeInfo *lt = col->lowType; - enum asTypes type = lt->type; - struct asObject *obj; - - if ((obj = col->obType) != NULL) - { - if (type == t_object) - return TRUE; - else if (type == t_simple) - { - if (internalsNeedFree(obj)) - return TRUE; - if (col->isArray && !col->fixedSize) - return TRUE; - } - } - else - { - if (col->isList) - { - if (lt->stringy) - return TRUE; - if (!col->fixedSize) - return TRUE; - } - else - { - if (lt->stringy) - return TRUE; - } - } - } -return FALSE; -} - -void printIndent(int spaces, FILE *f, char *format, ...) -/* Write out to file indented by spaces. */ -{ -va_list args; -va_start(args, format); -spaceOut(f, spaces); -vfprintf(f, format, args); -va_end(args); -} - -void freeFields(struct asObject *table, int spaces, FILE *f) -/* Write out code to free fields of a table. */ -{ -struct asColumn *col; -for (col = table->columnList; col != NULL; col = col->next) - { - struct asTypeInfo *lt = col->lowType; - enum asTypes type = lt->type; - char *colName = col->name; - struct asObject *obj; - - if ((obj = col->obType) != NULL) - { - if (type == t_object) - { - printIndent(spaces, f, "%sFreeList(&el->%s);\n", obj->name, colName); - } - else if (type == t_simple) - { - if (internalsNeedFree(obj)) - { - if (col->isArray) - { - if (col->fixedSize) - { - printIndent(spaces, f, "%sFreeInternals(el->%s, ArraySize(el->%s));\n", - obj->name, colName, colName); - } - else - { - printIndent(spaces, f, "%sFreeInternals(el->%s, el->%s);\n", - obj->name, colName, col->linkedSizeName); - printIndent(spaces, f, "freeMem(el->%s);\n", colName); - } - } - else - { - printIndent(spaces, f, "%sFreeInternals(&el->%s, 1);\n", obj->name, colName); - } - } - else - { - if (col->isArray && !col->fixedSize) - { - printIndent(spaces, f, "freeMem(el->%s);\n", colName); - } - } - } - } - else - { - if (col->isList) - { - if (lt->stringy) - { - printIndent(spaces, f, "/* All strings in %s are allocated at once, so only need to free first. */\n", colName); - printIndent(spaces, f, "if (el->%s != NULL)\n", colName); - printIndent(spaces, f, " freeMem(el->%s[0]);\n", colName); - } - if (!col->fixedSize) - { - printIndent(spaces, f, "freeMem(el->%s);\n", colName); - } - } - else - { - if (lt->stringy) - { - printIndent(spaces, f, "freeMem(el->%s);\n", colName); - } - } - } - } -} - -void makeFreeInternals(struct asObject *table, FILE *f, FILE *hFile) -/* Make a function that frees the internal parts if any of a simple object - * (or array of simple objects). */ -{ -char *tableName = table->name; - -fprintf(hFile, "void %sFreeInternals(struct %s *array, int count);\n", tableName, tableName); -fprintf(hFile, "/* Free internals of a simple type %s (one not put on a list). */\n\n", tableName); - -fprintf(f, "void %sFreeInternals(struct %s *array, int count)\n", tableName, tableName); -fprintf(f, "/* Free internals of a simple type %s (one not put on a list). */\n", tableName); -fprintf(f, "{\n"); -fprintf(f, "int i;\n"); -fprintf(f, "for (i=0; iname; - -fprintf(hFile, "void %sFree(struct %s **pEl);\n", tableName, tableName); -fprintf(hFile, "/* Free a single dynamically allocated %s such as created\n", tableName); -fprintf(hFile, " * with %sLoad(). */\n\n", tableName); - -fprintf(f, "void %sFree(struct %s **pEl)\n", tableName, tableName); -fprintf(f, "/* Free a single dynamically allocated %s such as created\n", tableName); -fprintf(f, " * with %sLoad(). */\n", tableName); -fprintf(f, "{\n"); -fprintf(f, "struct %s *el;\n", tableName); -fprintf(f, "\n"); -fprintf(f, "if ((el = *pEl) == NULL) return;\n"); -freeFields(table, 0, f); -fprintf(f, "freez(pEl);\n"); -fprintf(f, "}\n\n"); -} - -void makeFreeList(struct asObject *table, FILE *f, FILE *hFile) -/* Make function that frees a list of dynamically table. */ -{ -char *name = table->name; - -fprintf(hFile, "void %sFreeList(struct %s **pList);\n", name, name); -fprintf(hFile, "/* Free a list of dynamically allocated %s's */\n\n", name); - -fprintf(f, "void %sFreeList(struct %s **pList)\n", name, name); -fprintf(f, "/* Free a list of dynamically allocated %s's */\n", name); -fprintf(f, "{\n"); -fprintf(f, "struct %s *el, *next;\n", name); -fprintf(f, "\n"); -fprintf(f, "for (el = *pList; el != NULL; el = next)\n"); -fprintf(f, " {\n"); -fprintf(f, " next = el->next;\n"); -fprintf(f, " %sFree(&el);\n", name); -fprintf(f, " }\n"); -fprintf(f, "*pList = NULL;\n"); -fprintf(f, "}\n\n"); -} - -void makeArrayColOutput(struct asColumn *col, boolean mightNeedQuotes, - char *outString, char *lineEnd, FILE *f) -/* Make code that prints one array or list column to a tab delimited file. */ -{ -struct asTypeInfo *lt = col->lowType; -struct asObject *obType = col->obType; -char *indent = ""; -fprintf(f, "{\n"); -fprintf(f, "int i;\n"); -if (obType != NULL) - { - fprintf(f, "/* Loading %s list. */\n", obType->name); - fprintf(f, " {\n struct %s *it = el->%s;\n", - obType->name, col->name); - indent = " "; - } -fprintf(f, "%sif (sep == ',') fputc('{',f);\n", indent); -if (col->fixedSize) - fprintf(f, "%sfor (i=0; i<%d; ++i)\n", indent, col->fixedSize); -else - fprintf(f, "%sfor (i=0; i%s; ++i)\n", indent, col->linkedSize->name); -fprintf(f, "%s {\n", indent); -if (lt->type == t_object) - { - fprintf(f, "%s fputc('{',f);\n", indent); - fprintf(f, "%s %sCommaOut(it,f);\n", indent, obType->name); - fprintf(f, "%s it = it->next;\n", indent); - fprintf(f, "%s fputc('}',f);\n", indent); - fprintf(f, "%s fputc(',',f);\n", indent); - } -else if (lt->type == t_simple) - { - fprintf(f, "%s fputc('{',f);\n", indent); - fprintf(f, "%s %sCommaOut(&it[i],f);\n", indent, obType->name); - fprintf(f, "%s fputc('}',f);\n", indent); - fprintf(f, "%s fputc(',',f);\n", indent); - } -else - { - if (mightNeedQuotes) - fprintf(f, "%s if (sep == ',') fputc('\"',f);\n", indent); - fprintf(f, "%s fprintf(f, \"%s\", el->%s[i]);\n", indent, outString, - col->name); - if (mightNeedQuotes) - fprintf(f, "%s if (sep == ',') fputc('\"',f);\n", indent); - fprintf(f, "%s fputc(',', f);\n", indent); - } -fprintf(f, "%s }\n", indent); -fprintf(f, "%sif (sep == ',') fputc('}',f);\n", indent); -if (obType != NULL) - fprintf(f, " }\n"); -fprintf(f, "}\n"); -fprintf(f, "fputc(%s,f);\n", lineEnd); -} - -void makeArrayColJsonOutput(struct asColumn *col, boolean mightNeedQuotes, - char *outString, FILE *f) -/* Make code that prints one array or list column to a tab delimited file. */ -{ -struct asTypeInfo *lt = col->lowType; -struct asObject *obType = col->obType; -char *indent = ""; -fprintf(f, "{\n"); -fprintf(f, "int i;\n"); -if (obType != NULL) - { - fprintf(f, "/* Loading %s list. */\n", obType->name); - fprintf(f, " {\n struct %s *it = el->%s;\n", obType->name, col->name); - indent = " "; - } -fprintf(f, "%sfputc('[',f);\n", indent); -if (col->fixedSize) - fprintf(f, "%sfor (i=0; i<%d; ++i)\n", indent, col->fixedSize); -else - fprintf(f, "%sfor (i=0; i%s; ++i)\n", indent, col->linkedSize->name); -fprintf(f, "%s {\n", indent); -if (lt->type == t_object) - { - fprintf(f, "%s %sJsonOutput(it,f);\n", indent, obType->name); - fprintf(f, "%s it = it->next;\n", indent); - } -else if (lt->type == t_simple) - { - fprintf(f, "%s %sJsonOutput(&it[i],f);\n", indent, obType->name); - } -else - { - if (mightNeedQuotes) - fprintf(f, "%s fputc('\"',f);\n", indent); - fprintf(f, "%s fprintf(f, \"%s\", el->%s[i]);\n", indent, outString, - col->name); - if (mightNeedQuotes) - fprintf(f, "%s fputc('\"',f);\n", indent); - } -if (col->fixedSize) - fprintf(f, "%s if (i<%d)\n", indent, (col->fixedSize)-1); -else - fprintf(f, "%s if (i<(el->%s)-1)\n", indent, col->linkedSize->name); -fprintf(f, "%s%s fputc(',',f);\n", indent, indent); -fprintf(f, "%s }\n", indent); -fprintf(f, "%sfputc(']',f);\n", indent); -if (obType != NULL) - fprintf(f, " }\n"); -fprintf(f, "}\n"); -} - -void makeScalarColOutput(struct asColumn *col, boolean mightNeedQuotes, - char *outString, char *lineEnd, FILE *f) -/* Make code that prints one scalar column to a tab delimited file. */ -{ -struct asTypeInfo *lt = col->lowType; -if (lt->type == t_object) - { - struct asObject *obj = col->obType; - fprintf(f, "if (sep == ',') fputc('{',f);\n"); - fprintf(f, "if(el->%s != NULL)", col->name); - fprintf(f, " %sCommaOut(el->%s,f);\n", obj->name, col->name); - fprintf(f, "if (sep == ',') fputc('}',f);\n"); - fprintf(f, "fputc(%s,f);\n", lineEnd); - } -else if (lt->type == t_simple) - { - struct asObject *obj = col->obType; - fprintf(f, "if (sep == ',') fputc('{',f);\n"); - fprintf(f, "%sCommaOut(&el->%s,f);\n", obj->name, col->name); - fprintf(f, "if (sep == ',') fputc('}',f);\n"); - fprintf(f, "fputc(%s,f);\n", lineEnd); - } -else - { - if (mightNeedQuotes) - fprintf(f, "if (sep == ',') fputc('\"',f);\n"); - if (!withNull) - { - fprintf(f, "fprintf(f, \"%s\", el->%s);\n", outString, - col->name); - } - else - { - if (! ((lt->type == t_string) || (lt->type == t_lstring)) ) - { - fprintf(f, "fprintf(f, \"%s\", *(el->%s));\n", outString, - col->name); - } - else - { - fprintf(f, "fprintf(f, \"%s\", el->%s);\n", outString, - col->name); - } - } - - if (mightNeedQuotes) - fprintf(f, "if (sep == ',') fputc('\"',f);\n"); - fprintf(f, "fputc(%s,f);\n", lineEnd); - } -} - -void makeScalarColJsonOutput(struct asColumn *col, boolean mightNeedQuotes, - char *outString, FILE *f) -/* Make code that prints one scalar column to a tab delimited file. */ -{ -struct asTypeInfo *lt = col->lowType; -if (lt->type == t_object) - { - struct asObject *obj = col->obType; - fprintf(f, "if(el->%s != NULL)", col->name); - fprintf(f, " %sJsonOutput(el->%s,f);\n", obj->name, col->name); - } -else if (lt->type == t_simple) - { - struct asObject *obj = col->obType; - fprintf(f, "%sJsonOutput(&el->%s,f);\n", obj->name, col->name); - } -else - { - if (mightNeedQuotes) - fprintf(f, "fputc('\"',f);\n"); - if (!withNull) - { - fprintf(f, "fprintf(f, \"%s\", el->%s);\n", outString, - col->name); - } - else - { - if (! ((lt->type == t_string) || (lt->type == t_lstring)) ) - { - fprintf(f, "fprintf(f, \"%s\", *(el->%s));\n", outString, - col->name); - } - else - { - fprintf(f, "fprintf(f, \"%s\", el->%s);\n", outString, - col->name); - } - } - - if (mightNeedQuotes) - fprintf(f, "fputc('\"',f);\n"); - } -} - -void makeSymColOutput(struct asColumn *col, char *lineEnd, FILE *f) -/* Make code that prints one symbolic column to a tab delimited file. */ -{ -fprintf(f, "if (sep == ',') fputc('\"',f);\n"); -fprintf(f, "sql%sPrint(f, el->%s, values_%s);\n", - col->lowType->nummyName, col->name, col->name); -fprintf(f, "if (sep == ',') fputc('\"',f);\n"); -fprintf(f, "fputc(%s,f);\n", lineEnd); -} - -void makeSymColJsonOutput(struct asColumn *col, FILE *f) -/* Make code that prints one symbolic column to a tab delimited file. */ -{ -fprintf(f, "fputc('\"',f);\n"); -fprintf(f, "sql%sPrint(f, el->%s, values_%s);\n", - col->lowType->nummyName, col->name, col->name); -fprintf(f, "fputc('\"',f);\n"); -} - -void makeColOutput(struct asColumn *col, FILE *f) -/* Make code that prints one column to a tab delimited file. */ -{ -char *outString = NULL; -struct asTypeInfo *lt = col->lowType; -enum asTypes type = lt->type; -char *lineEnd = (col->next != NULL ? "sep" : "lastSep"); -boolean mightNeedQuotes = FALSE; - -switch(type) - { - case t_char: - outString = (col->fixedSize > 0) ? "%s" : "%c"; - mightNeedQuotes = TRUE; - break; - case t_string: - case t_lstring: - outString = "%s"; - mightNeedQuotes = TRUE; - break; - default: - outString = lt->outFormat; - break; - } - -if (col->isList || col->isArray) - makeArrayColOutput(col, mightNeedQuotes, outString, lineEnd, f); -else if ((lt->type == t_enum) || (lt->type == t_set)) - makeSymColOutput(col, lineEnd, f); -else - makeScalarColOutput(col, mightNeedQuotes, outString, lineEnd, f); -} - -void makeColJsonOutput(struct asColumn *col, FILE *f) -/* Make code that prints one column to a tab delimited file. */ -{ -char *outString = NULL; -struct asTypeInfo *lt = col->lowType; -enum asTypes type = lt->type; -boolean mightNeedQuotes = FALSE; - -switch(type) - { - case t_char: - outString = (col->fixedSize > 0) ? "%s" : "%c"; - mightNeedQuotes = TRUE; - break; - case t_string: - case t_lstring: - outString = "%s"; - mightNeedQuotes = TRUE; - break; - default: - outString = lt->outFormat; - break; - } - -fprintf(f, "fputc('\"',f);\n"); -fprintf(f, "fprintf(f,\"%s\");\n", col->name); -fprintf(f, "fputc('\"',f);\n"); -fprintf(f, "fputc(':',f);\n"); -if (col->isList || col->isArray) - makeArrayColJsonOutput(col, mightNeedQuotes, outString, f); -else if ((lt->type == t_enum) || (lt->type == t_set)) - makeSymColJsonOutput(col, f); -else - makeScalarColJsonOutput(col, mightNeedQuotes, outString, f); -} - -void makeOutput(struct asObject *table, FILE *f, FILE *hFile) -/* Make function that prints table to tab delimited file. */ -{ -char *tableName = table->name; -struct asColumn *col; - -fprintf(hFile, - "void %sOutput(struct %s *el, FILE *f, char sep, char lastSep);\n", tableName, tableName); -fprintf(hFile, - "/* Print out %s. Separate fields with sep. Follow last field with lastSep. */\n\n", - tableName); - -fprintf(f, - "void %sOutput(struct %s *el, FILE *f, char sep, char lastSep) \n", tableName, tableName); -fprintf(f, - "/* Print out %s. Separate fields with sep. Follow last field with lastSep. */\n", - tableName); - -fprintf(hFile, - "#define %sTabOut(el,f) %sOutput(el,f,'\\t','\\n');\n", tableName, tableName); -fprintf(hFile, - "/* Print out %s as a line in a tab-separated file. */\n\n", tableName); - -fprintf(hFile, - "#define %sCommaOut(el,f) %sOutput(el,f,',',',');\n", tableName, tableName); -fprintf(hFile, - "/* Print out %s as a comma separated list including final comma. */\n\n", - tableName); - -fprintf(f, "{\n"); -for (col = table->columnList; col != NULL; col = col->next) - makeColOutput(col, f); -fprintf(f, "}\n\n"); -} - -void makeJsonOutput(struct asObject *table, FILE *f, FILE *hFile) -/* Make function that prints table in JSON format. */ -{ -char *tableName = table->name; -struct asColumn *col; - -fprintf(hFile, - "void %sJsonOutput(struct %s *el, FILE *f);\n", tableName, tableName); -fprintf(hFile, "/* Print out %s in JSON format. */\n\n", tableName); - -fprintf(f, - "void %sJsonOutput(struct %s *el, FILE *f) \n", tableName, tableName); -fprintf(f, "/* Print out %s in JSON format. */\n", tableName); - -fprintf(f, "{\n"); -fprintf(f, "fputc('{',f);\n"); -for (col = table->columnList; col != NULL; col = col->next) - { - makeColJsonOutput(col, f); - if (col->next != NULL) - fprintf(f, "fputc(',',f);\n"); - } -fprintf(f, "fputc('}',f);\n"); -fprintf(f, "}\n\n"); -} - -void makeDjangoOutput(struct asObject *table, FILE *f, FILE *hFile) -/* Make function that prints table as django model in Python code */ -{ -char *tableName = table->name; -struct asColumn *col; - -fprintf(hFile, - "void %sDjangoOutput(struct %s *el, FILE *f);\n", tableName, tableName); -fprintf(hFile, "/* Print out %s as Django model in python. */\n\n", tableName); - -fprintf(f, - "void %sDjangoOutput(struct %s *el, FILE *f) \n", tableName, tableName); -fprintf(f, "/* Print out %s as Django model in python. */\n\n", tableName); - -fprintf(f, "{\n"); -fprintf(f, "fputc('{',f);\n"); -for (col = table->columnList; col != NULL; col = col->next) - { - fprintf(f, "/* TBD %s */\n", col->name); - // makeColJsonOutput(col, f); - if (col->next != NULL) - fprintf(f, "fputc(',',f);\n"); - } -fprintf(f, "fputc('}',f);\n"); -fprintf(f, "}\n\n"); -} - -void cSymColumnDef(struct asColumn *col, FILE *cFile) -/* output definition used for parsing and formating a symbolic column field */ -{ -struct slName *val; -fprintf(cFile, "/* definitions for %s column */\n", col->name); -fprintf(cFile, "static char *values_%s[] = {", col->name); -for (val = col->values; val != NULL; val = val->next) - fprintf(cFile, "\"%s\", ", val->name); -fprintf(cFile, "NULL};\n"); -fprintf(cFile, "static struct hash *valhash_%s = NULL;\n\n", col->name); -} - -void cSymColumnDefs(struct asObject *obj, FILE *cFile) -/* output definitions used for parsing and formating a symbolic column fields */ -{ -struct asColumn *col; -for (col = obj->columnList; col != NULL; col = col->next) - { - if ((col->lowType->type == t_enum) || (col->lowType->type == t_set)) - cSymColumnDef(col, cFile); - } -} - -void genObjectCode(struct asObject *obj, boolean doDbLoadAndSave, - FILE *cFile, FILE *hFile, FILE *sqlFile, FILE *djangoFile) -/* output code for one object */ -{ -cTable(obj, hFile); -cSymColumnDefs(obj, cFile); - -if (obj->isTable) - { - sqlTable(obj, sqlFile); - if (makeDjango) - djangoModel(obj, djangoFile); - if (!objectHasVariableLists(obj) && !objectHasSubObjects(obj)) - staticLoadRow(obj, cFile, hFile); - if(doDbLoadAndSave) - { - dynamicLoadByQuery(obj, cFile, hFile); - dynamicSaveToDb(obj, cFile, hFile); - dynamicSaveToDbEscaped(obj, cFile, hFile); - } - } -dynamicLoadRow(obj, cFile, hFile); -dynamicLoadAll(obj, cFile, hFile); -dynamicLoadAllByChar(obj, cFile, hFile); -makeCommaIn(obj, cFile, hFile); -/*if (makeJson) - makeJsonInput(obj, cFile, hFile);*/ - -if (obj->isSimple) - { - if (internalsNeedFree(obj)) - makeFreeInternals(obj, cFile, hFile); - } -else - { - makeFree(obj, cFile, hFile); - makeFreeList(obj, cFile, hFile); - } -makeOutput(obj, cFile, hFile); -if (makeJson) - makeJsonOutput(obj, cFile, hFile); -verbose(2, "Made %s object\n", obj->name); -} - - -int main(int argc, char *argv[]) -{ -struct asObject *objList, *obj; -char *outRoot, outTail[256]; -char dotC[256]; -char dotH[256]; -char dotSql[256]; -char dotDjango[256]; -FILE *cFile; -FILE *hFile; -FILE *sqlFile; -FILE *djangoFile = NULL; -char defineName[256]; -boolean doDbLoadAndSave = FALSE; - -optionInit(&argc, argv, optionSpecs); -doDbLoadAndSave = optionExists("dbLink"); -withNull = optionExists("withNull"); -makeJson = optionExists("json"); -makeDjango = optionExists("django"); - -if (argc != 3) - usage(); - -objList = asParseFile(argv[1]); -outRoot = argv[2]; -/* don't embed directories in files */ -splitPath(outRoot, NULL, outTail, NULL); - -safef(dotC, sizeof(dotC), "%s.c", outRoot); -cFile = mustOpen(dotC, "w"); -safef(dotH, sizeof(dotH), "%s.h", outRoot); -hFile = mustOpen(dotH, "w"); -safef(dotSql, sizeof(dotSql), "%s.sql", outRoot); -sqlFile = mustOpen(dotSql, "w"); -if (makeDjango) - { - safef(dotDjango, sizeof(dotDjango), "%s.django", outRoot); - djangoFile = mustOpen(dotDjango, "w"); - } - -/* Print header comment in all files. */ -fprintf(hFile, - "/* %s.h was originally generated by the autoSql program, which also \n" - " * generated %s.c and %s.sql. This header links the database and\n" - " * the RAM representation of objects. */\n\n", - outTail, outTail, outTail); -fprintf(cFile, - "/* %s.c was originally generated by the autoSql program, which also \n" - " * generated %s.h and %s.sql. This module links the database and\n" - " * the RAM representation of objects. */\n\n", - outTail, outTail, outTail); -fprintf(sqlFile, - "# %s.sql was originally generated by the autoSql program, which also \n" - "# generated %s.c and %s.h. This creates the database representation of\n" - "# an object which can be loaded and saved from RAM in a fairly \n" - "# automatic way.\n", - outTail, outTail, outTail); -if (makeDjango) - { - fprintf(djangoFile, - "# %s.python was originally generated by the autoSql program, which also \n" - "# generated %s.sql %s.c and %s.h. This creates the database representation of\n" - "# an object which can be loaded and saved from RAM in a fairly \n" - "# automatic way.\n\n", - outTail, outTail, outTail, outTail); - } - -/* Bracket H file with definition that keeps it from being included twice. */ -sprintf(defineName, "%s_H", outTail); -touppers(defineName); -fprintf(hFile, "#ifndef %s\n", defineName); -fprintf(hFile, "#define %s\n\n", defineName); -if(doDbLoadAndSave) - { - fprintf(hFile, "#include \"jksql.h\"\n"); - } - -/* Put the usual includes in .c file, and also include .h file we are - * generating. */ -fprintf(cFile, "#include \"common.h\"\n"); -fprintf(cFile, "#include \"linefile.h\"\n"); -fprintf(cFile, "#include \"dystring.h\"\n"); -fprintf(cFile, "#include \"jksql.h\"\n"); -fprintf(cFile, "#include \"%s\"\n", dotH); -fprintf(cFile, "\n"); -fprintf(cFile, "\n"); - -/* Also generate imports for django. */ -if (makeDjango) - { - fprintf(djangoFile, "import datetime\n"); - fprintf(djangoFile, "from django.db import models\n\n"); - } - -/* Process each object in specification file and output to .c, - * .h, and .sql and even Django/Python. */ -for (obj = objList; obj != NULL; obj = obj->next) - genObjectCode(obj, doDbLoadAndSave, cFile, hFile, sqlFile, djangoFile); - -fprintf(cFile, "/* -------------------------------- End autoSql Generated Code -------------------------------- */\n\n"); -fprintf(hFile, "/* -------------------------------- End autoSql Generated Code -------------------------------- */\n\n"); -if (makeDjango) - fprintf(djangoFile, "###################### End autoSql Generated Code ######################\n\n"); -/* Finish off H file bracket. */ -fprintf(hFile, "#endif /* %s */\n\n", defineName); -return 0; -} -