int OGRAVCLayer::AppendTableDefinition( AVCTableDef *psTableDef ) { for( int iField = 0; iField < psTableDef->numFields; iField++ ) { AVCFieldInfo *psFInfo = psTableDef->pasFieldDef + iField; char szFieldName[128]; /* Strip off white space */ strcpy( szFieldName, psFInfo->szName ); if( strstr(szFieldName," ") != NULL ) *(strstr(szFieldName," ")) = '\0'; OGRFieldDefn oFDefn( szFieldName, OFTInteger ); if( psFInfo->nIndex < 0 ) continue; // Skip FNODE#, TNODE#, LPOLY# and RPOLY# from AAT table. if( eSectionType == AVCFileARC && iField < 4 ) continue; oFDefn.SetWidth( psFInfo->nFmtWidth ); if( psFInfo->nType1 * 10 == AVC_FT_DATE || psFInfo->nType1 * 10 == AVC_FT_CHAR ) oFDefn.SetType( OFTString ); else if( psFInfo->nType1 * 10 == AVC_FT_FIXINT || psFInfo->nType1 * 10 == AVC_FT_BININT ) oFDefn.SetType( OFTInteger ); else if( psFInfo->nType1 * 10 == AVC_FT_FIXNUM || psFInfo->nType1 * 10 == AVC_FT_BINFLOAT ) { oFDefn.SetType( OFTReal ); if( psFInfo->nFmtPrec > 0 ) oFDefn.SetPrecision( psFInfo->nFmtPrec ); } poFeatureDefn->AddFieldDefn( &oFDefn ); } return TRUE; }
OGRLayer * OGRCouchDBDataSource::ExecuteSQLStats( const char *pszSQLCommand ) { swq_select sSelectInfo; if( sSelectInfo.preparse( pszSQLCommand ) != CE_None ) { return NULL; } if (sSelectInfo.table_count != 1) { return NULL; } swq_table_def *psTableDef = &sSelectInfo.table_defs[0]; if( psTableDef->data_source != NULL ) { return NULL; } OGRCouchDBLayer* _poSrcLayer = (OGRCouchDBLayer* )GetLayerByName( psTableDef->table_name ); if (_poSrcLayer == NULL) { return NULL; } if (_poSrcLayer->GetLayerType() != COUCHDB_TABLE_LAYER) return NULL; OGRCouchDBTableLayer* poSrcLayer = (OGRCouchDBTableLayer* ) _poSrcLayer; int nFieldCount = poSrcLayer->GetLayerDefn()->GetFieldCount(); swq_field_list sFieldList; memset( &sFieldList, 0, sizeof(sFieldList) ); sFieldList.table_count = sSelectInfo.table_count; sFieldList.table_defs = sSelectInfo.table_defs; sFieldList.count = 0; sFieldList.names = static_cast<char **>( CPLMalloc( sizeof(char *) * nFieldCount )); sFieldList.types = static_cast<swq_field_type *>( CPLMalloc( sizeof(swq_field_type) * nFieldCount )); sFieldList.table_ids = static_cast<int *>( CPLMalloc( sizeof(int) * nFieldCount )); sFieldList.ids = static_cast<int *>( CPLMalloc( sizeof(int) * nFieldCount )); PointerAutoFree oHolderNames(sFieldList.names); PointerAutoFree oHolderTypes(sFieldList.types); PointerAutoFree oHolderTableIds(sFieldList.table_ids); PointerAutoFree oHolderIds(sFieldList.ids); for( int iField = 0; iField < poSrcLayer->GetLayerDefn()->GetFieldCount(); iField++ ) { OGRFieldDefn *poFDefn=poSrcLayer->GetLayerDefn()->GetFieldDefn(iField); int iOutField = sFieldList.count++; sFieldList.names[iOutField] = (char *) poFDefn->GetNameRef(); if( poFDefn->GetType() == OFTInteger ) sFieldList.types[iOutField] = SWQ_INTEGER; else if( poFDefn->GetType() == OFTReal ) sFieldList.types[iOutField] = SWQ_FLOAT; else if( poFDefn->GetType() == OFTString ) sFieldList.types[iOutField] = SWQ_STRING; else sFieldList.types[iOutField] = SWQ_OTHER; sFieldList.table_ids[iOutField] = 0; sFieldList.ids[iOutField] = iField; } CPLString osLastFieldName; for( int iField = 0; iField < sSelectInfo.result_columns; iField++ ) { swq_col_def *psColDef = sSelectInfo.column_defs + iField; if (psColDef->field_name == NULL) return NULL; if (strcmp(psColDef->field_name, "*") != 0) { if (osLastFieldName.empty()) osLastFieldName = psColDef->field_name; else if (strcmp(osLastFieldName, psColDef->field_name) != 0) return NULL; if (poSrcLayer->GetLayerDefn()->GetFieldIndex(psColDef->field_name) == -1) return NULL; } if (!(psColDef->col_func == SWQCF_AVG || psColDef->col_func == SWQCF_MIN || psColDef->col_func == SWQCF_MAX || psColDef->col_func == SWQCF_COUNT || psColDef->col_func == SWQCF_SUM)) return NULL; if (psColDef->distinct_flag) /* TODO: could perhaps be relaxed */ return NULL; } if (osLastFieldName.empty()) return NULL; /* Normalize field name */ int nIndex = poSrcLayer->GetLayerDefn()->GetFieldIndex(osLastFieldName); osLastFieldName = poSrcLayer->GetLayerDefn()->GetFieldDefn(nIndex)->GetNameRef(); /* -------------------------------------------------------------------- */ /* Finish the parse operation. */ /* -------------------------------------------------------------------- */ if( sSelectInfo.parse( &sFieldList, NULL ) != CE_None ) { return NULL; } if (sSelectInfo.join_defs != NULL || sSelectInfo.where_expr != NULL || sSelectInfo.order_defs != NULL || sSelectInfo.query_mode != SWQM_SUMMARY_RECORD) { return NULL; } for( int iField = 0; iField < sSelectInfo.result_columns; iField++ ) { swq_col_def *psColDef = sSelectInfo.column_defs + iField; if (psColDef->field_index == -1) { if (psColDef->col_func == SWQCF_COUNT) continue; return NULL; } if (psColDef->field_type != SWQ_INTEGER && psColDef->field_type != SWQ_FLOAT) { return NULL; } } const bool bFoundFilter = CPL_TO_BOOL( poSrcLayer->HasFilterOnFieldOrCreateIfNecessary(osLastFieldName)); if( !bFoundFilter ) return NULL; CPLString osURI = "/"; osURI += poSrcLayer->GetName(); osURI += "/_design/ogr_filter_"; osURI += osLastFieldName; osURI += "/_view/filter?reduce=true"; json_object* poAnswerObj = GET(osURI); json_object* poRows = NULL; if (!(poAnswerObj != NULL && json_object_is_type(poAnswerObj, json_type_object) && (poRows = CPL_json_object_object_get(poAnswerObj, "rows")) != NULL && json_object_is_type(poRows, json_type_array))) { json_object_put(poAnswerObj); return NULL; } int nLength = json_object_array_length(poRows); if (nLength != 1) { json_object_put(poAnswerObj); return NULL; } json_object* poRow = json_object_array_get_idx(poRows, 0); if (!(poRow && json_object_is_type(poRow, json_type_object))) { json_object_put(poAnswerObj); return NULL; } json_object* poValue = CPL_json_object_object_get(poRow, "value"); if (!(poValue != NULL && json_object_is_type(poValue, json_type_object))) { json_object_put(poAnswerObj); return NULL; } json_object* poSum = CPL_json_object_object_get(poValue, "sum"); json_object* poCount = CPL_json_object_object_get(poValue, "count"); json_object* poMin = CPL_json_object_object_get(poValue, "min"); json_object* poMax = CPL_json_object_object_get(poValue, "max"); if (poSum != NULL && (json_object_is_type(poSum, json_type_int) || json_object_is_type(poSum, json_type_double)) && poCount != NULL && (json_object_is_type(poCount, json_type_int) || json_object_is_type(poCount, json_type_double)) && poMin != NULL && (json_object_is_type(poMin, json_type_int) || json_object_is_type(poMin, json_type_double)) && poMax != NULL && (json_object_is_type(poMax, json_type_int) || json_object_is_type(poMax, json_type_double)) ) { double dfSum = json_object_get_double(poSum); int nCount = json_object_get_int(poCount); double dfMin = json_object_get_double(poMin); double dfMax = json_object_get_double(poMax); json_object_put(poAnswerObj); //CPLDebug("CouchDB", "sum=%f, count=%d, min=%f, max=%f", // dfSum, nCount, dfMin, dfMax); OGRFeatureDefn* poFeatureDefn = new OGRFeatureDefn(poSrcLayer->GetName()); poFeatureDefn->Reference(); for( int iField = 0; iField < sSelectInfo.result_columns; iField++ ) { swq_col_def *psColDef = sSelectInfo.column_defs + iField; OGRFieldDefn oFDefn( "", OFTInteger ); if( psColDef->field_alias != NULL ) { oFDefn.SetName(psColDef->field_alias); } else { const swq_operation *op = swq_op_registrar::GetOperator( (swq_op) psColDef->col_func ); oFDefn.SetName( CPLSPrintf( "%s_%s", op->pszName, psColDef->field_name ) ); } if( psColDef->col_func == SWQCF_COUNT ) oFDefn.SetType( OFTInteger ); else if (psColDef->field_type == SWQ_INTEGER) oFDefn.SetType( OFTInteger ); else if (psColDef->field_type == SWQ_FLOAT) oFDefn.SetType( OFTReal ); poFeatureDefn->AddFieldDefn(&oFDefn); } OGRFeature* poFeature = new OGRFeature(poFeatureDefn); for( int iField = 0; iField < sSelectInfo.result_columns; iField++ ) { swq_col_def *psColDef = sSelectInfo.column_defs + iField; switch(psColDef->col_func) { case SWQCF_AVG: if (nCount) poFeature->SetField(iField, dfSum / nCount); break; case SWQCF_MIN: poFeature->SetField(iField, dfMin); break; case SWQCF_MAX: poFeature->SetField(iField, dfMax); break; case SWQCF_COUNT: poFeature->SetField(iField, nCount); break; case SWQCF_SUM: poFeature->SetField(iField, dfSum); break; default: break; } } poFeature->SetFID(0); OGRCouchDBOneLineLayer* poAnswerLayer = new OGRCouchDBOneLineLayer(); poAnswerLayer->poFeatureDefn = poFeatureDefn; poAnswerLayer->poFeature = poFeature; return poAnswerLayer; } json_object_put(poAnswerObj); return NULL; }